为什么我可以在Ruby类定义中添加随机代码?

时间:2012-05-17 06:51:34

标签: ruby-on-rails ruby ruby-on-rails-3

我正在学习一些Rspec的东西,并不小心将一些代码引入我的模型类中,我希望它会产生错误。但令我惊讶的是没有。

class Address < ActiveRecord::Base
  attr_accessible :city, :country, :person_id, :street, :zip
  validates_presence_of :city, :zip, :street
  before_save :setDefaultCountry

  # -- Beginning strange code --

  if true
     puts "Hey! I shouldn't be able to do this"
  end       

  # -- End of strange code --

  private   
  def setDefaultCountry
    if self.country.blank?
      self.country = "US"
    end
  end
end

这是rails控制台输出:

Arman$ rails console
Loading development environment (Rails 3.2.3)
1.9.3p194 :001 > a = Address.new
Hey! I shouldn't be able to do this
 => #<Address id: nil, street: nil, city: nil, zip: nil, country: nil, person_id: nil, created_at: nil, updated_at: nil> 
1.9.3p194 :002 > 

为什么ruby不抱怨在类定义中添加奇怪的代码?

2 个答案:

答案 0 :(得分:3)

因为class块仅引入了用于执行代码的新上下文。 Ruby是Ruby,而不是C ++ - 不要这样对待它。如果我们想在类定义期间执行一些代码,为什么你认为我们不应该这样做?您可以在其中执行代码 - 在此期间,self将指向代表您的类的Class对象,而不是其类的任何实例。这可以让你获得极大的灵活性,这也是Ruby Monkey-patchable的重要之处(从Rubyists的角度来看,这是一个很好的例子,尽管许多其他人对这种做法不屑一顾)。

答案 1 :(得分:2)

这就是红宝石的作用方式。您不认为attr_accessible会导致错误,是吗?但这只是一个常规方法调用! Here's its source

# File activerecord/lib/active_record/base.rb, line 1083
def attr_accessible(*attributes)
  write_inheritable_attribute(:attr_accessible, 
                              Set.new(attributes.map(&:to_s)) + (accessible_attributes || []))
end

您可以在类定义中运行任意ruby代码。这是一个功能,而不是错误:))