Search code examples
ruby-on-railsmonkeypatching

Monkey patching a core class with business logic with Rails


I have a monkeypatched of ActiveRecord find with some business logic, for example:

# lib/core_extensions/active_record/finder_methods/finder.rb
module ActiveRecord
  module FinderMethods
    def find(*args)
      return super if block_given?  

      #... business logic code =>  my_error_control = true

      raise "My Error" if my_error_control
      retorn = find_with_ids(*args)
    end
  end
end
retorn

I have not seen many examples like this, and this causes me a doubt:

Where should finder.rb be?

In this example, this file is in lib/core_extensions/... but if it contains business logic, I think finder.rb should lives in the folder app/core_extensions/ isn't it?


Edited, after Sergio Answer

things like this, are a bad practice?

# lib/core_extensions/nil_class/image_attributes.rb
# suport for product images attributes
class NilClass
  def main_image(size,evita_video)
    "/images/paperclip_missing/original/missing.png"
  end
end

Solution

  • Where should finder.rb be?

    Ultimately, it doesn't matter. It only matters that this code gets loaded. This mix of patching base libraries and adding business logic there looks like something that MUST be documented thoroughly (in the project's wiki or something like that). And if it is documented, then it doesn't matter. The code is where the documentation says it is.

    That being out of the way, here's a design suggestion:

    when user seeks a Family Family.find(params[family_id],session[:company_id]), this find will compare the company of the family result family.company witht the parameter

    Why not do something like this:

    family = current_company.families.find(params[:family_id])
    

    where current_company can be defined as @current_company ||= Company.find(session[:company_id])

    Here, if this company doesn't have this family, you'll get an exception.

    Same effect*, only without any patching. Much more futureproof. You can even add a couple of rubocop rules to ensure that you never write a naked Family.find.


    * it's not like you add that patch and rest of your code magically acquires super-powers. No. You still have to change all the finders, to pass that company id.