代码之家  ›  专栏  ›  技术社区  ›  Tony

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

  •  2
  • Tony  · 技术社区  · 15 年前

    我有一个具有国家偏好的应用程序。用户将有两种国家偏好-活动和研究。将来可能会有更多。我更倾向于用两张桌子来代表这个,而不是用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中实际实现它吗?

    1 回复  |  直到 15 年前
        1
  •  5
  •   tadman    15 年前

    我认为你要宣布他们错了,因为这应该是正确的。这就是 :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 作为 :到 :

    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