簡體   English   中英

Rails 模型關聯,has_many :through 和 has_one 具有相同的模型

[英]Rails model associations, has_many :through and has_one with the same model

我有兩個模型:用戶和狀態。 州模型擁有美國 50 個州中每一個州的記錄。

我希望每個用戶都有兩個屬性:一個是“家”狀態,另一個是“訪問”狀態。

我知道我必須建立某種模型關聯來實現這一點,但不確定最好的方法是什么。

這是我到目前為止所擁有的,但我知道將 has_many 和 has_one 關聯到同一模型肯定有問題。

#user.rb
class User < ActiveRecord::Base
   has_many :visits
   has_many :states, :through => :visits
   has_one :state
end

#visit.rb
class Visit < ActiveRecord::Base
   belongs_to :user
   belongs_to :state
end

#state.rb
class State < ActiveRecord::Base
   has many :visits
   has many :users, :through => :visits 
   belongs_to :user
end
   

有什么建議?

在我看來,您已經擁有的幾乎是正確的,除非您將主狀態外鍵存儲在用戶上,如下所示:

# user.rb
class User < ActiveRecord::Base
  belongs_to :state
  has_many :visits
  has_many :states, through: visits
end

# visit.rb
class Visit < ActiveRecord::Base
  belongs_to :user
  belongs_to :state
end

# state.rb
class State < ActiveRecord::Base
  has_many :visits
  has_many :users, through: :visits
end

然后,您將像這樣訪問主狀態:

u = User.first
u.state

和訪問過的狀態,如下所示:

u = User.first
u.states

為了編程清晰,您可以重命名您的關系:

# user.rb
class User < ActiveRecord::Base
  belongs_to :home_state, class_name: "State"
  has_many :visits
  has_many :visited_states, class_name: "State", through: visits
end

# state.rb
class State < ActiveRecord::Base
  has_many :residents, class_name: "User"
  has_many :visits
  has_many :visitors, class_name: "User", through: :visits
end

您的域模型會更有意義:

u = User.first
u.home_state
u.visited_states

s = State.first
s.residents
s.visitors

我預計您可能希望存儲有關訪問的其他信息,因此保留Visit模型的 HMT 連接表將允許您執行此操作,而不是使用 HABTM 關系。 然后,您可以向訪問添加屬性:

# xxxxxxxxxxxxxxxx_create_visits.rb
class CreateVisits < ActiveRecord::Migration
  def change
    create_table :visits do |t|
      t.text :agenda
      t.datetime commenced_at
      t.datetime concluded_at
      t.references :state
      t.references :user
    end
  end
end

我希望每個用戶都有兩個屬性:一個是“家”狀態,另一個是“訪問”狀態。

在您的模型中,一個州可能只belongs_to一個用戶 ( belongs_to )。

正確的語義是

class User < AR::Base
  belongs_to :home_state, :class_name => "State", :foreign_key => "home_state_id", :inverse_of => :users_living
  has_and_belongs_to_many :visited_states, :through => :visits
  # ...
end

class State < AR::Base
  has_many :users_living, :class_name => "User", :inverse_of => :home_state
  # ...
end

您不能在單個模型上擁有 has_many 和 has_one 關系,在本例中為 state。 一種解決方案是:

創建狀態的靜態模型,它們不需要是數據庫模型,它們可以是狀態模型上的靜態變量: US_STATES = {'1' => 'AK', '2' => 'AL', etc}或者因為你需要使用一個rake任務或數據庫,你可以使用fixture狀態的表加載到數據庫中(更復雜:種子任務加載夾具進入分貝,但好的,因為你可以使用活動記錄管理該模型)。

然后您可以在定義 home_state 的用戶模型上提供 home_state_id,訪問只是 user_id 和 state_id 之間的連接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM