group_by two parametrs - ruby-on-rails

In the tasks_controller, I defined:
def index
#tasks = Task.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #tasks }
end
end
I have three parameters in my table: name, task, done.
now, I want to produce:
<table>
<tr>
<th>Name</th>
<th>num of tasks</th>
<th>num tasks left</th>
</tr>
<% #tasks.group_by(&:name).each do |name, tasks| %>
<tr>
<td><%= name %></td>
<td><%= tasks.size %></td>
<td> here I want to produce the number of tasks left </td>
</tr>
<% end %>
</table>
how can I get the number of tasks left? I think it should be something like:
<% #tasks.group_by(&:name).each do |name, tasks| %>
<tr>
<td><%= name %></td>
<td><%= tasks.size %></td>
<% #tasks.group_by(name, :done => "yes").each do |name, tasks| %>
<td><%= tasks.size %></td>
<% end %>
</tr>
<% end %>

You had a good idea ;)
<% #tasks.group_by(&:name).each do |name, tasks| %>
<tr>
<td><%= name %></td>
<td><%= tasks.size %></td>
<td><%= tasks.select{ |task| task.done != 'yes' }.size %></td>
</tr>
<% end %>
tasks.select{ |task| task.done != 'yes' } : This will select the tasks where done is not yes, put it in an array and calculate its size (number of tasks not done yet).
I strongly recommend you to set your #tasks variable like following (takes much less performances: the DB does the work for you!)
# in the controller
#tasks = Task.count(:group => 'name') #instead of #tasks = Task.all
It has the same output as #tasks.group_by(...) but is much better in execution time.

Related

show products that belong to orders on admin pannel

I am trying to show the name of each product that belongs to an order on my admin panel but I cant seem to get it.
here are my associations:
OrderItem belongs_to :product
OrderItem belongs_to :order
Product has_many :order_items
Order has_many :order_items
I have tried two different things:
<tbody>
<% #orders.each do |order| %>
<tr>
<td><%= order.id %></td>
<td><%= order.order_items.product.name %></td>
<td><%= order.total %></td>
</tr>
<% end %>
</tbody>
This gets me this error:
undefined method `name' for #<Array:0x0000000535fbb0>
So then I try to loop through like this:
<tbody>
<% #orders.each do |order| %>
<tr>
<td><%= order.id %></td>
<% order.order_items each do |order_item| %>
<% order_item.products each do |product| %>
<td><%= product.name %></td>
<% end %>
<% end %>
<td><%= order.total %></td>
</tr>
<% end %>
</tbody>
And I get this error:
undefined local variable or method `each' for <Class:0x007fce540aa3f0>:0x007fce5417fed8>
Here is my controller code:
def orders
#orders = Order.all
#order_items = OrderItem.all
#products = Product.all
end
I am not sure where I am going wrong any help would be appreciated, thanks.
You can do this in either way you suggest: just keep an eye on your collections vs. items
First Way:
This one puts all your items in a single <td>
<tbody>
<% #orders.each do |order| %>
<tr>
<td><%= order.id %></td>
<td><%= order.order_items.map{ |o| o.product.name }.join(', ') %></td>
<td><%= order.total %></td>
</tr>
<% end %>
</tbody>
Second Way:
Here, each order_item gets its own <td>
<tbody>
<% #orders.each do |order| %>
<tr>
<td><%= order.id %></td>
<% order.order_items each do |order_item| %>
<td><%= order_item.product.name %></td>
<% end %>
<td><%= order.total %></td>
</tr>
<% end %>
</tbody>
You might consider adding some has_many through or delegate relationships in your models in the long term - it will make this kind of association a little tidier.

Rails 5 controller dumping data from database as an array

