List with nested resources - ruby

I have a Rails 3.2.1 application where:
class Article < ActiveRecord::Base
belongs_to :category
class Category < ActiveRecord::Base
has_many :articles
In routes:
resources :categories, :shallow => true do
resources :articles
end
I want to display in my Articles#index all the categories with a list of their articles.
In my articles controller:
def index
#Categories
#categories = Category.all
#category = Category.find(params[:category_id]) if params[:category_id].present?
#category_articles = #category.present? ? #category.articles : Article.where("created_at >= ?", Time.now - 3.days).order("views DESC", :limit => 5).offset(1)
#feature_article = #category.present? ? #category.articles : Article.where("created_at >= ?", Time.now - 3.days).order("views DESC").first
end
My view (articles#index)
<% #categories.each do |category| %>
<%= link_to category.name, category %> <!-- category name -->
<%= link_to #feature_article.title, #feature_article %> <!-- feature article -->
<% #category_articles.each do |article| %> <!-- Each category articles -->
<%= link_to article.title, article %>
<% end %>
<% end %>
The problem is that it list all the categories but it seems not to respect the category_id param.
In each category it shows all articles, not the articles of each category.

Related

LoadError: Unable to autoload constant Review, Failure/Error: #review = Review.new

I am getting the following error in my tests in this Ruby project I am doing. I can't seem to figure out why.
Below is my controller.
class ReviewsController < ApplicationController
def new
#restaurant = Restaurant.find(params[:restaurant_id])
#review = Review.new
end
def create
#restaurant = Restaurant.find(params[:restaurant_id])
#restaurant.reviews.create(review_params)
end
private
def review_params
params.require(:review).permit(:thoughts, :rating)
end
end
Below is my view for the Reviews.
<%= form_for [#restaurant, #review] do |f| %>
<%= f.label :thoughts %>
<%= f.text_area :thoughts %>
<%= f.label :rating %>
<%= f.select :rating, (1..5) %>
<%= f.submit 'Leave Review' %>
<% end %>
I can't seem to figure out what is wrong.
The model for the Review is wrong. My model was referring to the wrong class.
class Restaurant < ApplicationRecord
belongs_to :restaurant
end
When it should have been the following.
class Review < ApplicationRecord
belongs_to :restaurant
end

Artists Group_by nested attribute Order_date

I have created a functioning e-commerce platform where Members can buy songs. Everything works fine, But I would like to group all of my Orders in my Index Page by Month.
Currently I am able to group each Album with its corresponding Artist, and each Ordered Song to its corresponding Album. But now I would like to group Orders by Month.
How Can I Group Artists by the order_date in my Orders Table, So that everything is organized by Month?
Ex. of what I've like to do
Month 1 Orders
Artist1
Album1 ###List of Albums Corresponding to an Artist
--Song1 (10 0rders)
--Song3 (5 Orders)
Album2
--Song5 (2 Orders) ###Ordered Songs Corresponding to an Album
Month 2 Orders
Artist2
Album1
--Song2 (1 Order)
Artist3
Album3
--Song5 (1 Order)
MODELS
class Order < ActiveRecord::Base
attr_accessible :artist_id, :album_id, :song_id, :user_id, :order_date
belongs_to :song
belongs_to :user
end
class Artist < ActiveRecord::Base
attr_accessible :name
has_many :albums
has_many :songs, :through => :albums
has_many :orders, :through => :songs
end
class Album < ActiveRecord::Base
attr_accessible :name, :artist_id
belongs_to :artist
has_many :songs
has_many :orders, :through => :songs
end
class Song < ActiveRecord::Base
attr_accessible :artist_id, :album_id, :title, :price
belongs_to :album
has_many :orders
end
CONTROLLERS
###How Can I Group Artists by the order_date in my Orders Table?
def index
#artists = Artist.includes(:orders).where('orders.id IS NOT NULL')
end
VIEWS
<% #artists.each do |artist| %> ###Lists All Artists with Orders
<h3><%= artist.name %></h3>
<% artist.albums.each do |album| %> ###Lists All Albums corresponding to Artist
<h4><%= album.name %></h4>
<% album.songs.each do |song| %> ###Lists All Ordered Songs corresponding to Albums
<% if song.orders.count >= 1 %>
(<%= song.orders.count %>)
<%= song.title %>
$<%= song.price %><br>
<% end %>
<% end %>
<% end %>
<% end %>
You get the list of orders ok with this line:
<% #order_months.sort.each do |month, orders| %>
But then you jump back into your full list of artists with this line:
<% #artists.each do |artist| %> ###Lists All Artists with Orders
Instead I think you need something like
<% orders.each do |order| %>
<% order.artists.each do |artist| %>
<% artist.albums.each do |album| %>
<% album.songs.each do |song| %>
<%= song.name %>
To get order.artists you will need to modify your model:
class Order < ActiveRecord::Base
attr_accessible :artist_id, :album_id, :song_id, :user_id, :order_date
belongs_to :song
belongs_to :user
has_many :albums, through: :song
has_many :artists, through: :albums
end
This is how I ended up Solving the Problem
Controller
#orders = Order.find(:all, :order => 'order_date, id', :limit => 50)
Views
<% #orders.sort.group_by { |order| order.order_date.beginning_of_month }.each do |month, orders| %>
<h3><%= month.strftime('%B') %> </h3>
<% orders.group_by { |order| order.song.album.artist }.each do |artist, orders| %>
<h4><%= artist.name %> </h4>
<% orders.group_by { |order| order.song.album }.each do |album, orders| %>
<h5><%= album.name %> </h5>
<% orders.group_by { |order| order.song }.each do |song, orders| %>
<p>(<%= orders.count %>) <%= song.title %> </p>
<p><%= song.price %> </p>
<% end %>
<% end %>
<% end %>
<% end %>

Group Book Orders by Author

I have created a functioning e-commerce platform where Members can buy books. Everything works fine, But I would like to group all of my Orders in my Index Page by Author.
Currently I am able to group each Author, but then every existing Book Order gets listed under each Author. As oppose to only listing the Book Orders corresponding to that Author.
EX. of what I'd like in my Orders Page
###Orders grouped by Authors
Author1
Book1 belongs_to Author1 ###BookOrders grouped by Author
Book2 belongs_to Author1
Book3 belongs_to Author1
Author2
Book1 belongs_to Author2
Book2 belongs_to Author2
Author3
Book1 belongs_to Author3
MODELS
class Order < ActiveRecord::Base
attr_accessible :author_id, :book_id, :user_id, :order_date
belongs_to :book
belongs_to :user
end
class Book < ActiveRecord::Base
attr_accessible : author_id, :title, :price
belongs_to : author
has_many :orders
end
class Author < ActiveRecord::Base
attr_accessible :name
has_many :books
end
CONTROLLER
def index
###How Can I combine this so it Groups Book Orders By Author
###Groups Orders by Author
#orders = Order.find(:all, :order => 'author_id, id', :limit => 50)
#author_orders = #orders.group_by { |order| order.book.author.name }
###Groups Orders by Book
#orders = Order.find(:all, :order => 'author_id, id', :limit => 50)
#book_orders = #orders.group_by { |order| order.book.title }
end
VIEWS
<% #author_orders.each do |author, orders| %>
<h2><%= author %> </h2>
<% #book_orders.each do |book, orders| %>
<h4><%= book %> </h4>
<% end %>
<% end %>
Why not instead:
Model:
class Author < ActiveRecord::Base
attr_accessible :name
has_many :books
has_many :orders, through: :books
end
Controller:
def index
#authors = Author.includes(:orders)
end
View
<% #authors.each do |author| %>
<h2><%= author.name %> </h2>
<% author.orders.each do |order| %>
<h4><%= order.book.title %> </h4>
<% end %>
<% end %>
Update:
To display only those authors who have an order you need unfortunately to do some gymnastics. Also previous includes will not save you completely from N+1 and needs to be improved.
#authors = Author.includes(orders: :books).where('orders.id IS NOT NULL')
You are really close I think.
You just need to get your books from the order that belongs to the author.
Like this...
<% #author_orders.each do |author, orders| %>
<h2><%= author %> </h2>
<% orders.each do |order| %>
<h4><%= order.book %> </h4>
<% end %>
<% end %>

will _paginate in show views

I have Categories view which list some items based on which categories the belong
now i want to paginate items on that category
So, in category controllerI have
<code>
def show
#category = Category.find(params[:id])
end
</code>
and in views/categories/show.html.erb
<code>
<%= will_paginate %>
<ul>
<% #category.photos.each do |photo| %>
<li><%= link_to image_tag( photo.image_url(:thumb).to_s ), photo %></li>
<% end %>
</ul>
<%= will_paginate %>
</code>
How to paginate those items ??
I cant understand the documentation github will_paginate however i know that if its just I can easily replace Category.all with
Category.paginate(:page => params[:page], :per_page => 20, :order => 'created_at DESC')
please help??
Try:
def show
#category = Category.find(params[:id])
#photos = #category.photos.order('created_at DESC')
.paginate(page: params[:page], per_page: 20)
end
and in your view, change:
<% #category.photos.each do |photo| %>
into:
<% #photos.each do |photo| %>

Adding comment as "most commented" on my view?

I have a Rails 3 blog, which has Article and Comment models in has_many and belongs_to associations. When an article comment is > 3, I should see it in my application.html.erb views so I can call it "most commented".
<div class="span2">
<%=image_tag ("Lekki_Gardens_new.gif") %>
<br><br>
<b><p>News update</p></b>
<% #articles.first(4).each do |article| %>
<%=image_tag article.avatar_url(:lilthumb).to_s, :class=>"img-polaroid" %><br>
<%= link_to article.name, article%><hr>
<% end %>
</div
You can use the :counter_cache option in your article model and then use a scope to retrieve the most commented ones.
class Article < ActiveRecord::Base
has_many :comments, counter_cache: true
scope :most_commented, where('comments_count > 3')
end
And then in your template:
<% Article.most_commented.each do |article| %>
<% # anything you want %>
<% end %>

Resources