How define named scoped with order on associations - ruby-on-rails

I have two models.
class Shoe < ActiveRecord::Base
has_many :sizes, :dependent => :destroy
scope :brand_asc , order('brand ASC')
scope :brand_desc , order('brand DESC')
attr_accessible :brand ,:model
end
class Size < ActiveRecord::Base
belongs_to :shoe
scope :size_brand_asc , order("#{self.shoe.brand} ASC")
scope :size_brand_desc , order("#{self.shoe.brand} DESC")
end
It is very easy to call named scope on Shoe model like below.
#shoes = Shoe.brand_asc
But i want to sort sizes on the base of "brand" that is attribute of shoe model.so this
is not working for me like below.
#sizes = Size.size_brand_asc # giving error
How i can sort sizes on base of shoe brand

You can achieve this by doing like the following:
class Size < ActiveRecord::Base
belongs_to :shoe
scope :brand_ordered, lambda do |way = 'ASC'|
includes(:shoe).order("shoes.brand #{way}")
end
Usage:
#sizes = Size.brand_ordered('DESC')
# or
#sizes = Size.brand_ordered('ASC')
# equivalent:
#sizes = Size.brand_ordered
In the Shoe class:
class Shoe < ActiveRecord::Base
scope :brand_ordered, lambda do |way = 'ASC'|
order("#{self.table_name}.brand #{way}")
end

one line answer
scope :size_brand_asc, ->{joins(:shoe) & Shoe.brand_asc}

Related

ActiveRecord sort_by model's association

I want to use a where clause to retrieve all the correct ItemAttributes, then sort by the column order in Static.
Relationships:
class ItemAttribute < ActiveRecord::Base
belongs_to :static, primary_key:"name", foreign_key:"name"
end
class Static < ActiveRecord::Base
has_many :item_attributes, :foreign_key => 'name', :primary_key => 'name'
end
Code that doesn't quite do it...
#items = ItemAttribute.where(level:5)
#sorted = #items.sort_by(&:static.order)
I like using scopes and keeping specifics of each class in it's class, for something like this I could add a scope to Static model,
class Static < ActiveRecord::Base
scope :sort_by_order, -> { order(order: :desc) } # or asc if you want
end
Then use that scope in the query
#sorted_items = ItemAttribute.joins(:static).where(level: 5).merge(Static.sort_by_order)
#sorted_items = ItemAttribute.include(:static).where(level:5).order('statics.order')

how to find out active record property through many to many

I'm currently adjusting fedena to have a many:many relationship between students and guardians (as opposed to one:many student:guardians).
So this is what I did:
class Guardian < ActiveRecord::Base
has_many :parentings, :dependent=>:destroy
has_many :students, :through=>:parentings
end
class Student < ActiveRecord::Base
has_many :parentings, :dependent=>:destroy
has_many :guardians, :through=>:parentings
end
class Parenting < ActiveRecord::Base
attr_accessible :student_id, :guardian_id
belongs_to :student
belongs_to :guardian
end
inside guardian.rb there was this class method:
def self.shift_user(student)
# find all the guardians having a ward_id = student.d (comment my own)
self.find_all_by_ward_id(student.id).each do |g|
..
end
I want to change it using the newly defined relationshop ie
self.find_all_by_student_id(student.id).each do |g|
..
It doesn't work! I thought it would work since I've already defined that a Guardian has many students through the Parenting class.. I've tried several permutations of the command above and I keep on getting the error:
undefined method `find_all_by_student_id' for #<Class:0x1091c6b28>
ideas? I'm using ruby 1.8.7 and RoR 2.3.5
Guardian has no propety student_id so there is no method find_all_by_student_id. So I don't understand why you are confused. Why don't you just use student.guardians?
You can do this using a named scope and a more complex query
class Guardian < ActiveRecord::Base
has_many :parentings, :dependent=>:destroy
has_many :students, :through=>:parentings
named_scope :find_all_by_student_id, lambda {|student_id|
{ :all,
:select => "guardians.*",
:joins => "JOIN parentings ON parentings.guardian_id = guardians.id
JOIN students ON students.id = parentings.student_id",
:conditions = ["students.id = ?", student_id] } }
end

Ruby / Rails - Can I use a joined table's scope(or class method) as part of my WHERE clause?

I want to grab all the categories that contain purchaseable products.
class Product < ActiveRecord::Base
belongs_to :category
scope :purchaseable, where(:available => true)
end
class Category < ActiveRecord::Base
has_many :products
scope :with_purchaseable_products, ?????
end
So, I'm trying to define :with_purchaseable_products. This works:
scope :with_purchaseable_products, joins(:products).where("products.available is true").group(:id).having('count(products.id) > 0')
But that's not very DRY. Is there any way to apply my :purchaseable scope to products in my :with_purchaseable_products scope?
Thanks.
You should use the merge method
class Category < ActiveRecord::Base
has_many :products
scope :with_purchaseable_products, joins(:products).merge(Product.purchaseable).group(:id).having('count(products.id) > 0')
end
Read more on http://asciicasts.com/episodes/215-advanced-queries-in-rails-3

Model Relationship Problem

I am trying to calculate the average (mean) rating for all entries within a category based on the following model associations ...
class Entry < ActiveRecord::Base
acts_as_rateable
belongs_to :category
...
end
class Category < ActiveRecord::Base
has_many :entry
...
end
class Rating < ActiveRecord::Base
belongs_to :rateable, :polymorphic => true
...
end
The rating model is handled by the acts as rateable plugin, so the rateable model looks like this ...
module Rateable #:nodoc:
...
module ClassMethods
def acts_as_rateable
has_many :ratings, :as => :rateable, :dependent => :destroy
...
end
end
...
end
How can I perform the average calculation? Can this be accomplished through the rails model associations or do I have to resort to a SQL query?
The average method is probably what you're looking for. Here's how to use it in your situation:
#category.entries.average('ratings.rating', :joins => :ratings)
Could you use a named_scope or custom method on the model. Either way it would still require some SQL since, if I understand the question, your are calculating a value.
In a traditional database application this would be a view on the data tables.
So in this context you might do something like... (note not tested or sure it is 100% complete)
class Category
has_many :entry do
def avg_rating()
#entries = find :all
#entres.each do |en|
#value += en.rating
end
return #value / entries.count
end
end
Edit - Check out EmFi's revised answer.
I make no promises but try this
class Category
def average_rating
Rating.average :rating,
:conditions => [ "type = ? AND entries.category_id = ?", "Entry", id ],
:join => "JOIN entries ON rateable_id = entries.id"
end
end

Rails: order using a has_many/belongs_to relationship

I was wondering if it was possible to use the find method to order the results based on a class's has_many relationship with another class. e.g.
# has the columns id, name
class Dog < ActiveRecord::Base
has_many :dog_tags
end
# has the columns id, color, dog_id
class DogTags < ActiveRecord::Base
belongs_to :dog
end
and I would like to do something like this:
#result = DogTag.find(:all, :order => dog.name)
thank you.
In Rails 4 it should be done this way:
#result = DogTag.joins(:dog).order('dogs.name')
or with scope:
class DogTags < ActiveRecord::Base
belongs_to :dog
scope :ordered_by_dog_name, -> { joins(:dog).order('dogs.name') }
end
#result = DogTags.ordered_by_dog_name
The second is easier to mock in tests as controller doesn't have to know about model details.
You need to join the related table to the request.
#result = DogTag.find(:all, :joins => :dog, :order => 'dogs.name')
Note that dogs is plural in the :order statement.

Resources