我正在为库存管理编写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
答案 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
。
另外,请检查您是否对产品型号中的用户关系没有任何验证。