Rails可选belongs_to

时间:2013-05-22 19:14:46

标签: ruby-on-rails ruby activerecord

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

class User < ActiveRecord::Base
  has_many :products
  # <snip>
end

class Product < ActiveRecord::Base
  belongs_to :user
  # <snip>
end

问题是产品是在用户注册之前创建的。也就是说,调用Product.create并将user_id设置为nil是完全可以接受的。但是,正如您可以想象的那样,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!'

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

感谢。


相关迁移:

class AddUseridToProducts < ActiveRecord::Migration
  def change
    add_column :products, :user_id, :integer
  end
end

以后:

class Changeuseridtobeoptionalforproducts < ActiveRecord::Migration
  def change
    change_column :products, :user_id, :integer, null: true
  end
end

3 个答案:

答案 0 :(得分:178)

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

belongs_to :user, optional: true

在Rails 5中,每当我们定义belongs_to关联时,默认情况下都需要关联的记录。

<强>更新
如果您仍希望默认使用旧行为,则可以将配置添加到application.rb文件中。

# /config/application.rb
config.active_record.belongs_to_required_by_default = false

通知: Rails 5的早期版本中有一些issues具有此配置,但目前已修复,在候选发布版上进行了测试的 5.2.3 即可。

答案 1 :(得分:6)

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

答案 2 :(得分:4)

Rails绝对支持开箱即用,请检查您的迁移,是否在:null => false行中添加了user_id等约束?如果是这样,把它拿出来!

编辑:或者@Rodrigo Dias说明,将其反转为:null => true

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