如何使用has_one创建关联记录和修改数据

时间:2017-03-06 15:05:40

标签: ruby-on-rails ruby postgresql

我是一个铁杆新手,虽然我已经构建了一个带有erb文件,ruby和postgres的应用程序,但我发现很难找到如何编写类方法的语法,特别是如果你想做的不仅仅是CRUD 。

我有两张桌子:材料& material_costs 材料has_one material_cost和material_cost属于Material。

Material模型的每个新条目都应自动将一个条目填充到material_costs。使用Material中的三个字段,我需要修改将创建新材料成本记录的数据。

我花了好几个小时试图找到build_with函数的正确语法。即使使用rails docs也不是那么容易。

到目前为止

代码:

class Material < ApplicationRecord
  has_and_belongs_to_many :job_entries
  has_one :material_costs, :material_charges, :dependent => :destroy

@material = current_material
@material_cost = @material.build_material_costs(
            :cost_a4 => ((@material.cost_per_sqm +        @material.ink_per_sqm) * 0.0626514876)
            :cost_a3 => ((@material.cost_per_sqm + @material.ink_per_sqm) * 0.124548139)


end

class MaterialCost < ApplicationRecord
 belongs_to :materials
end

移植

class CreateMaterials < ActiveRecord::Migration[5.0] 
  def change 
    create_table :materials do |t| 
      t.string :product_name, :guk_name 
      t.integer :roll_width_in, :roll_length_m, :factor, :rounded_sale_price 
      t.float :list_price, :cost_per_sqm, :ink_per_sqm, :supplier_discount, :sell_per_sqm 

      t.timestamps 
    end 
  end 
end

我是否在正确的轨道上?任何人都知道有关构建用于基本查询和修改数据的类模型方法的用户友好指南吗?谢谢,godhar

class CreateMaterials < ActiveRecord::Migration[5.0]
 def change
  create_table :materials do |t|
  t.string :product_name, :guk_name
  t.integer :roll_width_in, :roll_length_m, :factor, :rounded_sale_price
  t.float :list_price, :cost_per_sqm, :ink_per_sqm, :supplier_discount, :sell_per_sqm
  t.timestamps
   end
  end
end


class CreateMaterialCosts < ActiveRecord::Migration[5.0]
  def change
   create_table :material_costs do |t|
   t.float :cost_a4, :cost_a3, :cost_a2, :cost_a1, :cost_b0, :cost_b1, :cost_b2
   t.float :cost_b3, :cost_b4
   t.timestamps
   end
 end
end

关闭我的机器和psql服务器后,重新启动并重新启动服务器,重新创建数据库,然后最终迁移我的所有迁移,我在错误地狱。如果有人放弃了表格,那么惯例是什么?我应该编辑迁移文件,以便重命名列和所有这些编辑迁移都不会运行吗?即我是否有机会从头开始,或者我是否也必须迁移我的所有更改?另外,我们是否要添加id列?我认为通过关系Rails为我们设置了ID,我相信我会在某处读到它?我们在何时何地添加id列?

2 个答案:

答案 0 :(得分:2)

试试这个:

class Material < ApplicationRecord
  has_and_belongs_to_many :job_entries
  has_one :material_cost, :material_charge, :dependent => :destroy

  after_create do
    self.create_material_cost(
      cost_a4: (self.cost_per_sqm + self.ink_per_sqm) * 0.0626514876),
      cost_a3: (self.cost_per_sqm + self.ink_per_sqm) * 0.124548139)
    )
  end

end

class MaterialCost < ApplicationRecord
 belongs_to :materials
end

after_create指定在创建每个材料后自动运行的代码块。 create_material_cost是使用has_one关系时生成的辅助方法。它允许您创建一个与给定材料自动关联的MaterialCost。

对于您的迁移,yes rails会在您未指定迁移时自动添加id列。默认名称为:id。 自动添加的导轨是将您的MaterialCosts链接到其父材质的外键列。您可以通过创建新迁移来添加它:

class AddMaterialIDToMaterialCosts < ActiveRecord::Migration[5.0]
  def change
    add_column :material_costs, :material_id, :integer
  end
end

要重置数据库并重新加载迁移,请运行:

rails db:drop db:create db:migrate db:seed

请注意,这将删除数据库中的所有现有数据

答案 1 :(得分:2)

嗯,你走在正确的轨道上,但你需要改变一些事情

  1. has_one必须是单数
  2. belongs_to必须是单数
  3. 您可以使用after_create回调为material_cost
  4. 创建关联的Material
  5. 您不需要@material = current_material,因为您可以将其称为self
  6. 如果您使用build,则需要保存实例或使用create
  7. 使用CONSTANT作为0.06265148760.124548139等值,因此如果您需要更改它们,则无需在项目范围内搜索它们。
  8. 因此,在修复这些内容之后,代码将是

    <强> material.rb

    class Material < ApplicationRecord
      has_and_belongs_to_many :job_entries
      has_one :material_cost, :material_charge, dependent: :destroy
    
      after_create :set_material_cost
      A3_FACTOR = 0.124548139
      A4_FACTOR = 0.0626514876
    
      private
    
      def set_material_cost
        @material_cost = self.create_material_cost(
          cost_a4: (cost_per_sqm + ink_per_sqm) * A4_FACTOR,
          cost_a3: (cost_per_sqm + ink_per_sqm) * A3_FACTOR
        )
      end
    end
    

    <强> material_cost.rb

    class MaterialCost < ApplicationRecord
      belongs_to :material
    end