【问题标题】:Ruby on Rails ActiveRecord - making relationships errorsRuby on Rails ActiveRecord - 使关系错误
【发布时间】:2019-02-23 11:40:54
【问题描述】:

我是 Rails 的新手,并且在各种在线课程中遵循了许多指南,并使用其他 Stack Overflow 问题来生成一些带有参考的模型(大陆、国家、州),并尝试开始制作一些实例并对其进行测试。

rails g model Continent name:string
rails g model Country name:string continent:reference
rails g model State name:string country:reference

我不记得我是按什么顺序制作的。但我必须在模型文件夹中手动添加以下内容。

class Continent < ApplicationRecord
    has_many :countries
    has_many :states, through: :countries
    has_many :regions, through: :states
end


class Country < ApplicationRecord
    belongs_to :continents, optional: true
    has_many :states
    has_many :regions, through: :states
end


class State < ApplicationRecord
  belongs_to :country, , optional: true
  has_one :continent, through: :country
  has_many :regions
end

class Region < ApplicationRecord
  belongs_to :state, optional: true
  has_one :country, through: :state
  has_one :continent, through: :country

最后,我开始添加一些测试以在种子和控制台中使用。添加大陆很简单,但是运行 Country.create(name:"Australia",continent: Continent.find_by(name: "Oceania")) 不会建立 Continent 和 Country 之间的关系(Continent_id 在国家)。

但是,我可以只运行 Continent.find_by(name: "Oceania") 并获取:

=> 大陆 id:10,名称:“大洋洲”,created_at:“2018-09-19 09:18:07”,更新时间:“2018-09-19 09:18:07”

我感觉自己走在了正确的轨道上,但在将多个解决方案/方法拼凑在一起时混淆了一些事情。我可能使用错误或类似的生成器,可能会将一些手动方法与我应该让生成器处理的东西混为一谈。如果有人可以帮助填补空白,将不胜感激。这是 schema.rb

ActiveRecord::Schema.define(version: 2018_09_13_044538) do

  create_table "continents", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "countries", force: :cascade do |t|
    t.string "name"
    t.integer "continent_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["continent_id"], name: "index_countries_on_continent_id"
  end

  create_table "states", force: :cascade do |t|
    t.string "name"
    t.integer "country_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["country_id"], name: "index_states_on_country_id"
  end

【问题讨论】:

  • 实际上,现在我开始认为#&lt;ActiveRecord::Relation [#&lt;Country id: 1, name: "Finland", continent_id: nil, created_at: "2018-09-19 10:05:54", updated_at: "2018-09-19 10:05:54"&gt;]&gt; 代表关系本身,而不是存储正确国家/地区的索引?我是否存储了错误的数据类型?

标签: ruby-on-rails activerecord foreign-keys database-migration relation


【解决方案1】:

之前

class Country < ApplicationRecord belongs_to :continents, optional: true has_many :states has_many :regions, through: :states end

之后

class Country < ApplicationRecord belongs_to :continent, optional: true has_many :states has_many :regions, through: :states end

Belongs_to 必须是单数,在本例中是大洲和非大洲。

【讨论】:

    【解决方案2】:

    在您的 Country 模型中,您有:

    belongs_to :continents
    

    由于belongs_to表示单数关系(即一个国家只能属于一个大陆),你需要把它改成

    belongs_to :continent
    

    那么 Rails 应该开始正确分配大陆了。

    【讨论】:

    • 非常感谢!我仍然习惯于自动复数的“魔法”,完全错过了那个。我很高兴至少逻辑没问题,它只是一种类型(尽管它是多么令人沮丧)。
    • 实际上,我刚刚意识到另一个错误,如果我手动添加continent_id(例如1或2)它会起作用。但是,在我的 Continent.find_by(name: "Oceania") 中,我实际上应该写 Continent.find_by(name: "Oceania").id
    • 你实际上不需要这样做,除非你直接设置continent_id。所以它看起来像Country.create(name:"Australia", continent_id: Continent.find_by(name: "Oceania").id)。如果您只使用continent: Continent.find_by(name: "Oceania"),它应该可以正常工作。事实上,我更喜欢你最初的方式。
    • 啊,好吧,我没有意识到您可以使用continent 或continent_id。我只是感到困惑并尝试了一些不同的选择,可能把它们弄混了。仍然习惯于使用原始数据库,但是一旦掌握了它就很好了 :) 感谢您的澄清!
    • Rails 有很多非常方便的功能,当您习惯它时会变得非常直观。祝一切顺利!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-01
    • 2013-09-25
    相关资源
    最近更新 更多