Use checkboxes to restrict search to belonging objects

I am working on a rails 3.2 app that basically acts as a blog with tags.

Tags are related to posts in a has_many :through association. (post have many tags through taggigns) Don't know why the app doesn't have a habtm association since it would have worked the same, but that's what I have.

The app can now show the list of posts belonging to a tag like this:

class TagsController < ApplicationController

  def show
    @tag = Tag.find(params[:id])    
    @posts = @tag.posts.paginate(page: params[:page], :per_page => 10) 
  end
  ...
end

This way the page example.com/tags/1 will show all the posts with a tag matching ID 1.

What I have to do is modify this app to have checkboxes for tags and to restrict the search for example to posts having both tag 1 and 4.

Can someone please give me an input on where to start or maybe some resources to look for? I think I should use a join but I'm not sure this is the case.

Thank you.

========

EDIT: Thank you for your answers. Anyway, as suggested by ok32, user1083138's solutions was creating duplicates. At the same time ok32's one was resulting in empty arrays (probably it's due to my poor implementation of the tagging system).

I went up with this solution that works just fine:

  def self.tag_query(list)
    Post.joins(:tags).where(:tags => { :name => list } ).having("count(tags.name) = ?", list.count ).group('posts.id')
  end

Answers


Yep, JOIN is your friend:

Post.joins(:tags).where(:tags => { :id => [tag_ids] } )

Check this rails guide as reference.

Also you have to create\modify views and controllers to show check-boxes and populate "tag_ids" variable.


JOIN is your friend, but.. To avoid duplicate results I'd suggest using something like that:

In the controller:

@tags = Tag.find(params[:tag_ids])
@posts = Post.tagged_with(@tags)

In the Post model:

def self.tagged_with(tags)
  post_ids = select('posts.id').joins(:tags).where('tags.id in (?)', tags)
  where(id: post_ids)
end

update:

I have modified the model method a bit:

def self.tagged_with(tags)
  post_ids = joins(:taggings).where('taggings.tag_id in (?)', tags)
  where(id: post_ids)
end

What has changed:

  1. I removed unnecessary select('posts.id'). It works well without it.

  2. Now it generates more efficient query (it joins with one table instead of two).


Need Your Help

Get all the objects inside an NSArray whose string property starts with a particular letter

ios objective-c cocoa-touch nsarray filtering

I have an NSArray containing instances of MyCustomObject; each has a NSString called firstName.

Why am I getting, “cannot find table 0”?

c# sql-server-ce compact-framework .net-1.1

At program startup, I'm creating a SQL Server CE table if it doesn't exist, and adding a record to it:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.