Problem while editing a record - ruby-on-rails

i treid to edit one record of my tables in rails 3 but ann error occured like this :
ActiveRecord::RecordNotFound in WordsController#edit
in my controller:
def edit
#adverb =Adverb.find(:id)
end
and in my view i have :
<% #adverb.each do |av| %>
<tr class="<%= cycle("odd", "even") -%>">
<td><%= av.name %></td>
<td><%= av.bedeutung %></td>
<td>
<%= link_to 'edit',{:controller => 'words',:action => 'edit',:id=> av.id} %>
</td>
</tr>
<% end %>
how can i solve this problem?

Try
#adverb = Adverb.find(params[:id])

its just
#adverb = Adverb.find(params[:id])
You dont need the .first option on the end thats only needed when using the where statement

:id is just a symbol, you are looking for that symbol's value inside the params hash
So instead of
Adverb.find(:id)
Use
Adverb.find(params[:id])
This will return a single record that matches the value of :id in params hash that is probably coming form you url /adverbs/:id
If there is no record with the provided ID, then an ActiveRecord::RecordNotFound exception will be raised, which in development will show you a stack trace page, and in production will show a 404 page.

Related

How to update instance with params of another instance from a view

I want to write a method that changes a WorkShift to booked:true and booked_by:current_member.member_id. However I get the error
"undefined method `book' for #< WorkShift:0xc973ce0>"
and I don't understand why. I just want it to be a button and not a separate edit view.
Edit: Turns out I put the book method in the wrong place, but the same method in work_shifts.rb throws a "undefined method `to_model' for true:TrueClass" instead. I'm (obviously) unsure what is the correct way to call a custom method that updates one object with the params of another from a view.
My index view:
<% #work_shifts.each do |work_shift| %>
<tr>
<td><%= work_shift.date %></td>
<td><%= work_shift.booked_by %></td>
<td><%= work_shift.booked %></td>
<td><%= work_shift.start_time.strftime("%H:%M") %></td>
<td><%= work_shift.stop_time.strftime("%H:%M") %></td>
<td><%= button_to 'Book', work_shift.book(current_member) %></td>
<% if current_member.admin? %>
<td><%= link_to 'Edit', edit_work_shift_path(work_shift) %></td>
<td><%= button_to "Ta bort", work_shift, :method=>:delete, :work_shift=>:destroy %></td>
<% end %>
</tr>
<% end %>
WorkShift.rb:
def book(member_id)
self.update(booked:true, booked_by: member_id)
end
routes.rb
resources :work_shifts do
member do
get 'book'
end
end
I'm new to rails and learning on the go, and I'm guessing the solution is trivial, but I just can't find any questions or documentation that helps with what I want to do.
Since you're trying to modify a resource's single field, the book link should be a PATCH request and not GET.
Change your routes to
resources :work_shifts do
member do
patch 'book/:member_id' => 'work_shifts#book', as: 'book'
end
end
This will generate the following route
book_work_shift PATCH /work_shifts/:id/book/:member_id(.:format) workshifts#book
And update your book action as
def book
#work_shift = WorkShift.find(params[:id])
#work_shift.book(params[:member_id])
# redirect to some view
end
And modify your model method accordingly.
def book(member_id)
self.update(booked:true, booked_by: member_id)
end
And replace the your view from
<%= button_to 'Book', work_shift.book(current_member) %>
to a link (You can style it as a button if you want)
<%= link_to 'Book', book_work_shift_path(work_shift, current_member.member_id), method: :patch %>
Thats it!

Pass .each loop reference object in Ruby on Rails

