has_many:通过基于'bridge'模型属性的查询

时间:2011-08-21 19:37:13

标签: ruby-on-rails ruby-on-rails-3

解决此类查询的最佳方法是什么:

  • 每个小组都有很多区域
  • 每个州都有很多地区
  • 每个小组通过地区都有很多州
  • 每个区都属于一个成员

第1组 - *区(属于一名成员)* - 1州

我想查找特定组的状态列表,其中其区域中的至少一个未分配给成员(即,区的member_id为空)。换句话说,如果该州的所有地区都已分配给某个成员,则该状态不会显示在我的列表中。

class State < ActiveRecord::Base
 has_many :districts
end

class Group < ActiveRecord::Base
 has_many :districts
 has_many :states, :through => :districts, :uniq => true
end

class District < ActiveRecord::Base
 belongs_to :state
 belongs_to :group
 belongs_to :member
end

我想在我看来要完成的是让用户首先选择他的小组,然后选择他想要工作的状态,最后选择根据他的小组和状态选择填充的可用区域。所以基本上我不希望州名单包括没有可用区域的州。

修改

我提出的一个可能的解决方案是在我的Group课程中定义一个新方法,请告诉我这是否是一个很好的解决方案:

class Group < ActiveRecord::Base

...

  def available_states
    result = []
    self.states.each do |state|
      state_list = state.districts & self.districts.where(:member_id => nil)
      if !state_list.empty?
        result << state
      end
    end
    result
  end

end

1 个答案:

答案 0 :(得分:2)

我觉得你过于复杂了。

您说您希望用户先选择 ,然后选择 。那么为什么你需要过滤每个州的完整地区名单?您已经拥有该组可能的区域列表,不是吗?如果您&针对每个州的地区,那么您最终将会进入该组的区域。

这似乎就足够了:

def available_states
  districts.where(:member_id => nil).group(:state_id).map(&:state)
end

或者我错过了什么?

纯粹未经测试,但您也可以尝试这样的事情:

class District
  # this scope is simple, but keeps the "available" definition where it
  # belongs, in District
  scope :available, lambda { where(:member_id => nil) }
end

class State
  # then here just join "available" districts and group on id for uniqueness
  scope :with_available_districts, lambda {
    joins(:districts).group(:id) & District.available
  }
end

# now you don't need an available_states method, it would just be:
Group.first.states.with_available_districts