Is there any built-in way to automatically enforce a type/class on an instance variable in Ruby?
I'm working with Ruby and Rails, so any Rails extension of Ruby should be fine too.
I'm wondering if there's a way to effectively force a type on instance variables (rather, their setters and getters) that's easier than manually defining them.
The class method attr_accessor
and the like don't enforce a type. I noticed for instance that Rails' ActiveRecord::Base
class does automatic casting on setters. It knows from the database that a particular active 开发者_StackOverflowrecord variable is an integer, and setting it with @record.integer_variable = '1'
automatically casts the argument and allows further access through @record.integer_variable # => 1
.
Is there a way to tap into this?
I could write my own getters and setters as class methods, but if smarter folk have already done the heavy lifting, I'd rather not have to trust myself.
I don't know if there's already something about it, but you can solve this problem with just a few lines of meta-programming:
module EnforceTypes
def attr_accessor_of_type(name, type)
send :define_method, name do
instance_variable_get("@#{name}")
end
send :define_method, "#{name}=" do |v|
raise ArgumentException unless v.is_a? type
instance_variable_set("@#{name}", v)
end
end
end
Usage:
class MyClass
extend EnforceTypes
attr_accessor_of_type :some_string, String
end
Of course you can make it a little smart by changing the 2nd emitted method, performing some conversions, etc.
Here's a nice reference: http://www.raulparolari.com/Ruby2/attr_accessor
And remember, almost anything that you can do by manually copy-and-pasting lots of code, can be solved with meta-programming.
精彩评论