Rails可选belongs_to

tsm*_*tsm 48 ruby activerecord ruby-on-rails

我正在为库存管理编写Rails前端.我希望用户能够注册产品,所以我有:

class User < ActiveRecord::Base
  has_many :products
  # <snip>
end
Run Code Online (Sandbox Code Playgroud)

class Product < ActiveRecord::Base
  belongs_to :user
  # <snip>
end
Run Code Online (Sandbox Code Playgroud)

问题是产品是在用户注册之前创建的.也就是说,这是完全可以接受的呼吁Product.create,只是把它设置user_idnil.但是,正如您可以想象的那样,Rails不支持开箱即用:

> Product.create!
   (0.3ms)  SELECT COUNT(*) FROM "products" WHERE "products"."type" IN ('Product')
   (0.1ms)  begin transaction
   (0.1ms)  rollback transaction
ActiveRecord::RecordInvalid: Validation failed: User can't be blank
    from ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-3.2.13/lib/active_record/validations.rb:56:in `save!'
Run Code Online (Sandbox Code Playgroud)

我已经考虑过一堆kludgey解决方法,其中最吸引人的是有一个NullUser子类User并使用它来创建产品.但这似乎仍然是一个黑客.这是什么Rails方式?

谢谢.


相关迁移:

class AddUseridToProducts < ActiveRecord::Migration
  def change
    add_column :products, :user_id, :integer
  end
end
Run Code Online (Sandbox Code Playgroud)

然后:

class Changeuseridtobeoptionalforproducts < ActiveRecord::Migration
  def change
    change_column :products, :user_id, :integer, null: true
  end
end
Run Code Online (Sandbox Code Playgroud)

Ale*_*xis 205

只是rails 5的更新,如果你想要这种行为,你需要传递这个选项:

belongs_to :user, optional: true
Run Code Online (Sandbox Code Playgroud)

在Rails 5中,每当我们定义belongs_to关联时,都需要默认存在关联的记录.


Mat*_*att 5

Rails的绝对支持这个开箱,检查你的迁移,有你提供一个约束,例如:null => falseuser_id线?如果是这样,将其取出!

编辑:或如@Rodrigo Dias所述,将其反转为:null => true

另外,请检查您是否对Product模型中的用户关系没有任何验证。

  • @tsm 尝试 `change_column_null :products, :user_id, true` (2认同)

小智 5

您是否有需要用户在场的验证?如果是这样,删除它.

  • `belongs_to`要求在创建时默认存在父对象。如果要创建一个没有父对象的子对象,则会收到“ [“ &lt;父母&gt;必须存在”]错误消息,因此您的对象无效。有关解决方案,请检查@Alexis答案 (2认同)