如何在Rails中两次加入相同的2个模型?

Ton*_*ony 2 ruby-on-rails has-and-belongs-to-many

我有一个国家偏好的应用程序.用户将有两种类型的国家偏好 - 事件和研究.将来可能会有更多.我更倾向于使用2个表来表示使用STI.我在执行此操作时优雅地配置Rails有点麻烦.我可以破解它,但我宁愿通过Rails惯例来做到这一点.我想要的是这样的:

class User < ActiveRecord::Base
  has_many event_countries, :through => :event_countries, :class_name => 'Country'
  has_many research_countries, :through => :research_countries, :class_name => 'Country'
end

class EventCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class ResearchCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class Country < ActiveRecord::Base
...
end
Run Code Online (Sandbox Code Playgroud)

但这不起作用.鉴于这个"伪代码"有没有人知道如何在Rails中实际实现它?

tad*_*man 5

我认为你要宣布他们错了,因为这应该正常工作.这就是该:through指令的用途:

class User < ActiveRecord::Base
  has_many :event_countries
  has_many :countries_with_events,
    :through => :event_countries,
    :source => :country

  has_many :research_countries
  has_many :countries_with_researches,
    :through => :research_countries,
    :source => :country
end

class EventCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class ResearchCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class Country < ActiveRecord::Base
  # ...
end
Run Code Online (Sandbox Code Playgroud)

许多尴尬来自于您为表格选择的标签.虽然乍一看它们看似合理,但你使用它们的方式最终会使它们变得困难.

你可能想要调用research_countries类似的东西user_research_countries,使关系名称可以user.research_countries如下:through:

class User < ActiveRecord::Base
  has_many :user_event_countries
  has_many :event_countries,
    :through => :user_event_countries,
    :source => :country

  has_many :user_research_countries
  has_many :research_countries,
    :through => :user_research_countries,
    :source => :country
end

class UserEventCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class UserResearchCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user
end

class Country < ActiveRecord::Base
  # ...
end
Run Code Online (Sandbox Code Playgroud)

您可以通过向用户 - 国家/地区关联表添加一个包含一个或多个标志的字段来进一步重构,在这种情况下,这些标志将是研究或事件或以后需要的任何内容:

class User < ActiveRecord::Base
  has_many :user_countries
  has_many :event_countries,
    :through => :user_countries,
    :source => :country,
    :conditions => { :event => true }
  has_many :research_countries,
    :through => :user_countries,
    :source => :country,
    :conditions => { :research => true }
end

class UserCountry < ActiveRecord::Base
  belongs_to :country
  belongs_to :user

  # * column :event, :boolean
  # * column :research, :boolean
end

class Country < ActiveRecord::Base
  # ...
end
Run Code Online (Sandbox Code Playgroud)