rails pagination and where clause with array - ruby-on-rails

Hello i have this models
models/store/store.rb
class Store::Store < ActiveRecord::Base
attr_accessible :name
has_many :store_products
has_many :products, :through => :store_products
end
models/product.rb
class Product < ActiveRecord::Base
attr_accessible :name ...
has_many :store_products
has_many :stores, :through => :store_products
end
models/store/store_product.rb
class Store::StoreProduct < ActiveRecord::Base
set_table_name "stores_products"
attr_accessible :store_id, :product_id
belongs_to :store
belongs_to :product
end
and im getting params['store_ids'] via post to controller action
>> params['store_ids']
=> ["1", "2"]
where i have this code
>> #products = Product.joins(:stores).where("stores.id IN (?)", params[:store_ids])
it throw error
#<NameError: uninitialized constant Product::StoreProduct>
How can i fix this (select products only in some stores) ? :-) Thank you
edit : MORE INFO :
Folder Structure
app/controllers/store/main_controller.rb
app/controllers/store/stores_controller.rb
app/models/store/store.rb
app/models/store/store_product.rb
app/models/product.rb
the code is in
class Store::MainController < ApplicationController
def index
if params['store_ids'] then
#products = Product.joins(:stores)...
else
#products = Product.paginate page: params[:page], order: 'name asc', per_page: 10
end
end
Part of DB Schema:
stores_products
id
product_id
store_id
products
id
name
...
stores
id
name
...
SOLUTION (thanks to Gotva)
class Product < ActiveRecord::Base
attr_accessible :name, ...
has_many :store_products, class_name: "Store::StoreProduct"
has_many :stores, :through => :store_products
end
class Store::Store < ActiveRecord::Base
attr_accessible :name
has_many :store_products, class_name: "Store::StoreProduct"
has_many :products, :through => :store_products
end
class Store::StoreProduct < ActiveRecord::Base
set_table_name "stores_products"
attr_accessible :store_id, :product_id
belongs_to :store, class_name: "Store::Store"
belongs_to :product, class_name: "Product"
end
and finally
#products = Product.joins(:stores).where("stores.id IN (?)", params[:store_ids]).paginate(page: params[:page], order: 'products.name asc', per_page: 10)

try this
#products = Product.joins(:stores).where("#{Store::Store.table_name}.id IN (?)", params[:store_ids]).paginate(page: params[:page], order: 'name asc', per_page: 10)
maybe it will duplicate products so add method uniq after where, this applies distinct in the query

Related

Many to many realationship and join in rails 3

I have following three models
class Rating < ActiveRecord::Base
belongs_to :user
belongs_to :book
end
class User < ActiveRecord::Base
attr_accessible :name, :dob, :mobile
has_many :books, :through => 'ratings'
end
class Book < ActiveRecord::Base
attr_accessible :book_name, :author, :pages
has_many :users, :through => 'ratings'
end
Now I have to find all the "book_name"s of each book which is related the respective user and store it in the array.
Here is code
#book_names = []
#books = Rating.find(:all, 'user_id = ?', current_user.id)
#books.each do |book|
book_info = Book.find(book.id)
#book_names << book_info.book_name
end
Is there any other way for the same or join method.
Yes, there is simple way to do it. Try
#book_names= current_user.books.map(&:book_name)

Use 2 has_many relations or 2 HABTM?

I have Product and Categories models.
Each Product can have many Categories. Each category will have many products.
Am I better off doing 2 HABTM or has_many relations?
I have been told that HABTM is being deprecated - is that true?
Also, for both, I assume I will have to use a join table categories_products. How do I create that? Just a regular migration?
Thanks.
Example of top(number). Updated.
class Product < ActiveRecord::Base
has_many :category_products do
def with_categories
includes(:category)
end
end
has_many :categories, :through => :category_products
def top_categories(number)
category_products.with_categories.order("purchases_count DESC").limit(number).map {|c| c.category} # category included
end
end
class Category < ActiveRecord::Base
has_many :category_products do
def with_products
includes(:product)
end
end
has_many :products, :through => :category_products
def top_products(number)
category_products.with_products.order("purchases_count DESC").limit(number).map {|c| c.product} # product included
end
end
class CategoryProduct < ActiveRecord::Base
belongs_to :product
belongs_to :category
validates_uniqueness_of :product_id, :scope => :category_id
# attribute :purchases_count, :default => 0
end

Rails: Prioritize/sort collection of records

I have a Post model that belongs to a single category and author. Users may create "favorites" for categories and authors. How can I most efficiently query a list of all posts, but with the visitor's preferred categories and/or authors sorted to the top?
class Post < ActiveRecord::Base
belongs_to :category
belongs_to :author
end
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :category # favorite category
belongs_to :author # favorite author
end
class User < ActiveRecord::Base
has_many :favorites
end
class User < ActiveRecord::Base
has_many :favorites
has_many :favorite_categories, :through => :favorites, :source => :category
has_many :favorite_authors, :through => :favorites, :source => :author
end
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :category # favorite category
belongs_to :author # favorite author
end
class Post < ActiveRecord::Base
belongs_to :category
belongs_to :author
named_scope :order_by_user, lambda {|user| where(
:category_id => user.favorite_categories.map(&:id),
:author_id => user.favorite_authors.map(&:id)
)}
end
user = User.first
posts = Post.order_by_user(user)
Alternate: less number of queries, but user model fetches data from Favorite
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :category # favorite category
belongs_to :author # favorite author
end
class User < ActiveRecord::Base
has_many :favorites
def favorite_category_ids
Favorite.where(:user_id => self.id).select(:category_id).map(&:category_id).compact
end
def favorite_author_ids
Favorite.where(:user_id => self.id).select(:author_id).map(&:author_id).compact
end
end
class Post < ActiveRecord::Base
belongs_to :category
belongs_to :author
named_scope :order_by_user, lambda {|user| where(
:category_id => user.favorite_category_ids,
:author_id => user.favorite_author_ids
)}
end
user = User.first
posts = Post.order_by_user(user)
This code is not tested, but gives the idea.

Query (M:N) ordered by relationship attribute

I have a simple many-to-many E-R described as below:
Model order.rb:
class Order < ActiveRecord::Base
has_many :cronologies
has_many :statuses, :through => :cronologies
end
Model cronology.rb:
class Cronology < ActiveRecord::Base
belongs_to :order
belongs_to :status
validates_uniqueness_of :order_id, :scope => :status_id
end
Model status.rb:
class Status < ActiveRecord::Base
has_many :cronologies
has_many :orders, :through => :cronologies
end
This code below lets me get all statuses assigned to an order.
#order.statuses
...but how to get statuses ordered by the "created_at" attribute of the cronology table?
#order.statuses.all(:order => "cronologies.created_at")
or put it into association if you always want it ordered this way.
class Order < ActiveRecord::Base
has_many :cronologies
has_many :statuses, :through => :cronologies, :order => "cronologies.created_at"
end

Recursive :include in Rails ActiveRecord

Say I have these models
class Project < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :project
belongs_to :user
end
class User < ActiveRecord::Base
has_many :comments
end
So that I can do
p = Project.find(1, :include => :comments)
p.comments.collect(&:user).collect(&:name) # this executes select for each user
How do I say I want to also include comment's user?
I believe :include => {:comments => :user} should work.

Resources