【发布时间】:2014-03-04 08:12:27
【问题描述】:
我在我的应用程序(Rails 3)中创建了两个表:
def change
create_table :articles do |t|
t.string :name
t.text :content
t.timestamps
end
create_table :tags do |t|
t.string :name
t.timestamps
end
create_table :articles_tags do |t|
t.belongs_to :article
t.belongs_to :tag
end
add_index :articles_tags, :article_id
add_index :articles_tags, :tag_id
end
我希望能够通过两种方式根据标签搜索文章:
- 带有任何给定标签的文章 (union)
- 具有所有给定标签(intersection)的文章
所以,换句话说,让我可以这样做的东西:
tag1 = Tag.create(name: 'tag1')
tag2 = Tag.create(name: 'tag2')
a = Article.create; a.tags << tag1
b = Article.create; b.tags += [tag1, tag2]
Article.tagged_with_any(['tag1', 'tag2'])
# => [a,b]
Article.tagged_with_all(['tag1', 'tag2'])
# => [b]
第一个相对容易。我刚刚在文章上做了这个范围:
scope :tagged_with_any, lambda { |tag_names|
joins(:tags).where('tags.name IN (?)', tag_names)
}
问题是第二个。我不知道如何在 ActiveRecord 或 SQL 中执行此操作。
我认为我可以做一些像这样令人讨厌的事情:
scope :tagged_with_all, lambda { |tag_names|
new_scope = self
# Want to allow for single string query args
Array(tag_names).each do |name|
new_scope = new_scope.tagged_with_any(name)
end
new_scope
}
但我敢打赌,这太低效了,而且闻起来很臭。有关如何正确执行此操作的任何想法?
【问题讨论】:
-
最终决定这是自制解决方案无法像我喜欢的那样工作的众多案例之一。所以我刚刚安装了this gem,它做了一些非常简洁的东西,看起来很愉快。有点逃避,但是...
标签: sql ruby-on-rails ruby-on-rails-3 postgresql activerecord