【问题标题】:has_one belongs_to relationship issue in Rails 4Rails 4中的has_one belongs_to关系问题
【发布时间】:2014-11-30 23:59:06
【问题描述】:

我在 Rails 4 中遇到了关系问题。

有 4 种型号

  1. 用户
  2. 请求
  3. 制作
  4. 型号

一个 User has_many Requests,一个 Request has_one Make 和一个 Make has_many Models。

User->Requests 和 Make->Models has_many 关系很好,但 Request->Make has_one 关系失败。

class Request < ActiveRecord::Base
    belongs_to :user
    has_one :make
end

class Make < ActiveRecord::Base
  has_many :models
  belongs_to :request
end

每个模型的架构是...

create_table "requests", force: true do |t|
  t.integer  "user_id"
  t.integer  "make_id"
  t.datetime "created_at"
  t.datetime "updated_at"
end

create_table "makes", force: true do |t|
  t.string   "name"
  t.datetime "created_at"
  t.datetime "updated_at"
end

当我尝试将 Make 分配给请求时,我收到以下错误

Mysql2::Error: Unknown column 'makes.request_id' in 'where clause': SELECT  `makes`.* FROM `makes`  WHERE `makes`.`request_id` = 7 LIMIT 1                                                                           
ActiveRecord::StatementInvalid Exception: Mysql2::Error: Unknown column 'makes.request_id' in 'where clause': SELECT  `makes`.* FROM `makes`  WHERE `makes`.`request_id` = 7 LIMIT 1                                 
nil  

为什么 ActiveRecord 在 Make 中需要 request_id?这不只适用于我在 User->Requests and Makes->Models 关系中的 has_many 关系吗?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 activerecord


    【解决方案1】:

    has_onebelongs_to 方法允许您在模型之间创建 一对一 关联,因此您可以通过各种帮助方法轻松地相互访问。

    has_one 仅应在其他类包含“外键”时使用。如果当前类包含“外键”,则应使用belongs_to

    根据您提供的架构,应该像以下示例中那样定义关联:

    class Request < ActiveRecord::Base
      # Because you have a `make_id` column in the "requests" table.
      belongs_to :make
    end
    
    class Make < ActiveRecord::Base
      # Because the Request model has the "foreign key" that 
      # creates the association, in this case `make_id`.
      has_one :request
    end
    

    通过像上面示例中那样进行关联,Rails 将为您提供帮助方法,允许您访问或创建每个关联的模型:

    # Request Model
    @request = Request.create!
    
    # Helper methods to access `make`: make, build_make, create_make, make=
    @request.make
    @request.build_make
    @request.create_make
    @request.make = Make.create!
    # ...
    
    
    # Make Model
    @make = Make.create!
    
    # Helper methods to access `request`
    @make.request
    @make.build_request
    @make.create_request
    @make.request = Request.create!
    #...
    

    我们使用has_onebelongs_to 方法来创建关联,同时也可以访问Rails 为我们创建的所有辅助方法。根据您是想从 Request 还是其他方式访问 Make,您可以添加或删除 has_onebelongs_to 来自特定的类。

    通过在两个类中保留每个类,我们可以从双方访问一堆帮助方法。例如,如果您从 Request 中删除了 belongs_to :make,您将无法使用 @request.make 从 Request 中访问 ma​​ke。但是,只要您保留 has_one 方法,您仍然可以使用 @make.request 从 make 访问 Request。

    请记住,迁移是他们自己的事情,我们还需要通过将“外键”添加到正确的表中来设置数据库级别的关联。通过查看 has_onebelongs_to 的定义,我们可以轻松找出在何处添加外键。 has_one 表示“外键”应该在关联表中,belongs_to 表示它应该在this表中。

    希望对您有所帮助!这里有更多信息:

    【讨论】:

    • 感谢您的帮助!你是对的,因为协会的方向是错误的。我一直在寻找一对多的关系,所以我在 Make 方面有 has_many 而不是 has_one。
    【解决方案2】:

    根据您的架构和错误消息,makes 中似乎没有来自 requests 的外键。

    看这个,例如:

    http://guides.rubyonrails.org/association_basics.html#the-has-one-association

    那里,Supplier 有一个帐户,accounts 有一个supplier_id。查看相应的迁移示例。

    【讨论】:

      【解决方案3】:

      您可能只需将 request_id 列添加到您的 make 表中。

      运行:

      rails g migration add_request_id_to_makes request_id:integer
      
      
      bundle exec rake db:migrate
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-09
        • 1970-01-01
        • 2014-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多