Created
July 25, 2012 13:10
-
-
Save mepatterson/3176111 to your computer and use it in GitHub Desktop.
common refactorings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # NOTES | |
| # - many of my style changes reflect the excellent Github Ruby Style Guide | |
| # https://github.com/styleguide/ruby/ | |
| # - convention for naming Time-based db fields is xxxx_at, Date-based is xxxx_on | |
| # - naming methods find_by_blah_blah_blah is old, Rails 1-ish. Newer convention is just simple names | |
| # and scoping, so you can do things like: user.named('Bob').with_children(2) | |
| # ( as opposed to: user.find_by_name_and_children('Bob', 2) ) | |
| # - don't indent methods after a protected or private call. this is something of a matter of style | |
| # preference, but the most common preference is no indent | |
| # ANTI-PATTERNS / ANTI-CONVENTIONS | |
| if !thing | |
| if other_doodad | |
| a = 4 | |
| end | |
| end | |
| # Unnecessary nesting. Just rewrite as => | |
| a = 4 if !thing && other_doodad | |
| # -------------------------------------------------------- | |
| a = some_method | |
| if !a | |
| a = 4 | |
| end | |
| # Ruby Convention => | |
| a = some_method || 4 | |
| # -------------------------------------------------------- | |
| some_method_that_sets_A_earlier | |
| # ... bunch of extra code | |
| unless a | |
| a = 4 | |
| end | |
| # Ruby Convention => | |
| a ||= 4 | |
| # -------------------------------------------------------- | |
| def whatsit | |
| a = some_method | |
| if a | |
| a.do_something | |
| else | |
| raise "Could not do the thing." | |
| end | |
| end | |
| # Ruby Convention (see `Refactoring Ruby` by Fields/Harvey/Fowler) => | |
| def whatsit | |
| raise "Could not do the thing." unless a = some_method | |
| a.do_something | |
| end | |
| # -------------------------------------------------------- | |
| def whatsit | |
| a = some_method | |
| if a | |
| a.do_something | |
| else | |
| false | |
| end | |
| end | |
| # Ruby Convention (see `Refactoring Ruby` by Fields/Harvey/Fowler) => | |
| def whatsit | |
| return false unless a = some_method | |
| a.do_something | |
| end | |
| # -------------------------------------------------------- | |
| FancyModel.find_by_foo_and_bar(a, b) | |
| FancyModel.find_all_by_foo_and_bar_and_baz(a, b, c) | |
| FancyModel.find_by_id(widget_id) | |
| # Newer Rails Conventions => | |
| # (NOTE: Rails 4 will deprecate find_all_by_* and find_by_* methods!) | |
| FancyModel.where(foo: a, bar: b).first | |
| FancyModel.where(foo: a, bar: b, baz: c) | |
| FancyModel.where(id: widget_id).first | |
| # in the second case, you probably don't want .all() at the end because that will | |
| # cause it to return an array of results, rather than an iteratable query scope, which | |
| # tends to be more useful/performant, especially when the table gets big | |
| # -------------------------------------------------------- | |
| # in a User model method | |
| def find_widgets_by_title_and_platform | |
| Widget.find_all_by_user_and_title_and_platform(self.id, title, platform) | |
| end | |
| # Newer Rails Conventions => | |
| def find_widgets_by_title_and_platform | |
| # you already have an association with widgets on this User class, | |
| # so just use thatand add some additional query restrictions | |
| widgets.where(title: title, platform: platform) | |
| end | |
| # -------------------------------------------------------- | |
| # PROBLEM: cobbling together a big SQL statement by creating two different methods to | |
| # account for the possibility of an optional extra restriction on the query... | |
| # SOLUTION: use one method, and take advantage of scopes and scope-chaining instead: | |
| def get_entitlements(title, args = {}) | |
| scope = self.entitlements. | |
| select('entitlements.string_identifier, entitlements.payload, entitlements.consumable, | |
| user_entitlements.consumable_amount, user_entitlements.consumed, | |
| user_entitlements.id AS user_entitlement_id') | |
| # you're not required to pass args[:platform] to this method, but if you do, this next line | |
| # adds an additional restriction to the final SQL | |
| scope = scope.where(platform: args[:platform]) if args[:platform] | |
| scope = scope.where(title: title).not_fully_consumed | |
| scope | |
| end | |
| # -------------------------------------------------------- | |
| if a == 1 | |
| b = 3 | |
| else | |
| b = 'joe' | |
| end | |
| # this is a good place for a ternary => | |
| b = a == 1 ? 3 : 'joe' | |
| # -------------------------------------------------------- | |
| f = 0 | |
| frogs = Frog.get_the_frogs | |
| if frogs && frogs.count > 0 | |
| f = frogs.count | |
| end | |
| # use the .try() method | |
| # try() returns nil if the method returns nil or false, and can be chained | |
| f = Frog.try(:get_the_frogs).try(:count) || 0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment