Reputation: 1721
I'm trying to write class method my_method (like a validate), that uses code block.
Model contains next code:
class Model < ActiveRecord::Base
include Usable
my_method :arg_1, :arg_2
my_method do |model|
# just for example
if model.attribute.present?
:arg3
else
:arg4
end
end
#...
end
my_method is class method defined in concern:
module Usable
extend ActiveSupport::Concern
# instance methods
def instance_method
self.class.display_attrs
end
# ...
module ClassMethods
# class methods
def display_attrs
@attrs_for_display ||= []
end
def my_method(*attr_names, &block)
attr_names.each do |attr|
attr_data = { attr: attr }
display_attrs << attr_data
end
display_attrs << { attr: block} if block_given?
end
end
end
Instance method @model.instance_method works fine when arguments putted in my_method directly my_method :arg_1, :arg_2
> Model.last.instance_method
=> [{:attr=>:arg_1}, {:attr=>:arg_2}]
But instance_method returns a Proc object when my_method uses block my_method {:arg_3}
> Model.last.instance_method
=>[{:attr=> #<Proc:0x00 ... >}]
How to put in my_method arguments in according of instance state? For example, @model.instance_method
should return :arg_3 if model.attribute.present?
Upvotes: 2
Views: 1073
Reputation: 1721
The problem was solved with call method. I rewrote instance_method as follows:
def instance_method
class_attrs = self.class.display_attrs.map { |n| n[:attr] }
class_blocks = self.class.display_attrs.map { |n| n[:block].call(self) if n[:block] }
(class_attrs + class_blocks).compact!
end
module ClassMethods
#...
display_attrs << { block: block} if block_given?
#...
end
Upvotes: 1