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 %>
Related
I'm trying to add students I created in a school, to a teachers period (class). I'm not looking to create a new student in a period, but rather select students from a list I created in the school. I was able to list the students in a period, but cannot add them to the period. I'm unsure if I use the build method or something different. I'm currently getting an undefined method error and am just unsure which way to go from here.
<p id="notice"><%= notice %></p>
<p>
<strong>Class Name:</strong>
<%= #period.period %>
</p>
<%= link_to 'Delete Period', [#period.teacher, #period],
method: :delete,
data: { confirm: 'Are you sure?' } %>
<h2>Add a student to period</h2>
<%= form_for([#period, #period.students.build]) do |f| %>
<p>
<%= check_box_tag "school[student_ids][]", student.id %>
<%= link_to student.name, edit_school_student_path(#school, student) %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
class Period < ActiveRecord::Base
belongs_to :teacher
has_many :students
end
class Student < ActiveRecord::Base
belongs_to :school
has_many :teachers, through: :periods
end
class Teacher < ActiveRecord::Base
belongs_to :school
has_many :periods
has_many :students, through: :periods
end
class School < ActiveRecord::Base
has_many :teachers, dependent: :destroy
has_many :students, dependent: :destroy
has_many :schoolads, dependent: :destroy
end
I have a simple blog app, where I want to be able to create a Post and also create a new Tag for it in the same form, using a nested form.
Post and Tag have a many-to-many relationship, via a join table:
class PostTag < ActiveRecord::Base
belongs_to :post
belongs_to :tag
end
Here's the tag model:
class Tag < ActiveRecord::Base
has_many :post_tags
has_many :posts, :through => :post_tags
validates_presence_of :name
validates_uniqueness_of :name
end
Post model accepts nested attributes for tags:
class Post < ActiveRecord::Base
has_many :post_tags
has_many :tags, :through => :post_tags
accepts_nested_attributes_for :tags
validates_presence_of :name, :content
end
On the posts controller, I permit tags_attributes:
def post_params
params.require(:post).permit(:name, :content, :tag_ids => [], :tags_attributes => [:id, :name])
end
In my form for a new post, where I want to be able to either associate already existing tags (via checkboxes) or create a new one via a nested form using fields_for:
....
<div class="field">
<%= f.collection_check_boxes :tag_ids, Tag.all, :id, :name %><br>
<%= f.fields_for [#post, Tag.new] do |tag_form| %>
<p>Add a new tag:</p><br>
<%= tag_form.label :name %>
<%= tag_form.text_field :name %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My error is "Unpermitted parameters: tag":
Parameters: {"utf8"=>"✓", "authenticity_token"=>"dZnCgFxrvuoY4bIUMMxI7kTLEr/R32pUX55wwHZsS4Q=", "post"=>{"name"=>"post title", "content"=>"post content", "tag_ids"=>[""], "tag"=>{"name"=>"new tag"}}, "commit"=>"Create Post"}
Unpermitted parameters: tag
Change:
<%= f.fields_for [#post, Tag.new] do |tag_form| %>
to
<%= f.fields_for(:tags, Tag.new) do |tag_form| %>
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 %>
I have two models, reservations and tables, with has_many through relationship between them with a join table and model collections, that has a separate attribute called :units_sold
my Reservation model:
class Reservation < ActiveRecord::Base
has_many :tables, through: :collections
has_many :collections
end
my table model:
class Table < ActiveRecord::Base
has_many :reservations, through: :collections
has_many :collections
end
and finally the collection model:
class Collection < ActiveRecord::Base
belongs_to :table
belongs_to :reservation
end
E.g:
A reservation in my name for 9 people (:units_sold) has 2 tables each with a capacity of 6 and I want 4 people in one table and 5 on the second table
What I have currently is this:
reservation_params
def reservation_params
params.require(:reservation).permit( :name, :total_units, table_ids: [],
collection_attributes: [ :units_sold],
table_attributes: [:capacity, :title])
end
and my form to submit a reservation:
<%= form_for [current_user, #account, #reservation] do |f| %>
<header>
<h1>Make your reservation</h1>
</header>
<%= f.text_field :name, placeholder: "Name" %>
<%= f.number_field :total_units, placeholder: "How many people..." %>
<%= f.fields_for :collections do |c|%>
<% #tables.each do |p| %>
<label for="<%= p.title %>"><%= p.title %></label>
<%= c.number_field :units_sold, placeholder: "People per table..." %>
<%= check_box_tag "reservation[table_ids][]", p.id %>
<% end %>
<% end %>
<%= f.submit "Save" %>
<% end %>
How should I do the reservation_params in the reservation controller? And nest the form to accept :units_sold for each table/reservation association
First, you should define the associations like :
has_many :collections
has_many :reservations, through: :collections
as in, first define collections and then reservations through collections. Similarly, update the associations in the Table model.
Then in the reservation model after defining the associations, add the following line:
accepts_nested_attributes_for :collections
In reservation_params, the key "collection_attributes" and "table_attributes" should be "collections_attributes" and "tables_attributes" respectively.
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.