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
CodePudding user response:
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)