I'm just starting out in learning Ruby on Rails. I have the following code in movies_controller.
class MoviesController < ApplicationController
def index
#movies = Movie.all
end
end
and my index.html.erb has a table structure to display the data from the database as follows:
<h4><%= pluralize(#movies.size, 'Movie') %> Found</h4>
<table>
<tr>
<th>Movie Title</th>
<th>Rating</th>
<th>Gross Revenue</th>
</tr>
<%= #movies.each do |movie| %>
<tr>
<td><%= movie.title %></td>
<td><%= movie.rating %></td>
<td><%= number_to_currency(movie.total_gross) %></td>
</tr>
<% end %>
</table>
The index.html.erb first dumped the whole movies data as an array and then display the data below it in the table structure shown above. Please what have I got wrong? Thanks.
Remove the = sign from the each block
<% #movies.each do |movie| %>
<tr>
<td><%= movie.title %></td>
<td><%= movie.rating %></td>
<td><%= number_to_currency(movie.total_gross) %></td>
</tr>
<% end %>
You have a extra = when you start the loop. That page should look like
<h4><%= pluralize(#movies.size, 'Movie') %> Found</h4>
<table>
<tr>
<th>Movie Title</th>
<th>Rating</th>
<th>Gross Revenue</th>
</tr>
<% #movies.each do |movie| %>
<tr>
<td><%= movie.title %></td>
<td><%= movie.rating %></td>
<td><%= number_to_currency(movie.total_gross) %></td>
</tr>
<% end %>
</table>

link_to create new nested_resource

I defined the next things:
task.rb:
class Task < ActiveRecord::Base
belongs_to :worker
attr_accessible :done, :name
end
worker.rb:
class Worker < ActiveRecord::Base
has_many :tasks
attr_accessible :name
end
I wrote the next code in "views/workers/index.html.erb":
<h1>Listing workers</h1>
<table>
<tr>
<th>Name</th>
<th>Task</th>
<th>Done</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #workers.group_by(&:name).each do |name, tasks| %>
<tr>
<td><%= name %></td>
<td><%= tasks.size %></td>
<td><%= tasks.select{ |task| task.done != 'yes' }.size %></td>
<td><%= link_to 'new Task', new_worker_task_path(name) %></td>
<td><%= link_to 'Show Tasks', worker_tasks_path(name) %></td>
</tr>
<% end %>
</table>
in order to use the link of: new_worker_task_path,
I defined in the task_controller:
def new
#worker = Worker.find(params[:worker_id])
#task = #worker.tasks.new
respond_with(#worker)
end
In addition, I defined: new.html.erb in the views/tasks, that also has: "Hi".
When I pressed the link of: "new task", I got:
Couldn't find Worker with id=alon
Rails.root: /home/alon/projects/TODO
Application Trace | Framework Trace | Full Trace
app/controllers/tasks_controller.rb:48:in `new'
Request
Parameters:
{"worker_id"=>"alon"}
first question: how can I find the worker who I want to add him a task?
second question: as I said, I defined:
<td><%= link_to 'new Task', new_worker_task_path(name) %></td>
why should I have to send the name? I use this value? I don't really understand why this parameter is necessary..
You have to send actual :param_key, which by default is ID.
So,
new_worker_task_path()
# have to receive worker's ID as argument. Or worker object, accepted too...
new_worker_task_path(#worker)
Updated for the 1st question:
Let me guess what you want.
<% #workers.group_by(&:name).each do |name, workers| %>
<tr>
<td><%= name %></td>
<td><%= workers.map {|w| w.tasks.size}.sum %></td>
<td><%= workers.map {|w| w.tasks.select{ |task| task.done != 'yes' }.size}.sum %></td>
<td>
<% workers.each do |worker| %>
<%= link_to 'new Task', new_worker_task_path(worker) %>
<% end %>
</td>
<td>
<% workers.each do |worker| %>
<%= link_to 'Show Tasks', worker_tasks_path(worker) %>
<% end %>
</td>
</tr>
<% end %>

ruby printing database content

I am new in Ruby.
I have to render the database structure, using tutorial i found suitable code:
File index.html.erb:
<h1>Listing tasks</h1>
<table>
<tr>
<th>Title</th>
<th>Content</th>
<th>Date From</th>
<th>Date To</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #tasks.each do |task| %>
<tr>
<td><%= task.title %></td>
<td><%= task.content %></td>
<td><%= task.datefrom %></td>
<td><%= task.dateto %></td>
<td><%= link_to 'Show', task %></td>
<td><%= link_to 'Edit', edit_task_path(task) %></td>
<td><%= link_to 'Destroy', task, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Task', new_task_path %>
Now i want to group tasks by 'date from' value, probably it means that in index.html.erb i should print only dates, and clicking on the date i should call another html file that will render tasks by chosen date.
this can be like
File index.html.erb:
<h1>Listing dates</h1>
<table>
<tr>
<th>Date From</th>
<% #tasks.each do |task| %>
<tr>
<td><%= !!! IF DATE NOT PRINTED THEN PTINT IT task.datefrom %></td>
<td><%= link_to 'Edit', edit_date_path(task, date) %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Task', new_task_path %>
Where edit_date_path(task, date) should refer me to the index_date.html.erb, where i can get selected date and print tasks according to selected date.
Maybe i can get suggestion, it will be much easier is fomebody can help me with that, as task should not be very difficult, but otherwise i can waste quite a lot of time googling.
Thanks,
Urmas.
Editing the question.
This helped a little. what i did now, i changed index.html.erb to
<h1>Listing dates</h1>
<table>
<tr>
<th>Date To</th>
<th></th>
</tr>
<% dates = Array.new %>
<% #tasks.each do |task| %>
<% if ( !dates.include?(task.dateto.strftime("%m.%d.%Y")) ) then
dates.push task.dateto.strftime("%m.%d.%Y")
%>
<tr>
<td><%= task.datefrom.strftime("%m.%d.%Y") %></td>
<td><%= link_to 'Show Date', {:action => "index", :date => task.dateto} %></td> <-- This does not work
</tr>
<%
end
%>
<% end %>
</table>
<br />
<%= link_to 'New Task', new_task_path %>
Where 'Show Date' link link should be made to show_date.html.erb, where is correct code for showing records when input date is passed.
I had added in controller also method
def show_date
#tasks = Task.find(params[:dateto])
#dateto = :dateto
respond_to do |format|
format.html # showdate.html.erb
format.json { render :json => #tasks }
end
end
that can be used in the not working link, to pass data to the 'Show Date' (show_date.html.erb), but i get errors all the time. The problem is with correct calling off the show_date.html.erb, code i will be able to write myself :)
Urmas
in Tasks controller:
add a method
def index_date
#tasks = Task.all
end
and create a index_date.html.erb write
<% #tasks.each do |task| %>
<tr> <td><%= task.datefrom %></td>
<td><%= link_to 'Edit', {:action => "index", :date => task.datefrom} %></td>
</tr>
<%end%>
and in the index method in the controller change
#tasks = Task.all to
#tasks = Task.find_all_by_datefrom(#{params[:date])
This will list the tasks that match the date selected and everything will be similar as it is now thereafter.
Found the solution.
It were necessary to add to routes.rb
resources :tasks do
member do
get 'showdate'
end
get "home/index"
end
add corresponding controller processing
def showdate
#task = Task.find(params[:id])
#tasks = Task.find(:all)
respond_to do |format|
format.html # showdate.html.erb
format.json { render :json => #tasks }
end
end
and to call it using (index.html.erb)
<td><%= link_to 'Show Date', showdate_path(task.id) %></td>
All further processing is already in showdate.html.erb.
Hope this helps somebody.
I AM THE BEST!!!! xD

Rails 3 task scopes?

I am working on a simple rails 3 todo application and I am trying to filter the app by completed tasks and none completed task but whenever I try calling a scope I get the error message.
undefined method `completed' for #<Array:0x007fe8420d0e58>
task.rb
scope :completed , where(:completed => true)
scope :incomplete , where(:finished => false)
index.html.erb
<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Finished</th>
<th>User</th>
</tr>
<% #tasks.each do |task| %>
<tr>
<td><%= task.name %><%= button_to "complete", complete_task_path(task.id)%></td>
<td><%= task.description %></td>
<td><%= task.finished %></td>
<td><%= task.user_id %></td>
<td><%= link_to 'Show', task %></td>
<td><%= link_to 'Edit', edit_task_path(task) %></td>
<td><%= link_to 'Destroy', task, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<%= content_tag :h2, "Stuff Ive done" %>
<table>
<tr>
<th>Name</th>
</tr>
<% #tasks.completed.each do |task| %>
<tr>
<td><%= task.name %></td>
</tr>
<% end %>
</table>
task_controller.rb
def complete
#task = Task.find(params[:task_id])
#task.completed = true
#task.save
redirect_to task_path
end
routes.rb
match "tasks/:id/complete" => "task#complete", :as => :complete_task
Any reasons why rails is giving me this error?
Just by looking at your view (index.html.erb), in one place, you are treating as a relation.
<% #tasks.each do |task| %>
Later in the code, you are trying to access it as a single object.
<% #tasks.completed.each do |task| %>
Since you are seeing the error on the second instance, you need to access 'completed' as in:
<% #tasks.completed.each do |task| %>
<% completed = task.completed %>
<% completed.each do |com| %>
Does this make sense?

Resources