使用Rails在create上创建嵌套记录

时间:2016-01-18 21:41:13

标签: html ruby-on-rails ruby-on-rails-3 associations rails-activerecord

我有一个项目模型,用于在创建时在特定项目中自动生成部门。这包含在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

每个部门都有很多职位。我也想为部门创造职位。如何将新职位与该模型中的部门相关联?

3 个答案:

答案 0 :(得分:2)

有两种方法:

#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

答案 1 :(得分:1)

如果我理解你的问题,你可能会在你的部门模型中做这样的事情:

after_create { self.positions.create! }

虽然这可能是一个有问题的方法。使用ActiveRecord回调创建这样的记录(这就是为我们提供了after_create)可以使你的整个应用程序变得非常脆弱。例如,如果你这样做,你将永远无法建立没有相关职位的部门。也许有一天你需要这样做。

即使它不是您问题的确切答案,我建议您在服务对象中创建这些关联模型,或者至少在控制器代码中创建。

答案 2 :(得分:0)

您可以使用以下内容添加新职位:

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

可能有更适合为您的应用命名的方法,但这是一般的想法。