【问题标题】:How to set a foreign key in rails?如何在rails中设置外键?
【发布时间】:2013-02-17 04:16:43
【问题描述】:

我正在尝试保存具有外键属性的对象。我不明白为什么它不起作用。外键在数据库中定义为非空。

class Store < ActiveRecord::Base
  attr_accessible :latitude, :longitude, :description
  validates :store_group, :presence => true
  validates :description, :presence => true, :length => {:maximum => 500}
  validates :latitude,    :presence => true
  validates :longitude,   :presence => true

  belongs_to :store_group
end

class StoreGroup < ActiveRecord::Base
  attr_accessible :name, :description, :image
  validates :name, :presence => { :message => "Store group can not be empty" }
end

所以,我正在尝试保存商店:

group = StoreGroup.new(:name=>"name",:description=>"description",:image=>"image")
store = Store.new(:store_group=>group,:latitude=>1,:longitude=>1,:description=>"description")
store.save

但是,MySQL 引发了一个异常:

Mysql2::Error: Column 'store_group' cannot be null: INSERT INTO `stores` (`created_at`, `store_group`, `description`, `latitude`, `longitude`, `updated_at`) VALUES ('2013-02-17 04:09:15', NULL, 'description', 1.0, 1.0, '2013-02-17 04:09:15')

为什么? 在此先感谢:)

【问题讨论】:

  • 我也试过 Store.new(:store_group=>group.id...),但没用。

标签: mysql ruby-on-rails ruby-on-rails-3 foreign-keys rails-activerecord


【解决方案1】:

您正在尝试通过store 创建/保存store_group 对象。因此使用:

accepts_nested_attributes_for :store_group

在您的 Store 模型中

Read here about accepts_nested_attributes_for

【讨论】:

  • 嗨 Rahul,我试过了,但是当我实例化存储对象时,它会引发 ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: store_group.因此,我在 attr_accessbile 中添加了 store_group,但是,之前的 MySQL 异常仍然存在。
  • 参考这个stackoverflow.com/a/8321540/985051你需要将你的关联attrs添加到attr_accessors
  • 我用这个解决了:stackoverflow.com/questions/4912154/…
  • 没关系...但是这里 storeGroup 和 store 将在不同的事务下创建,因此如果在创建 store 时出现任何验证错误,您的 storegroup 仍将提交到数据库。跨度>
【解决方案2】:

首先,从长远来看,如果您将 has_many :stores 添加到 StoreGroup 可能会更容易,例如,如果您想要检索属于特定 StoreGroup 的所有商店。其次,您应该通过其 StoreGroup 添加商店,并且由于您已经在那里建立了关联,因此非常简单(注意更改为 Store.create):

group = StoreGroup.create(name: "name", description: "description", image: "image")
group.stores << Store.create(lat: 1, long: 1, desc: "description")

此方法将自动设置:store_group_id 并将新的 Store 实例保存为其 StoreGroup 的“子”。请注意,您还需要更改代码以考虑现有的 StoreGroups,以便以后可以将商店添加到现有的 StoreGroups。在 Rails 3.2.x 中使用 .first_or_create.where(...) 子句是惯用的,尽管在以前的 Rails 版本中存在具有创建能力的动态查找器(例如 find_or_create_by_name_and_store_group_id)。

最后,删除 validates :store_group,因为关联验证不能那样工作。如果你真的需要,请使用validates :store_group_id

【讨论】:

  • 嗨,埃里克,首先感谢您的提示。我在 StoreGroup 中添加了 has_many 并替换了 store_group_id 的验证。所以,我尝试了你所说的,但是在这个命令之后"group.stores &lt;&lt; Store.create(lat: 1, long: 1, desc: "description")" 它引发了同样的异常。我应该弄错的一件事是,StoreGroup 对象的表 Store 中的列应该是 store_group 还是 store_group_id?我正在使用 store_group,我不知道这是否可能是 ActiveRecord 关系的问题..
  • 抱歉,在我的示例中,我使用了StoreGroup.new,其中 .new 不会保存实例,因此在将 Store 分配给它时将没有可用的 ID。应该是StoreGroup.create。我已经编辑了我的示例来做到这一点。
猜你喜欢
  • 1970-01-01
  • 2010-10-05
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多