I am writing a code in ruby on rails where I am creating dynamic rows in table which involves a .each loop. I want to pass the .each loop reference object but it gives me an error.
Following is the code:
<% pworkflows.workflow_executions_list.each do |wf| %>
<tr>
<td><%= wf.execution_status %></td>
<td>
<% if(wf.start_timestamp != nil) %>
<%= wf.start_timestamp.localtime; %> UTC
<% end %>
</td>
<td><%= wf.close_status %></td>
<td><%= wf.execution.run_id %></td>
<td><%= button_to "Details",{ :controller => "pages", :action => "mainpage",:rulesetinstance=>rInsId, :ndetails=>wf} %></td>
</tr>
<% end %>
:ndetails=>wf gives an error. wf is not being recognized as a correct syntax to send.
Please suggest a way.
the error being:
undefined local variable or method `id' for #<ComRuleManagement::WorkflowExecutionObject:0x00003da1751528>
When you do this
<%= button_to "Details",{ :controller => "pages", :action => "mainpage",:rulesetinstance=>rInsId, :ndetails=>wf} %>
you are building an html tag. (since button_to is an html helper). The extra options you pass through, in this instance ":rulesetinstance" and ":ndetails" will be used to make extra attributes in the element, like rulesetinstance="123". However, if you pass the wf object through, then rails will call to_s on it, and you'll end up with something that looks like this ndetails="#<Wf:0x7f518dfc6e68>". This is almost certainly not what you want in your html element. Should you be calling another method of the wf object instead?

My controller is -persistently- sending wrong params[:id] in Rails?!

I'm new to Ruby on Rails & to web programming.
In my application I have two models; Directorate which has_many :users, and User which belongs_to :directorate.
When creating a new user, I use <%= f.collection_select(:directorate_id,Directorate.all, :id, :name) %> in the new.html.erb form to assign the new user to specific directorate. However, I want to build a user-friendly interface for the dba that lists all directorates; and listing all users beside each directorate, with a link to assign any user to a specific directorate.
What I did is the following:
In Directorate model, I defined the following function:
def assign_user!(user)
user.update_attributes(directorate_id: #directorate)
end
and in the directorates controller, I defined the following action:
def assign_user
#directorate = params[:directorate]
assign_user! params[:user]
redirect_to directorates_url
end
Now, directorates/index.html.erb contains the following:
<h1>Listing directorates</h1>
<table>
<tr>
<th>Name</th>
<th>Info</th>
</tr>
<% #directorates.each do |directorate| %>
<tr>
<td><%= directorate.name %></td>
<td><%= directorate.info %></td>
<td><%= link_to 'Show', directorate %></td>
<td><%= link_to 'Edit', edit_directorate_path(directorate) %></td>
<td><%= link_to 'Destroy', directorate, confirm: 'Are you sure?', method: :delete %></td>
<%= #directorate = directorate%>
<%= render 'users_form' %>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Directorate', new_directorate_path %>
and, -users_form.html.erb contains the following form (which is supposed to list all users beside each directorate, with a link to assign any user to a certain directorate):
<h1>Listing Users</h1>
<table>
<tr>
<th>User Name</th>
</tr>
<% #users.each do |user| %>
<tr>
<td><%= user.username %></td>
<td><%= link_to 'Assign to Current Directorate', {controller: 'directorates', action: 'assign_user', directorate: #directorate, user: user}, :method => :put %></td>
</tr>
<% end %>
</table>
<br />
Here is the problem, when listing directorates & click on the 'Assign to Current Directorate' I receive the following error:
http://127.0.0.1:3000/directorates/assign_user?directorate=4&user=5
ActiveRecord::RecordNotFound in DirectoratesController#update
Couldn't find Directorate with id=assign_user
Rails.root: /home/ehab/sites/IAMS
Application Trace | Framework Trace | Full Trace
app/controllers/directorates_controller.rb:61:in `update'
Request
Parameters:
{"_method"=>"put",
"authenticity_token"=>"L5tz3hv2IW0meE79qUq0/tjfGKwDlpC23hOeAWtmTvk=",
"directorate"=>"4",
"user"=>"5",
"id"=>"assign_user"}
It's clear that the params is submitting "id"=>"assign_user" which I don't want, what i want is "id"=>"directorate.id" (4 in the above example). What shall I do to fix this issue?!
first of all your routes should say that assign_user is a member method on a certain directorate object:
resources :directorates do
member do
put :assign_user
end
end
second you say you define assign_user! in Directorate model and assign_user in DirectoratesController but both methods imply that they share same object state like instance variable #directorate which is not true
your controller method assign_user should look vaguely like
def assign_user
#directorate = Directorate.find params[:id]
#user = User.find params[:user_id]
#directorate.assign_user! #user
end
and model method should look like
def assign_user!(user)
user.update_attributes(directorate_id: self.id)
end
and even that i would switch around to instead of telling Directorate to change user's attributes you would tell User to assign itself to whatever controller wants.
and the final bit is your link that assigns user to directorate:
link_to 'Assign to Current Directorate',
assign_user_directorates_path(#directorate, :user_id => user)
0 lines of code above were tested for even syntactical correctness, DO NOT copy-paste, read and understand

difficulty setting loop based on params

Here is my controller:
def sedomain
#domain = params[:domain]
#virksomhed = Virksomhed.find(:all)
end
Virksomhed has_one Domain and Domain belongs_to Virksomhed.
That I am trying to achieve is looping through all rows in the domain table based on the params.
Here is a example for the dk domain page. It works fine.
<% #virksomhed.each do |virk| %>
<tr>
<td><%= virk.navn %></td>
<td><%= virk.domain.dk %> kr.</td>
<td><%= virk.domain.dkf %></td>
<td><%= virk.domain.dko %></td>
</tr>
<% end %>
But then I want to make it dynamic:
<% #virksomhed.each do |virk| %>
<tr>
<td><%= virk.navn %></td>
<td><%= virk.domain.#domain %> kr.</td>
<td><%= virk.domain.#domain %></td>
<td><%= virk.domain.#domain %></td>
</tr>
<% end %>
But I get a syntax error. I also think it is a bad solution because of users can access other columns in the Domain table via the params.
You can't dereference variables like this. What you mean to do is use send:
<td><%= virk.domain.send(#domain) %> kr.</td>
You will want to ensure that this user parameter conforms to a list of "known good" ones. There's two ways you might go about doing this, either pre-filtering and throwing an error if it's not valid, or having a method that eats the call quietly if it doesn't conform.
For instance:
#domain =
case(params[:domain])
when 'dk', 'dku', '...'
params[:domain]
else
raise "Hey, what are you doing?"
end
#tadman's answer is good, but i'd like to add my two cents. As #Emily said, you can store your whitelisted domains as a set in a Constant :
require 'set'
DOMAINS = Set.new( %W{dk dkf dko} )
As i understand it, your params[:domain] can either be an array or a string. to check if the domain is whitelisted, you can then do:
# ...
#domains= check_domains( params[:domain] )
# ...
def check_domains( dom )
case dom
when Array
dom if dom.to_set.subset?( DOMAINS )
else
[dom] if DOMAINS.include?( dom )
end
dom ||= []
end
then in your view (or maybe as some helper / partial):
<% if #domains.any? %>
<% #domains.each do |domain| %>
<td><%= virk.domain.send(domain) %> kr.</td>
<% end %>
<% end %>

Returning a hash from controller to a view using a helper

Warning I'm brand new to rails!
While reading through a tutorial it has asked me to place a hash of string keys with decimal values into the products action method (My assumption they are talking about the "def products" in the controller.
In reguards to using the products method in the controller did I place my hash correctly?
In reguards to the placing the information from the hash into a table do I even need the helper method or is there a better way?
My helper needs help and doesn't format the data correctly using .html_safe I
This is what I have so far in my controler:
def products
#hard coded as products in controller
#stuff = {"a"=>200.00, "b"=>150.00, "c"=>100.00, "d"=>9.00, "e"=>15.00, "f"=>20.00 }
end
This is what I have in my product.html.erb file
<%= form_tag(products_path) do %>
<table id="aboutus_table">
<%= products_tabler() %>
</table>
<% end %>
and then the helper...it needs help
def products_tabler
snowholder = #snow_stuff.each {|key,value|puts "<tr><td>#{key}</td><td>#{value}</td><tr>"}
return snowholder
end
puts is probably a mistake, you don't really want to print to standard out in a web service. See if this works?
def products_tabler
snowholder = ""
#snow_stuff.each {|key,value| snowholder += "<tr><td>#{key}</td><td>#{value}</td><tr>"}
return snowholder
end
I realize this is a tutorial, but using a helper that emits hardcoded html is not an improvement over having the html in the view itself.
In this case, it's really simple to do it in the view:
<table id="aboutus_table">
<% #snow_stuff.each do |key, value| %>
<tr>
<td><%= key %></td><td><%= value %></td>
</tr>
<% end %>
</table>
If you really wanted to separate the creation of the rows, a collection partial would be better. Then Rails does the iteration for you. Use this technique when you've got real data (i.e. ActiveRecords instead of hashes).
<table id="aboutus_table">
<%= render :partial => "row", :collection => #stuff %>
</table>
Then the _row partial would contain:
<tr>
<td><%= row.name %></td><td><%= row.value %></td>
</tr>

Resources