Sometimes you'll find yourself with a set of tasks that require similar code for different models. For example, if you start working at a new application that allows CRUDing pears and apples, each commit might look similar to this:
commit 41e3adef10950b324ae09e308f632bef0dee3f87 (HEAD -> ml/add-apples-12345)
Author: Michael Leimstaedtner <michael.leimstaedtner@acme.com>
Date: Fri Aug 11 09:42:34 2023 +0200
Add Apples as a new fruit
diff --git a/app/models/apple.rb b/app/models/apple.rb
new file mode 100644
index 0000000..a51cbad
--- /dev/null
+++ b/app/models/apple.rb
@@ -0,0 +1,9 @@
+class Apple < Fruit
+ belongs_to :juice, class_name: 'AppleJuice'
+
+ attr_accessor :type
+
+ def to_s
+ I18n.t(type, scope: 'fruits.apples')
+ end
+end
diff --git a/spec/models/apple_spec.rb b/spec/models/apple_spec.rb
new file mode 100644
index 0000000..6b9a90e
--- /dev/null
+++ b/spec/models/apple_spec.rb
@@ -0,0 +1,10 @@
+describe Apple do
+ subject(:apple) { build(:apple) }
+
+ describe '#to_s' do
+ it "humanizes the apple's type" do
+ subject.type = :golden_delicious
+ expect(subject.to_s).to eq('Golden Delicious')
+ end
+ end
+end
Now usually adding pears will be a monotonous job as they provide no big difference in terms of code. You can however use git to speed it up!
A primer on patches
What you see above is a so called patch, generated by git show 41e3ade
. Any diff is a patch, really: for example the output of git diff main
will tell you which patches are required to bring main
to the same state as your current branch (and staged changes).
Patches can be applied. For example, if you want to cherry-pick the "apples" changes to another branch you can do git show 41e3ade | git apply --reject
. Or, a bit more verbose: first write it to a patchfile with git show 41e3ade > apples.patch
, then apply it with git apply --reject apples.patch
. Changes that cannot be applied will result in .rej
files.
Note that this is just a fictional example, you can use git cherry-pick
for this specific use case.
Altering patchfiles to speed up tedious work
As mentioned above, we want to support pears in our application. I suggest you the following:
-
git show 41e3ade > pears.patch
: Write the apple commit to a patchfile - (using your IDE): Search and replace
apple
withpear
,Apple
withPear
etc. -
git apply --reject pears.patch
: Apply the modified patchfile above -
git add -N .
Add new files to git -
git add -p
apply suggested changes and fix necessary differences
Take your time for the last step. For example "Golden Delicious" does not make sense for pears!
A gsubed / modified pears.patch
file could look like this
commit 41e3adef10950b324ae09e308f632bef0dee3f87 (HEAD -> ml/add-pears-12345)
Author: Michael Leimstaedtner <michael.leimstaedtner@acme.com>
Date: Fri Aug 11 09:42:34 2023 +0200
Add Pears as a new fruit
diff --git a/app/models/pear.rb b/app/models/pear.rb
new file mode 100644
index 0000000..a51cbad
--- /dev/null
+++ b/app/models/pear.rb
@@ -0,0 +1,9 @@
+class Pear < Fruit
+ belongs_to :juice, class_name: 'PearJuice'
+
+ attr_accessor :type
+
+ def to_s
+ I18n.t(type, scope: 'fruits.pears')
+ end
+end
diff --git a/spec/models/pear_spec.rb b/spec/models/pear_spec.rb
new file mode 100644
index 0000000..6b9a90e
--- /dev/null
+++ b/spec/models/pear_spec.rb
@@ -0,0 +1,10 @@
+describe Pear do
+ subject(:pear) { build(:pear) }
+
+ describe '#to_s' do
+ it "humanizes the pear's type" do
+ subject.type = :williams
+ expect(subject.to_s).to eq('Williams')
+ end
+ end
+end