为什么不能将这个继承的class属性赋值给?

时间:2016-05-12 20:32:12

标签: ruby-on-rails ruby rails-activerecord

我知道在Ruby中,与其他语言不同,有类方法继承。

class A
  def self.filter_by
    "filter"
  end
end

class B < A
end

B.filter_by => "filter"

B的单例类从A的单例类继承方法,它似乎继承了这些类方法的实例变量:

class A
  class << self
    attr_accessor :filter_by
  end
end

class B < A    
end

B.filter_by = "filter"
A.filter_by = "no_filter" 
=> "no_filter" 
B.filter_by # B's value is not changed
=> "filter"

但它没有继承值:

class A
  class << self
    attr_accessor :filter_by
  end
end

class B < A
end

A.filter_by = "filter"
B.filter_by => nil 

B没有继承设置为A的@filter_by实例变量的值。

可以使用内置的继承钩子以this方式解析,或者在Rails中使用class_attribute

class A < ActiveRecord::Base
  class_attribute :filter_by
end
class B < A
end 
A.filter_by = "filter"
 => "filter" 
B.filter_by # Now B's @filter_by inherited the value set in A's @filter_by
 => "filter"

但我不明白为什么我不能这样做:

class A < ActiveRecord::Base
  class_attribute :filter_by
end

class B < A
  filter_by= %w(user_id_is status_id_is task_category_id_is)
end
B.filter_by => nil

为什么在这种情况下它返回nil而在其他情况下不返回?在这种情况下,当我声明B(它是单例对象)时,我在self上设置了一个值。

2 个答案:

答案 0 :(得分:3)

请记住,在上一个示例中,有

  1. 名为filter_by的类属性(包含相应的filter_byfilter_by=方法(继承自A类)
  2. B类中的本地范围变量,名为filter_by
  3. 变量filter_by在范围之外不可用,并且在任何类型的class B方法中也不可用。在class B中,您已将此变量设置为字符串列表,但是当您执行B.filter_by时,将调用从class A继承的方法。此值尚未设置,因此会返回nil

    如果您在课程中完成了self.filter_by = %w(...),那么它就会访问方法filter_by=并按照您的意图设置class属性。

答案 1 :(得分:2)

您在分配属性时忘记了self.。 Ruby认为你分配给了一个本地人。使用self.

修复它
class A < ActiveRecord::Base
  class_attribute :filter_by
end

class B < A
  self.filter_by= %w(user_id_is status_id_is task_category_id_is)
end

B.filter_by => nil
=> ["user_id_is", "status_id_is", "task_category_id_is"]