Rails 3 : Mass update - ruby

I want to use mass-update every operation in a single view, with a single update button. Using this following code, Rails thows this error
Showing /home/vincent/git/gestion/app/views/operations/tag.html.erb where line #23 raised:
undefined method `merge' for 1:Fixnum
Extracted source (around line #23):
20: <td>
21: <% #tags.each do |elem| %>
22: <%= f.label elem.tag %>
23: <%= f.check_box "operation[tag_ids][]", elem.id, operation.tags.include?(elem) %>
24: <% end %>
25: </td>
26: <td><%= f.submit %></td>
Models
class Operation < ActiveRecord::Base
attr_accessible :credit, :date_operation, :debit, :libelle, :tag_ids
has_and_belongs_to_many :tags
accepts_nested_attributes_for :tags, :allow_destroy=>true
end
class Tag < ActiveRecord::Base
attr_accessible :id, :tag
has_and_belongs_to_many :operations
end
Controller
def tag
#operations = Operation.limit(100)
#tags = Tag.all
respond_to do |format|
format.html { "tag" }# tag.html.erb
# format.json { render json: #operations }
end
end
View
<% #operations.each do |operation| %>
<tr>
<td><%= operation.date_operation %></td>
<td><%= operation.libelle %></td>
<td><%= operation.credit %></td>
<td><%= operation.debit %></td>
<%= form_for operation do |f| %>
<td>
<% #tags.each do |elem| %>
<%= f.label elem.tag %>
<%= f.check_box "operation[tag_ids][]", elem.id, operation.tags.include?(elem) %>
<% end %>
</td>
<td><%= f.submit %></td>
<% end %>
</tr>
<% end %>
Do you have any clue/help about this problem?
Thank you in advance
Edit 1 : adding full stack trace

You need to change the f.check_box for check_box_tag, for instance:
<%= check_box_tag "operation[tag_ids][]", elem.id, operation.tags.include?(elem) %>
The problem in this scenario is that f.check_box is expecting that the value is bounded to the form which in not in this case.

use nested_form gem for this case i think it will work.
for more about nested_form Click here

Related

approve multiple records at once

how to achieve this Scenario:
admin to select multiple records using a checkbox and click a button to approve selected, which will change the status of the selected items to approved at once. records are like posts.
here is my code:
config/routes:
resources :time_cards do
collection do
get 'management'
put 'approve_multiple'
end
member do
get 'review'
get 'tracking'
patch 'approve_or_reject'
end
end
html:
<%= form_tag({controller: 'time_cards', action: 'approve_multiple'}, method: 'put', id: 'approve_multiple_time_card_form') do %>
<% #time_cards.each do |time_card| %>
<tr>
<% if time_card.status.downcase == 'submitted' %>
<td><%= check_box_tag "time_cards_to_approve[]", time_card.id %></td>
<% else %>
<td> </td>
<% end %>
<td><%= time_card.id %></td>
<td><%= time_card.week_of.to_date.strftime('%B %-d, %Y') %></td>
<td><%= time_card.user.name %></td>
<td><%= time_card.status %></td>
<td><%= output_hours(time_card.time_card_entries) %></td>
<td>
<%= link_to review_time_card_path(time_card) do %>
<% if time_card.status.downcase == 'submitted' %>
<i class="material-icons">edit</i>
<% end %>
<% end %>
</td>
</tr>
<% end %>
<%= submit_tag "Approve Selected", class: 'btn btn-success' %>
<% end %>
controller:
#PUT /time_cards/approve_multiple
def approve_multiple
authorize TimeCard
#time_cards.update_all({status: 'Approved'}, {id: params[:time_cards_to_approve]})
respond_to do |format|
if !#time_cards.errors
format.json { render json: { notice: 'Time cards approved successfully.'} }
format.html { redirect_to redirect_to management_time_cards_path, notice: 'Time cards approved successfully.'}
else
format.json { render json: { error: #time_cards.errors, alert: 'There was a problem approving the time card.'}}
format.html { redirect_to management_time_cards_path, alert: #time_cards.errors}
end
end
end
??? I don't no where it is wrong?
Send these ids to an action like this
Post.where(id: params[:ids]).update_all(approved: true)
params[:ids] is an array of posts' ids
update_all returns the number of the updated records
Ops, I took for granted we were talking about rails but it's never mentioned.

Ruby - Nesting objects through input values

Hello my fellow companion!
What I'm trying to achieve is a system by which an Order form is compiled in two ways:
by fullfilling its own attributes (:sender_name, :sender_mobile etc..)
by selecting products through the price labels attached on them.
After a while of poking here and there, I managed to display the product list on the order form. Here the 3 models and the views
models/order.rb
class Order < ActiveRecord::Base
attr_accessible :sender_comment, :sender_email, :sender_mobile, :sender_name, :order_attributes
has_many :products
accepts_nested_attributes_for :products
end
models/product.rb
class Product < ActiveRecord::Base
belongs_to :order
attr_accessible :product_name, :product_description, :prices_attributes, :order_id
has_many :prices
accepts_nested_attributes_for :prices
end
models/price.rb
class Price < ActiveRecord::Base
belongs_to :product
attr_accessible :product_id, :price_label, :price_amount, :price_checked, :how_many_prices, :products_attributes
end
views/orders/_form.html.erb
<%= form_for(#order) do |f| %>
<div class="field">
<%= f.label :sender_name %><br />
<%= f.text_field :sender_name %>
</div>
# [...] other order's fields...
<%= f.fields_for :product do |builder| %>
<%= render "products_field", :f => builder %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
views/orders/_products.html.erb
<% #products.each do |p| %>
<td><%= p.product_name %></td>
<td><%= p.product_description %></td><br />
<% p.prices.each do |price| %>
<td><%= price.price_label %></td><br />
<td><%= price.price_amount %></td><br />
<td><input type="radio" class="order_bool" name="<%= p.product_name %>" <% if price.price_checked == true; puts "SELECTED"; end %> value="<%= price.price_amount%>"/></td><br />
<% end %>
<% end %>
Products and relatives prices are printed in the Order form, yet once selected they're not saved as order_attributes; along with the order's attributes, every radio selected generates an object like this
[#<Product id: nil, order_id: 23, product_name: nil, product_description: nil, created_at: nil, updated_at: nil>]
How can I convert the selected products into effective order_attributes?
This is my first project with OOP and that I'm learning all by myself, with a very few help but from the internet. Please don't be too harsh!
Also feel free to change the title if you don't consider it appropriate enough; english is not my native language and i find very difficult to recap this issue in just a few words.
Thanks for the patient :)
Basically your current _products_fields partial isn't even attached to the form object. You're building arbitrary inputs right now. See form_for documentation and fields_for documentation and radio_button documentation.
Note: When you use f.method_name you're actually going to call the FormBuilder versions of the method and not the FormHelper versions. Since the FormHelper version has more and still relevant documentation that's the better version. Just omit the object_name parameter.
I think changing a these lines should do the trick:
Form Partial:
<%= f.fields_for :products, #products do |builder| %>
<%= render "products_field", :f => builder %>
<% end %>
Products Fields Partial
# 'f' is the variable passed in using ':f => builder'
# So 'f' = builder
# f.object is accessing the object were building the fields for
<td><%= f.object.product_name %></td>
<td><%= f.object.product_description %></td><br />
<% f.object.prices.each do |price| %>
<td><%= price.price_label %></td><br />
<td><%= price.price_amount %></td><br />
<td><%= f.radio_box("price", price.price_amount %></td><br />
<% end %>

How can I render partial in show.html.erb

I have these two models in my Ruby on Rails application - Artist and Song. They are associated as follows:
class Artist < ActiveRecord::Base
has_many :songs
attr_accessible :artist_name
and
class Song < ActiveRecord::Base
belongs_to :artist
attr_accessible :title, :track_URL, :artist_id
I have this code in views/artist/show.html.erb:
<%= render 'artist_song' %>
<table>
<% #artist.songs.each do |song| %>
<tr>
<td><%= song.title %></td>
</tr>
<% end %>
</table>
The partial Im trying to render(_artist_song.html.erb) in the same view looks like this:
<table>
<% #artist = Artist.all %>
<% #artist.each do |artist| %>
<tr>
<td><%= link_to artist.artist_name, artist %></td>
</tr>
<% end %>
</table>
The way it is suppose to work is when I click on an artist shown trough the partial, the code below the partial has to show me all the songs that belongs to the particular artist.
Both the partial and the code in the table tag are working individually. But when I put them together, it looks like there is a conflict between them and the server is showing me this No Method Error:
NoMethodError in Artists#show
Showing C:/Sites/OML/app/views/artists/show.html.erb where line #9 raised:
undefined method `songs' for #<Array:0x5fe1418>
Extracted source (around line #9):
6:
7:
8: <table>
9: <% #artist.songs.each do |song| %>
10: <tr>
11: <td><%= song.title %></td>
12: </tr>
Rails.root: C:/Sites/OML
Application Trace | Framework Trace | Full Trace
app/views/artists/show.html.erb:9:in `_app_views_artists_show_html_erb__950110288_54062208'
app/controllers/artists_controller.rb:21:in `show'
I couldn`t find a solution. Any help will be appreciated.
Thank you.
You are not using a partial. You need to render the partial inside the artist loop:
show.html.erb
<table>
<% #artists = Artist.all %>
<% #artists.each do |artist| %>
<tr>
<td><%= link_to artist.artist_name, artist %></td>
</tr>
<%= render :partial => 'artist_song', :artist => artist %>
<% end %>
</table>
This way, you are passing the current artist object to inside the partial, so there you can do:
artist_song.html.erb
<% artist.songs.each do |song| %>
<tr>
<td><%= song.title %></td>
</tr>
<% end %>

Accessing data through associations

I'm very green when it comes to RoR and am having trouble trying to figure out whether my issue is caused by a problem in my model associations or whether I'm just not using the right syntax to access the data.
A user can have many budgets. Each budget is comprised of multiple detail lines. I thought there wasn't a need for the user id in budget_details since it's captured in budget and so can be inferred through the relationship between the three (maybe?!)
In the budget_details index I want to be able to include the users name; I've got it to work in the 'show' view but not the index.
I did use a scaffold to set these up, so I know there's a lot of crud there, I was just trying to do an example before moving to a new project to do it for real.
The actual error is;
NoMethodError in Budget_details#index
Showing C:/Sites/example1/app/views/budget_details/index.html.erb where line #17 raised:
undefined method `name' for nil:NilClass
I can't see why this fails but the show method works? Is is something to do with the scope? ie show is at the single instance level whereas index is at the 'all' level and so it can't find the data in Users?
Any help much appreciated
Models:
User.rb
class User < ActiveRecord::Base
attr_accessible :email, :name
has_many :budgets
has_many :budget_details, :through => :budgets
Budget.rb
class Budget < ActiveRecord::Base
attr_accessible :budget_name, :user_id
belongs_to :user
has_many :budget_details
Budget_details.rb
class BudgetDetail < ActiveRecord::Base
attr_accessible :amount, :amount_type, :budget_id, :itemname
belongs_to :budget
Controller - budget_details_controller.rb
class BudgetDetailsController < ApplicationController
# GET /budget_details
# GET /budget_details.json
def index
#budget_details = BudgetDetail.all
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #budget_details }
end
end
# GET /budget_details/1
# GET /budget_details/1.json
def show
#budget_detail = BudgetDetail.find(params[:id])
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #budget_detail }
end
end
.....
show.html.erb
<%= notice %>
<p>
<b>Username:</b>
<%= #user.name %>
</p>
<p>
<b>Budget:</b>
<%= #budget_detail.budget_id %>
</p>
<p>
<b>Itemname:</b>
<%= #budget_detail.itemname %>
</p>
<p>
<b>Amount:</b>
<%= #budget_detail.amount %>
</p>
<p>
<b>Amount type:</b>
<%= #budget_detail.amount_type %>
</p>
<%= link_to 'Edit', edit_budget_detail_path(#budget_detail) %> |
<%= link_to 'Back', budget_details_path %>
index.html.erb
<h1>Listing budget_details</h1>
<table>
<tr>
<th>Username</th>
<th>Itemname</th>
<th>Budget</th>
<th>Amount</th>
<th>Amount type</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #budget_details.each do |budget_detail| %>
<tr>
<td><%= #user.name %></td>
<td><%= budget_detail.itemname %></td>
<td><%= budget_detail.budget_id %></td>
<td><%= budget_detail.amount %></td>
<td><%= budget_detail.amount_type %></td>
<td><%= link_to 'Show', budget_detail %></td>
<td><%= link_to 'Edit', edit_budget_detail_path(budget_detail) %></td>
<td><%= link_to 'Destroy', budget_detail, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br />
In your index.html.erb file:
<td><%= #user.name %></td>
You haven't defined #user in your index action - hence the error.
You can avoid this problem and altogether directly pulling #user in the controller for either action, if just use the association:
<td><%= budget_detail.user.name %></td>
And to avoid the performance hit for doing so (N+1), you can eager-load them in your controller using includes:
#budget_details = BudgetDetail.includes(:user).all
However, this association doesn't yet exist - you will need to add a 'has-one-through' relationship to your BudgetDetail class - the reverse of what you did for your User class.
has_one :user, :through => :budget
To summarize:
You should add a user association to BudgetDetail as 'has-one-through'.
Your controller actions should look like this:
def index
#budget_details = BudgetDetail.includes(:user).all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #budget_details }
end
end
def show
#budget_detail = BudgetDetail.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #budget_detail }
end
end
And in your views don't use #user.name rather:
<%= budget_detail.user.name %>
The error indicates that #user.name errors because #user is nil.
In your controller you currently seem to fetch:
def index
#budget_details = BudgetDetail.all
#users = User.all
end
def show
#budget_detail = BudgetDetail.find(params[:id])
#user = User.find(params[:id]) # THIS WOULD MEAN THAT A USER HAS THE SAME ID AS THE BUDGET_DETAIL
end
As the index action fetches the variables for the index template, you see that you aren't fetching any #userthere, just an #usersvariable that holds all users.
Instead, you should remove the user fetching in both actions, and fetch them in the view through the budget_detail.user association.
def index
#budget_details = BudgetDetail.all
end
def show
#budget_detail = BudgetDetail.find(params[:id])
end
show.html.erb
<p>
<b>Username:</b>
<%= #budget_detail.user.name %>
</p>
<% #budget_details.each do |budget_detail| %>
<tr>
<td><%= budget_detail.user.name %></td>
...
</tr>
<% end %>

NoMethodError in Awards#index

I am just starting on rails and found a problem which I can't solve. I am creating a simple app with two models (awards and students). :award has_one :student and :student belongs_to :award
I was told that in app/views/awards/ in show.html.erb, replace:
<%= #award.student_id %>
with:
<%= #award.student.given_name %> <%= #award.student.family_name %>
and in index.html.erb, replace:
<%= award.student_id %>
with:
<%= award.student.given_name %> <%= award.student.family_name %>
after this the localhost:3000/students is working fine but localhost:3000/awards is not working and giving following error :-
**NoMethodError in Awards#index**
Showing /home/redblink/rbtest/students/app/views/awards/index.html.erb where line #17 raised:
undefined method `given_name' for nil:NilClass
Extracted source (around line #17):
14: <tr>
15: <td><%= award.name %></td>
16: <td><%= award.year %></td>
17: <td><%= award.student.given_name %> <%= award.student.family_name %></td>
18: <td><%= link_to 'Show', award %></td>
19: <td><%= link_to 'Edit', edit_award_path(award) %></td>
20: <td><%= link_to 'Destroy', award, method: :delete, data: { confirm: 'Are you sure?' } %></td>
please reply asap with the solution.....
The problem is that there is one of the awards record whose corresponding students record is not present so its returning nil and u can call given_name on nil.
So you can handle it as:
Write following:
<%= award.student ? award.student.given_name : '' %> <%= award.student ? award.student.family_name : '' %>
instead of
<%= award.student.given_name %> <%= award.student.family_name %>

Resources