has_many 通过关联 Rails 4 的问题

Problems with has_many through Association Rails 4

所以我正在尝试做一个存储当前天气的数据库:

 --------------             ------------------            ----------
|              | 1       * |                  |*       1 |          | 
| YearMonthDay |-----------| WeatherCondition |----------| Location |
|              |           |                  |          |          |
 --------------             ------------------            ----------

我使用 belongs_to 和 has_many 生成模型 :through

class WeatherCondition < ActiveRecord::Base
    belongs_to :year_month_day
    belongs_to :location
end

class YearMonthDay < ActiveRecord::Base
    has_many :weather_conditions
    has_many :locations, :through => :weather_conditions
 end

class Location < ActiveRecord::Base
    has_many :weather_conditions
    has_many :year_month_days, :through => :weather_conditions
end

并且还为他们每个人创建了一个迁移,YearMonthDay 和 Locations 是正常的,WeatherConditions 如下:

class CreateWeatherConditions < ActiveRecord::Migration
  def change
    create_table :weather_conditions do |t|
        t.belongs_to :location, index: true
        t.belongs_to :year_month_day, index: true

      t.timestamps null: false
    end
  end
end

我不知道我做错了什么,但我收到一个错误:

 unknown attribute 'year_month_day_id' for WeatherCondition.

Rails讲究复数表。可能不明白如何复数year_month_day。您的架构是什么样的?

创建多对多关系,你需要一个has_and_belongs_to_many符号。

class YearMonthDay < ActiveRecord::Base
    has_and_belongs_to_many :locations
end

class Location < ActiveRecord::Base
    has_and_belongs_to_many :year_month_days
end

删除 WeatherConditions 的 class,您只需要必须命名以匹配两个模型的连接 table。名称必须按字母顺序排列。

create_table :locations_year_month_days, id: false do |t|
    t.belongs_to :location, index: true
    t.belongs_to :year_month_day, index: true

  t.timestamps null: false
end

建立关系后,您可以调用 my_date.locations 获取与该日期关联的位置对象数组,或者调用 my_location.year_month_dates 反之亦然。

这个Rails guide有更长的解释。

您仍然需要将外键添加到 WeatherConditions:

如果您要创建一个新的 table:

class CreateWeatherConditions < ActiveRecord::Migration
  def change
    create_table :weather_conditions do |t|
        t.integer :location_id
        t.integer :year_month_day_id

      t.timestamps null: false
    end
  end
end

如果您已经拥有 table:

class CreateWeatherConditions < ActiveRecord::Migration
  def change
    add_column :weather_conditions, :location_id, :integer
    add_column :weather_conditions, :year_month_day_id, :integer
  end
end