使用 Rails 创建嵌套记录
Creating nested records on create with Rails
我有一个项目模型,用于在创建特定项目时自动生成部门。这包含在 projects
模型中:
class Project < ActiveRecord::Base
attr_accessible :title, :departments_attributes, :positions_attributes, :id
belongs_to :user
has_many :departments
has_many :positions
validates :title, presence: true
before_create :set_departments
accepts_nested_attributes_for :departments
accepts_nested_attributes_for :positions
private
def set_departments
self.departments.build department: "Test Dept", production_id: self.id
end
end
每个部门都有很多职位。我也在努力为部门创造职位。我如何将新职位与此模型中的部门相关联?
您可以通过以下方式添加新职位:
Project.first.positions << Position.create(:foo => 'foo', :bar => 'bar')
或
position = Position.create(:foo => 'foo', :bar => 'bar')
Department.first.positions << position
Project.first.positions << position
显然“.first”只是为了说明,您可以对任何部门或项目实例使用 <<
符号。
再看看这个,它似乎非常适合多态关联。
class Position < ActiveRecord::Base
belongs_to :positioned, polymorphic: true
end
class Project < ActiveRecord::Base
has_many :positions, as: :positioned
end
class Department < ActiveRecord::Base
has_many :positions, as: :positioned
end
在您的迁移中:
create_table :positions do |t|
...
t.integer :positioned_id
t.string :positioned_type
...
end
可能有更合适的方式为您的应用命名,但这是一般的想法。
如果我对你的问题的理解正确,你可能会在你的 Department 模型中做这样的事情:
after_create { self.positions.create! }
尽管这可能是一种有问题的方法。使用 ActiveRecord 回调(这给了我们 after_create)创建这样的记录会使您的整个应用程序非常脆弱。例如,如果您这样做,您将永远无法创建一个没有关联职位的部门。也许有一天你需要这样做。
因此,即使这不是您问题的确切答案,我还是建议查看在服务对象中或至少在控制器代码中创建这些关联模型。
有两种方法:
#app/models/project.rb
class Project < ActiveRecord::Base
has_many :departments
accepts_nested_attributes_for :departments
before_create :set_department
private
def set_department
self.departments.build department: "Test"
end
end
#app/models/department.rb
class Department < ActiveRecord::Base
has_many :positions
accepts_nested_attributes_for :positions
before_create :set_positions
private
def set_positions
self.positions.build x: y
end
end
...或...
#app/models/project.rb
class Project < ActiveRecord::Base
has_many :departments
accepts_nested_attributes_for :departments, :projects
before_create :set_departments
private
def set_departments
dpt = self.departments.build department: "Test"
dpt.positions << Position.new position: "Admin"
dpt.positions << Position.new position: "Tester"
end
end
--
您还可以在一行中声明多个嵌套属性:
accepts_nested_attributes_for :departments, :positions
我有一个项目模型,用于在创建特定项目时自动生成部门。这包含在 projects
模型中:
class Project < ActiveRecord::Base
attr_accessible :title, :departments_attributes, :positions_attributes, :id
belongs_to :user
has_many :departments
has_many :positions
validates :title, presence: true
before_create :set_departments
accepts_nested_attributes_for :departments
accepts_nested_attributes_for :positions
private
def set_departments
self.departments.build department: "Test Dept", production_id: self.id
end
end
每个部门都有很多职位。我也在努力为部门创造职位。我如何将新职位与此模型中的部门相关联?
您可以通过以下方式添加新职位:
Project.first.positions << Position.create(:foo => 'foo', :bar => 'bar')
或
position = Position.create(:foo => 'foo', :bar => 'bar')
Department.first.positions << position
Project.first.positions << position
显然“.first”只是为了说明,您可以对任何部门或项目实例使用 <<
符号。
再看看这个,它似乎非常适合多态关联。
class Position < ActiveRecord::Base
belongs_to :positioned, polymorphic: true
end
class Project < ActiveRecord::Base
has_many :positions, as: :positioned
end
class Department < ActiveRecord::Base
has_many :positions, as: :positioned
end
在您的迁移中:
create_table :positions do |t|
...
t.integer :positioned_id
t.string :positioned_type
...
end
可能有更合适的方式为您的应用命名,但这是一般的想法。
如果我对你的问题的理解正确,你可能会在你的 Department 模型中做这样的事情:
after_create { self.positions.create! }
尽管这可能是一种有问题的方法。使用 ActiveRecord 回调(这给了我们 after_create)创建这样的记录会使您的整个应用程序非常脆弱。例如,如果您这样做,您将永远无法创建一个没有关联职位的部门。也许有一天你需要这样做。
因此,即使这不是您问题的确切答案,我还是建议查看在服务对象中或至少在控制器代码中创建这些关联模型。
有两种方法:
#app/models/project.rb
class Project < ActiveRecord::Base
has_many :departments
accepts_nested_attributes_for :departments
before_create :set_department
private
def set_department
self.departments.build department: "Test"
end
end
#app/models/department.rb
class Department < ActiveRecord::Base
has_many :positions
accepts_nested_attributes_for :positions
before_create :set_positions
private
def set_positions
self.positions.build x: y
end
end
...或...
#app/models/project.rb
class Project < ActiveRecord::Base
has_many :departments
accepts_nested_attributes_for :departments, :projects
before_create :set_departments
private
def set_departments
dpt = self.departments.build department: "Test"
dpt.positions << Position.new position: "Admin"
dpt.positions << Position.new position: "Tester"
end
end
--
您还可以在一行中声明多个嵌套属性:
accepts_nested_attributes_for :departments, :positions