我有一个国家偏好的应用。用户将有两种类型的国家偏好 - 事件和研究。将来可能会有更多。我更倾向于使用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
但这不起作用。鉴于这个“伪代码”有没有人知道如何在Rails中实际实现它?
答案 0 :(得分: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
许多尴尬来自你为桌子选择的标签。虽然乍一看它们看似合理,但你使用它们的方式最终会使它们变得困难。
您可能希望将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
您可以通过向用户国家/地区关联表添加一个字段来进一步重构,其中包含一个或多个标记,在这种情况下将是研究或事件或以后需要的任何标记:
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