Filtring查询:通过关联

时间:2015-12-24 12:44:55

标签: ruby-on-rails ruby ruby-on-rails-4

我有3个型号:

class User < ActiveRecord::Base
  has_many :categories
  has_many :links, through: :categories
end

class Category < ActiveRecord::Base
  belongs_to :user
  has_many :links
end

class Link < ActiveRecord::Base
  belongs_to :category
end

对于给定的用户,我想找到他喜欢的字段等于true的所有链接。我正在从'rails guides'学习rails并且我在那里搜索了对此的简单查询,但我没有找到任何东西。最后我使用select iterator解决了问题:

@links = current_user.links.select{ |l| l.favorite }

但我不确定这是一个很好的解决方案。怎么用rails方式?

3 个答案:

答案 0 :(得分:4)

要添加到@Pierre Michard的答案,您可能还希望查看ActiveRecord Association Extensions,它基本上会取代scope模型中的Link

#app/models/user.rb
class User < ActiveRecord::Base
   has_many :categories
   has_many :links, through: :categories do
      def favorites
         where favorite: true
      end
   end
end

这将允许您致电:

@links = current_user.links.favorites

答案 1 :(得分:3)

工作正常,但该代码生成的SQL查询将类似于

SELECT * FROM links where links.user_id = ?

然后,您感兴趣的链接将被select方法过滤。 如果您的用户有很多链接,而且很少有人喜欢,那么以这种方式选择收藏夹可能会更有效:

@links = current_user.links.where(favorite: true)

这会产生这种查询:

SELECT * FROM links where links.user_id = ? AND links.favorite = 't'

您可以在链接模型中创建范围以过滤收藏的链接。

class Links < ActiveRecord::Base
  scope :favorites, -> { where(favorite: true) }
end

相应的查询:

@links = current_user.links.favorites

这可以更有效,因为这将创建更少的ActiveModel对象。

答案 2 :(得分:-1)

需要多对多的关系,

class User < ActiveRecord::Base
  has_many :categories
  has_many :links, through: :categories
end

class Category < ActiveRecord::Base
  belongs_to :user
  belongs_to :link
end

class Link < ActiveRecord::Base
  has_many :categories
  has_many :users, through: :categories
end

然后你可以获取最喜欢的列为真的链接记录,

@links = current_user.categories.include(:links).where('links.favorite = ?', true)