开发者

Is there any built-in way to automatically enforce a type/class on an instance variable in Ruby?

开发者 https://www.devze.com 2023-03-17 13:10 出处:网络
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 gett

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消