繁体   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