默认情况下,ActiveRecord从相应的数据库表中获取所有字段,并为所有字段创建公共属性。
我认为将模型中的所有属性公开是合理的不。更重要的是,暴露出供内部使用的属性会使模型的界面混乱,并违反封装原则。
那么,有没有办法按字面意思private
制作一些属性?
或者,也许我应该转向其他ORM?
答案 0 :(得分:32)
Jordini大部分都在那里
大多数active_record都发生在method_missing中。如果你预先定义方法,它将不会触及该方法的method_missing,而是使用你的方法(有效覆盖,但不是真的)
class YourModel < ActiveRecord::Base
private
def my_private_attribute
self[:my_private_attribute]
end
def my_private_attribute=(val)
write_attribute :my_private_attribute, val
end
end
答案 1 :(得分:5)
好吧,你总是可以覆盖方法......
class YourModel < ActiveRecord::Base
private
def my_private_attribute
self[:my_private_attribute]
end
def my_private_attribute=(val)
self[:my_private_attribute] = val
end
end
答案 2 :(得分:5)
最近偶然发现了这一点。如果你想私人写作和阅读以及公开阅读这样的话
class YourModel < ActiveRecord::Base
attr_reader :attribute
private
attr_accessor :attribute
end
对我来说似乎很好。您可以使用attr_reader,attr_writer和attr_accessor来决定应该公开什么以及应该私有什么。
答案 3 :(得分:1)
您可以将现有方法设为私有:
YourClass.send(:private, :your_method)
答案 4 :(得分:1)
对我来说,来自Otto和jordinl的方法都运行正常,并使得对象Class的rspec传递:
object.should_not respond_to :attribute
但是当我使用jordinl方法时,我有一个弃用消息,不能直接写入数据库,而是使用attr_writer。
更新:
但真正做到这一点的“正确”方法结果却很简单。感谢MladenJablanović和Christopher Creutzig from here。要使预定义方法成为私有或受保护的...只需重新定义它:
Class Class_name
private :method_name
protected :method_name_1
end
重要的是,您无需重写以前定义的方法的逻辑。
答案 5 :(得分:0)
将设置设为私有会产生ActiveRecord错误。
我通过检查调用者将访问控制代码放在公共setter的覆盖方法中:
def my_private_attribute=(val)
if (caller.first.include?('active_record/base.rb') || caller.first.include?('app/models/myclass.rb'))
self[:my_private_attribute] = val
else
raise Exception.new("Cannot set read-only attribute.")
end
end
答案 6 :(得分:0)
我认为有100%可靠的方法可以做到这一点。它还值得检查最常用的访问属性的方法:
http://www.davidverhasselt.com/set-attributes-in-activerecord/