how to retrieve single record through chained associations

Hi

I have a standard associations belongs_to, has_many :through

class Shop < ActiveRecord::Base   has_many :show_categories   has_many :categories, :through => :shop_categories end

class Category < ActiveRecord::Base   has_many :shop_categories   has_many :shops, :through => :shop_categories end

class ShopCategory < ActiveRecord::Base   belongs_to :shop   belongs_to :category end

There is one root category with hierarchical data for shops. shop_categories are holding some common fields for shop and category. mixed one record for one shop and category. So, for 100 categories, in shop_categories are 200 records, one for each shop.

For this example I have 2 shops.

Shop.first.category.find(10).shop_categories Rails are returning 2 shop_categories records one for each shop. Something is wrong with associations because it should find in shop_categories all records for first shop.

What I need is to retrieve only one record from shop_categories for corresponding association. I have tried has_one :shop_category but it returns not one but first and always same never less if I try Shop.find(1).category.find(10).shop_categories or Shop.find(2).category.find(10).shop_categories

So, what is really happening with this association? I realy can not guess, and I have tried all sort of things with no results.

Logically this kind of chaining Shop.find(2).category.find(10).shop_categories should collect and join appropriate associations and return data only for shop 2.

Could any one give some clues? Or clarify this kind of relation. Maybe there is another way to retrieve this single data?

Thanks, Tod

Hi Tod

For finding the category 10 of shop 1, the following should work by using Activerecord associations

Shop.find(1).categories.find(10) or Shop.find(1).categories.find(:first, :conditions => 'category = 10')

rainer

Dharmdip Rathod wrote:

Logically this kind of chaining Shop.find(2).category.find(10).shop_categories should collect and join appropriate associations and return data only for shop 2.

That''s not really how it works - once you do that find(10) you get a perfectly ordinary instance of Category (ie the stop_categories is just scoped to the category - not the shop.

I'm not sure why you're doing this at all - why not Shop.find (2).shop_categories.find_by_category_id(10) (or find_all_by_category_id if you want all of them)

Fred

ok - misunderstood this

The solution is already given by Fred

can u tell me online tutorial..???

don't know about DataMapper. In activerecord as soon as you call find you'll get a normal record/array of records. if you just want something that adds some extra conditions then you may be interested in named_scope. The other thing is that (in active record) scopes scope a particular table, so when you do Shop.find(1).categories then the categories proxy there is scoping finds on Category to those with the appropriate shop_id - it's not magic thing across everything with a shop_id column.

Fred

Fred

Hi and thanks,

yes this works Shop.find(2).shop_categories.find_by_category_id(10)

In shop_categories table I have field 'active' to mark that a category is visible/active for the shop.

So what is the best way to retrieve this value for shop's category?

In Category model I have defined 'active' so I can fetch with @category.active or @categories.each do |category| <%= category.name %> <%= category.active %> end

  def active     self.merchant_categories.find_by_category_id(id).active   end

I know that this is not so good solution, but I could not figured out over way to get this value. It is realy over kill for server. And It would get harder if there are more values that I need to keep in merchant_categories.

Is there a better way to do it?

Tod

Frederick Cheung wrote:

Hi,

I see that nobody knows how to do better way.

So maybe someone could suggest different model design that I can do @category.active

And just to avoid calling this self.merchant_categories.find_by_category_id(id).active

def active   self.merchant_categories.find_by_category_id(id).active end

instead to call self.merchant_category.active

Thanks, Tod

Tod Tod wrote: