While surveying ActiveSupport::CurrentAttributes
code I found that rails way of defining singleton class is a little odd or unusual at least.
Rails way:
class RailsWay
attr_reader :attributes
def initialize
@attributes = {}
end
class << self
def instance
@instance ||= new
end
def attribute(*names)
generated_attribute_methods.module_eval do
names.each do |name|
self.define_method(name) do
attributes[name.to_sym]
end
self.define_method("#{name}=") do |value|
attributes[name.to_sym] = value
end
end
end
names.each do |name|
define_singleton_method(name) do
instance.public_send(name)
end
define_singleton_method("#{name}=") do |attribute|
instance.public_send("#{name}=", attribute)
end
end
end
private
def generated_attribute_methods
@generated_attribute_methods ||= Module.new.tap { |mod| include mod }
end
end
end
class Klass < RailsWay
attribute :a, :b
end
Klass.a = "RailsWay"
I am most curious about why use generated_attribute_methods
and define instance methods in Module and then include it at runtime instead of defining them directly in class directly.
Simple/My way:
If we don’t introduce the additional module we can implement it by following:
NOTE: It is based on my current understanding of the code mentioned above, I am not 100% sure if it mirrors the behavior of the above code snippet. Please do educate me, if I am missing anything!
class MyWay
attr_reader :attributes
def initialize
@attributes = {}
end
class << self
def instance
@instance ||= new
end
def attribute(*names)
names.each do |name|
self.define_method(name) do
attributes[name.to_sym]
end
self.define_method("#{name}=") do |value|
attributes[name.to_sym] = value
end
end
names.each do |name|
define_singleton_method(name) do
instance.public_send(name)
end
define_singleton_method("#{name}=") do |attribute|
instance.public_send("#{name}=", attribute)
end
end
end
end
end
class Klass < MyWay
attribute :a, :b
end
Klass.a = "myway"
I know I am missing something here and please do educate us on why the current design was opted! Thank you.
P.S: Rails is an amazing framework!! and thank you rails-core for maintaining it and making web development awesome!