views:

46

answers:

2

Hey all,

i need a little help with a AR query. This is how my models look like:

class User < AR:B
  has_many :publications
end

class Publication < AR:B
  belongs_to :user
  belongs_to :category
end

class Category < AR:B
  has_many :publications
end

Now let's say I want to iterate over all existing categories and either display the user's publications, or display something like "#{current_user.name} has no publications in this category".

class PublicationsController < AC:B

  def index
    @categories = Category.find(:all, :include => :publications, :conditions => { 'publications.user_id' => current_user })
  end

end

This gives me all Categories the user actually has publications, but lacks the "empty" ones.

Any suggestions? :-)

A: 

This gives you all the Category objects:

@categories = Category.all

Then, if you declare has_many :through associations you can do something like the following:

@categories.each do |category|
  if category.users.include?(current_user)
    # User has publications
    publications = category.publications.select { |pub| pub.user == current_user }
  else
    # User has no publications
  end
end

(has-many-through declarations:

class User < AR:B
  has_many :publications
  has_many :categories, :through => :publication
end

class Publication < AR:B
  belongs_to :user
  belongs_to :category
end

class Category < AR:B
  has_many :publications
  has_many :users, :through => :publication
end

... warning: drycode)

There's probably an neater way to do this using named scopes though.

fd
Thanks for the answer, but how would i access the publications? @category.publications would still give me all publications of the category...
malloy
Inside the if statement is the publications = ..., that should give you the publications the user has on the category
fd
Err.... thought this'd be controller code :/ Problem solved, thanks!
malloy
A: 

You might be able to just modify the find call:

@categories = Category.find(:all, :include => :publications, :conditions => [ 'publications.user_id=? OR publications.user_id IS NULL', current_user ])

Notice that we use the Array variant here rather than the Hash variant, since the example in the documentation implies this is the correct usage.

fd
This gives me all categories with publications, but not all categories. The condition publications.user_id IS NULL will be false by default, because there are no matching records, or am i missing something?
malloy
I'd need to try it or read the code to understand the SQL that comes out, in the mean time the following may work:@categories = Category.find(:all, :joins => "LEFT JOIN publications ON publications.user_id = #{current_user.id}")
fd