在这里简化一下,但假设一个具有用户和UserRecords的应用程序。用户必须拥有一个或多个UserRecords。我想将UserRecords的创建限制为User中的方法,即#create_new_user_record。
换句话说,我不想在应用程序的任何其他位置允许UserRecord.new或UserRecords.create。我需要控制这些记录的创建,并围绕它们执行一些逻辑(例如,将新的当前设置和其他任何设置为不是当前的),并且我不希望数据库中有任何孤立的UserRecords。
我尝试了after_initialize回调并检查对象是否是新的并在那里引发错误,但当然我需要在User#create_new_user_record中调用UserRecord.new。如果我能以某种方式在#create_new_user_record中标记我从该方法调用new,并在after_intialize中选择它,那会有效,但是如何?
我可能会过度思考。我当然可以在User上创建一个方法,并且“知道”总是调用它。但是其他人最终会在这个应用程序上工作,我会离开并重新回到它的位置。
我想我可以在#create_new_user_record中提出错误并从中解救。至少,如果另一个开发人员在其他地方尝试它,他们会发现为什么我会在他们追求错误时这样做。
无论如何,想知道这里的Rails大师不得不说些什么。
答案 0 :(得分:1)
super
方法。虽然你需要一些解决方法(可能只是简单检查你知道的选项值)以满足你的需求
class User< ActiveRecord的:基
def .new(attributes = nil, options = {})
do_your_fancy_stuff
if option[:my_secret_new_method]
super # call AR's .new method and automatically pass all the arguments
end
end
答案 1 :(得分:1)
好的,这就是我的所作所为。如果这是一个坏主意,请随时告诉我,或者,如果这是一个好主意,如果有更好的方法。对于它的价值,这确实实现了我的目标。
在User模型的工厂方法中,我在API中的新方法上定义的可选选项哈希中发送自定义参数。然后我在UserRecord #new覆盖中,我检查这个参数。如果是真的,我创建并返回对象,否则我引发自定义错误。
以我的思维方式,以任何其他方式创建UserRecord对象 是一个错误。一个无辜地尝试它的开发人员将导致两种方法中的解释性评论。
我不清楚的一件事是,当我打电话给超级时,为什么我需要省略选项哈希。用它调用super会导致我在之前的评论中发布的ArgumentError。没有它就调用超级似乎工作正常。
class User < ActiveRecord::Base
...
def create_new_user_record
# do fancy stuff here
user_record = UserRecord.new( { owner_id: self.id, is_current: true }, called_from_factory: true )
user_record.save
end
...
end
class UserRecord < ActiveRecord::Base
...
def UserRecord.new(attributes = nil, options = {})
if options[:called_from_factory] == true
super(attributes)
else
raise UseFactoryError, "You must use factory method (User#create_new_user_record) to create UserRecords"
end
end
...
end