views:

76

answers:

2

Hey all,

I am starting to create my sites in Ruby on Rails these days instead of PHP.

I have picked up the language easily but still not 100% confident with associations :)

I have this situation:

User Model

has_and_belongs_to_many :roles

Roles Model

has_and_belongs_to_many :users

Journal Model

has_and_belongs_to_many :roles

So I have a roles_users table and a journals_roles table

I can access the user roles like so:

user = User.find(1)
User.roles

This gives me the roles assigned to the user, I can then access the journal model like so:

journals = user.roles.first.journals

This gets me the journals associated with the user based on the roles. I want to be able to access the journals like so user.journals

In my user model I have tried this:

def journals
  self.roles.collect { |role| role.journals }.flatten
end

This gets me the journals in a flatten array but unfortunately I am unable to access anything associated with journals in this case, e.g in the journals model it has:

has_many :items

When I try to access user.journals.items it does not work as it is a flatten array which I am trying to access the has_many association.

Is it possible to get the user.journals another way other than the way I have shown above with the collect method?

Hope you guys understand what I mean, if not let me know and ill try to explain it better.

Cheers

Eef

A: 

Similar question http://stackoverflow.com/questions/2802539/ruby-on-rails-join-table-associations

You can use Journal.scoped to create scope with conditions you need. As you have many-to-many association for journals-roles, you need to access joining table either with separate query or with inner select:

  def journals
    Journal.scoped(:conditions => ["journals.id in (Select journal_id from journals_roles where role_id in (?))", role_ids])
  end

Then you can use user.journals.all(:include => :items) etc

Voyta
+1  A: 

If you want to have user.journals you should write query by hand. As far as I know Rails does has_many :through associations (habtm is a kind of has_many :through) one level deep. You can use has_many with finder_sql.

user.journals.items in your example doesn't work, becouse journals is an array and it doesn't have items method associated. So, you need to select one journal and then call items:

user.journals.first.items

I would also modify your journals method:

def journals
  self.roles(:include => :journals).collect { |role| role.journals }.flatten.uniq
end

uniq removes duplicates and :inlcude => :journals should improve sql queries.

klew