I am just getting my hands on Concerns in Rails and try to implement a simple logging for ActiveRecord classes. In there I want to define the field that should go into the log and have the log written automatically after save.
What I have is this:
#logable.rb (the concern)
module Logable
extend ActiveSupport::Concern
@field = nil
module ClassMethods
def set_log_field(field)
@feild = field
end
end
def print_log
p "LOGGING: #{self[@index.to_s]}"
end
end
#houses.rb (the model using the concern)
class House < ActiveRecord::Base
include Logable
after_save :print_log
set_log_field :id
end
Unfortunately the call to set_log_field does not have an effect - or rather the given value does not make it to print_log. What am I doing wrong?
Thanks for your help!
You probably mean this (btw, why not Loggable
?):
# logable.rb
module Logable
extend ActiveSupport::Concern
# Here we define class-level methods.
# Note, that @field, defined here cannot be referenced as @field from
# instance (it's class level!).
# Note also, in Ruby there is no need to declare @field in the body of a class/module.
class_methods do
def set_log_field(field)
@field = field
end
def log_field
@field
end
end
# Here we define instance methods.
# In order to access class level method (log_field), we use self.class.
included do
def print_log
p "LOGGING: #{self.class.log_field}"
end
end
end
Update You also asked about what's the difference between methods in included
block and those within method body.
To make a short resume there is seemingly no difference. In very good approximation you can consider them the same. The only minor difference is in dependency management. Great illustration of it is given in the end of ActiveSupport::Concern documentation. It worth reading, take a look!