我对rails很陌生,最近我发现我对activerecords has_one关联的理解与它实际的工作方式相反。参考rubyonrails指南中的示例,我想象它是供应商应该持有其account_id,因为我认为强制每个帐户持有其供应商没有意义。
因为我真的不明白为什么,或者只是不同意对象在其他对象中维护它的外键,我不知道什么是正确的rails解决我的简单问题:我有两个对象——document和draft。每个文件都有多个草稿,其中一个被标记为当前草稿。我想象的表格布局是这样的:
table document
id
current_draft_id
table draft
id
document_id
text
我在这里寻找的是类似于has_one关联的东西,但反过来,这样文档就会保存并维护current_draft_id。使用belongs_to不是一个选项,因为它的行为不同。例如,我想要document。Current_draft = new_draft正确更新foreign_key
如何在rails中实现这一点?
—update 1
为了澄清我的问题,请假设草案是当前将不会与created_at和updated_at字段无关,所以作用域不会做。
从表设计的角度来看,在drafts表中添加current字段将是一个奇怪的举动。我还计划将有关发布的草案的信息添加到文档对象中,并且将这些信息乘法到草案表中似乎是一个奇怪的步骤。我喜欢Amesee的想法,但我仍然有一些内在的阻力,类似于在drafts表中添加current列。
我认为Draft
是一个Document
,所以用单表继承来管理这些类可能更有意义。你可以根据汇票的类型来判断它是"当前汇票"。
class CreateDocuments < ActiveRecord::Migration
def change
create_table :documents do |t|
t.string :type
# ...
t.timestamps
end
end
end
和模型。
class Document < ActiveRecord::Base
# ...
end
class Draft < Document
# ...
end
class CurrentDraft < Draft
# ...
end
之后,当草案不再是"当前"时,通过将其type
属性更改为"draft"或"Document"来更新其类型。我认为这是一个更好的解决方案,而不是不断检查对象上的布尔或日期属性,并询问其在应用程序中的任何地方的状态。
如何强制执行哪个草案是"当前"草案?它会是最近创建的吗?最后编辑的那个?我将使当前的草案是草案表的逻辑计算的方面,并找到它的范围,而不是强制一个固定的ID,可能并不总是匹配的逻辑。
class Document < ActiveRecord::Base
has_many :drafts
def current_draft
self.drafts.ordered.first
end
end
class Draft < ActiveRecord::Base
belongs_to :document
scope :all
scope :ordered, order_by(:updated_at)
end
或者,将:current, :boolean, :default => false
字段添加到草稿表中,并且只有一个current为true的子字段。(这个方法的逻辑可以在这里找到一个很好的解释:Rails 3应用程序模型如何确保一次只有一个布尔字段设置为真)
如果您真的想要在父元素中有一个固定的子ID,那么您需要一个具有定义外键的:belongs_to
:
文档表:
id
current_draft_id
模型:
class Document < ActiveRecord::Base
has_many :drafts
belongs_to :current_draft, :class_name => 'Draft', :foreign_key => 'current_draft_id'
end
控制器代码:
@document.current_draft = @draft