Search code examples
ruby-on-railsrubymetaprogramming

class << self in ruby and its methods


I have a model in ruby on rails with the below code, which uses a singelton class definition. Also, som metaprogramming logic. But, I don't understand when this code will invoke.Is it when an attribute below specified is editing?

class Product < ApplicationRecord

    class << self
      ['cat_no', 'effort', 'impact', 'effect', 'feedback'].each do |attr| 
        define_method "update_#{attr}" do |pr, count, user_id|
           pr.order=pr.cat_no     
           pr.idea=pr.description
           pr.update("#{attr}"=>count,:last_modified_by=>user_id)
        end
      end
    end
end

Please help. Thanks


Solution

  • This code generates five methods, one for each attribute name in the list. All these generated methods take three arguments and will basically look like this (I use the impact attribute name as an example):

    def self.update_impact(pr, count, user_id)
      pr.order = pr.cat_no     
      pr.idea = pr.description
      pr.update("impact" => count, :last_modified_by => user_id)
    end
    

    That means there are five methods generated that update the passed in pr with some data from itself and with a count and a user_id.

    Note that this method only deals with a specific pr therefore it is certainly better to use an instance instead of a class method as Stefan already suggested in his comment. And IMO there is not really a benefit in meta-programming here. I would change the logic to

    def update_count(type, count, user_id) # or any another name that makes sense in the domain
      if type.in?(%i[cat_no effort impact effect feedback])
        update(
          :order => cat_no, 
          :idea => description, 
          :last_modified_by => user_id, 
          type => count
        )
      else
        raise ArgumentError, "unsupported type '#type'"
      end
    end
    

    and call it instead of

    Model.update_impact(pr, count, user_id)
    

    like this

    pr.update_count(:impact, count, user_id)