I'm new to Ruby so please excuse my ignorance. I really didn't know how to word this question so this may also be part of the reason I haven't found an answer online.
I'm working with Rho Elements, and I'm trying to pass something from one page to another. I've made some good headway but run into something that I do not understand. I can pass through an ID like so
<input type="hidden" name="id" value="<%= #orderdetails.object %>"/>
I then grab the ID(only doing this right now to make sure I do get the ID)
#id = #params['id']
then redirect to another page
redirect url_for(:action => :newpage, :id => #id).
This is where my problems start. When I debug the application I get past the redirect and enter :newpage
def newpage
#orderdetails = OrderDetails.find(#params['id'])
if #orderdetails
render :action => :newpage, :back => url_for(:action => :index)
else
redirect :action => :index
end
end
Once here I check
#params['id]
and this is what is displayed.
#params {"id"=>"{131113212443313.17}"}
"id" ""
#params {"id"=>"{131113212443313.17}"} is shown by eclipse and when I break into the variable "id" "" is shown.
Why can I see the ID that I want to use to grab the orderdetails that was just created but also have the actual variable be empty?
**EDIT: This is the information I'm trying to pass.
#params {"id"=>"131113212443313.17", "next"=>"asleftnext", "orderdetails"=>
{"AsFoundMeterRead"=>"", "AsFoundImage"=>""}}
"id" "131113212443313.17"
"next" "asleftnext"
"orderdetails" {"AsFoundMeterRead"=>"","AsFoundImage"=>""}
Use params in the controller, not #params. Also the canonical form of accessing keys is params[:id].
Like its say in the previous answer you access the params in the controller in this way
#id = params[:id]
Also if you are using Rails 3 or higher you may want to use the new url way is less verbose so its more easy to read.
newpage_controllername_url(:id => #id)
you can also ask for the path with this method.
If you don't know if you are passing right the params you can display the content using
params.inspect
You can view the content of any object with inspect
Related
I am currently trying to define my first new action in Rails 3, despite various problems I think things are almost done now. However, I as a final hurdle I am struggling to send the correct parameter value to my function...
My function is defined in items_controller:
def clickcountplusone
clickeditem = Item.find(params[:id])
redirect_to clickeditem.externalurl if clickeditem.update_attribute(:click_count, clickeditem.click_count + 1)
end
routes.rb contains:
match '/items/clickcountplusone', :to => 'items#clickcountplusone'
and the view contains:
<%= link_to image_tag( item.picture.to_s + ".gif", send("items_clickcountplusone_path", item.item_name)%>
The view page itself loads correctly (the one with the link on it), but when I click on the link I get an error:
Couldn't find Item with ID=clickcountplusone
{"id"=>"clickcountplusone",
"format"=>"whatever the name is"}
and rather than going to the external page, my browser tries to load:
http://localhost:3000/items/clickcountplusone.whatever the name is
Can anyone tell me how I should be calling the function so that the ID is the item_name and the external URL is visited rather than an incorrect one on my site?
Thanks in advance
It seems like this would be a normal route, instead of a RESTful route (this is fine). There are some places you have to change.
First, in your controller's action, you used params[:id] which is not set actually.
In this particular case, I would suggest you use params[:item_name] instead of id because you are really sending the item_name.
def clickcountplusone
clickeditem = Item.find_by_item_name(params[:item_name])
redirect_to clickeditem.externalurl if clickeditem.update_attribute(:click_count, clickeditem.click_count + 1)
end
Item.find could only be used if the parameter is one of the actual id / :all / :first / :last.
You are finding by the item_name, so you should use Item.find_by_item_name instead.
Second, you have to update you route too (or else you would need something like /you_path..?item_name=blahblahblah which is fine too if you don't mind)
get 'items/:item_name' => 'items#clickcountplusone', :as => :items_clickcountplusone
Third, you view. IMO, most of the time if you are using send but not writing library / really back end code, you probably misusing it.
<%= link_to image_tag("#{item.picture.to_s}.gif"), items_clickcountplusone_path(:item_name => item.item_name) %>
You don't have any variable in your match statement. Try something like
match '/items/clickcountplusone/:id', :to => 'items#clickcountplusone'
and
<%= link_to image_tag(item.picture.to_s + ".gif", items_clickcountplusone_path(:id => item.item_name))%>
My objective is to allow Admins the right to sign Users up for a Project.
Currently, Users can sign themselves up for Projects.
So I was thinking in order to allow Admin to do this.. do something like this :
haml
= link_to "Project Signup", card_signups_path + "?user=#{user.id}", :class => "button"
And pass the params[:user] so I can replace this controller with this :
if params[:user]
#card_signup = User.find(params[:user]).build_card_signup
else
#card_signup = current_user.build_card_signup
end
The trouble is though.. this is a 3 part signup process, and its loaded VIA AJAX, so I can't pass the ?user=#{user.id} in any of the steps after the first.. ( at least not by the same convention that I already did, or know how to )
What kind of strategy would you employ in this?
One possible way of accomplishing this, would be to add a hidden field to your form, that mirrors the parameter your passing in, if its found.
So if the parameter your passing in is user, in your view you want to add a hidden field something like:
<input type="hidden" name="user" and value="<%= params[:user] %>" />
or with a rails form helper:
hidden_field_tag 'user', params[:user]
This way the code in your controller can check for this parameter at each step on the receiving end and know who to save the object for. Something like this:
def create
#card_signup = CardSignup.new(params[:card_signup])
if params[:user] && params[:user].to_i > 0
##
##some logic here to make sure current_user is admin, as no one else is allowed to do this
##
#card_signup.user_id = params[:user]
else
#card_signup.user_id = current_user.id
end
##onto validating model and saving / redirecting / etc
end
But the ultimate goal here is to keep the user param around, whether its an initial GET parameter to the page, or a Put/Post from ajax/etc to submit the form, this parameter will be around.
One other security angle to check would also be in the 'new' action of this controller, and check that if the user param is present then the current_user is an administrator, otherwise redirect or display an error message. This combined with re-validating this on the create should provide a decent way of making sure no one else can make these requests. You could also put this in a before_filter and call it for only new and create to keep things clean.
I was curious on how to use arrays in the link_to method in ruby on rails for example:
Controller:
def index
#test = [1,2,3]
end
View:
<%= link_to "test", {:action => 'index'}, :test => #test %>
When looking at the source then, I end up with something to the effect of:
test
My guess is that the array's to_string or something similar is getting called to set the value of test in the html.
My goal is to be able to have a form in which people can submit data on the page, and then once they've submitted the data and return to the page, if they click on the link the data will persist through clicking on the link.
*Ideally I would like to do this without having to pass the parameters in the url.
Thank you.
If you want to keep data you should probably use cookies. They are very easy to use, just assign a value with the following in the action:
cookies[:some_key] = "some value"
and retrieve it with this:
cookies[:some_key] # returns "some value"
However, just to clarify what link_to is doing in your example:
<%= link_to "test", {:action => 'index'}, :test => #test %>
When looking at the source then, I end up with something to the effect of:
test
The reason is that you are passing #test to the third argument in link_to, which is a hash of html attributes, hence why it's turned into one. To have it become an parameter on the link, you need to pass it with the second, eg, {:action => 'index', :text => #test}. As noted above, however, this is not necessarily the best way to tackle this and, in addition, it's usually best to also pass the controller name to link_to or, better yet, use a named route.
If I understand well, you want to keep the datas submitted by the user after they validate the form ?
Well Rails is able to do that without any of your code line needed.
Based on the supposition that you have a route resource "objects"
In your controller :
def edit
#object = Object.find_by_id params[:id]
end
def update
#object = Object.find_by_id params[:id]
if #object.update_attributes params[:object]
# The datas have been successfully saved. You redirect wherever you want to.
else
render :action => 'edit'
end
end
and in your view :
<% form_for #object do |f| %>
<%= text_field :name %>
<% end %>
When the form fails to validate, the "name" text field automatically gets the previous entered data.
If after that you still need to reload your datas, you don't need to add them as a parameter in a link tag.
You get the object in your controller and passes it's datas to the view where you display it.
I would just write a view helper that formats it into a string with good separators, like commas.
That isn't a good way to be passing along information though. Try session variables, cookies, or url-encoded variables instead.
The best match to what you are doing would be url-encoded variables, which will show up in a form similar to this:
test
My guess is that it is using Array#join.
You could try something like
:test => #test.join( ',' )
and then parse the string in your controller. But it is somewhat error prone if the user enters the same character you chose as delimiter.
But, assuming the linked page is also served by Rails, I think the best solution would be to use the flash area to store the results on the server
flash[ :submitted_params ] = params;
and in the controller for the linked page
old_params = flash[ :submitted_params ] || {}
When I add a new "product" using my scaffold create rails app, the following line properly adds a new product
#product = Product.new(params[:product])
When I try to add a new product using the following URL (trying to POST data up from a java program).
http://localhost:3000/products?serial=555&value=111
The product is not created, however I can access the "serial" and "value" values like this:
#product = Product.new
#product.serial=params[:serial]
#product.value=params[:value]
#product.save
To further confuse me, if I use the rails app to add a new product, the params[:serial] and params[:value] variables are empty.
Can someone please point me in the right direction.
Thanks
The Model.new method takes a hash.
params[:product] actually contains something like {:serial => 555, :value => 111}
The url you would want to use is:
http://localhost:3000/products?product[serial]=555&product[value]=111
(Make sure that you are indeed using POST)
If you want to keep your current url scheme you would have to use:
#product = Product.new({:serial => params[:serial], :value => params[:value]})
You can also determine exactly what is available inside of params by printing it out to console using:
p params
Good luck!
I'm trying to pass a model attribute to a view, after successfully setting it to a new value from inside an action in my controller. But this variable is always nil by the time it gets to the view, so I can't use it to conditionally display stuff. I should add that this attribute is not a field in the database. What am I missing/doing wrong?
Here is the code in my model:
attr_accessor :mode
#getter
def mode
#mode
end
#setter
def mode=(val)
#mode = val
end
...in the controller:
#report.mode = "t"
redirect_to edit_report_path(#report)
...and in my view:
<%= build_report(#report.mode) %>
...but this helper method never gets the variable I just set in the controller. It is nil. What gives? Clearly I'm missing something basic here because this seems like it should be straightforward. Any insight would be greatly appreciated.
Thanks.
edit_report_path generates a URL with the ID of #report in it.
redirect_to essentially creates a whole new request, and goes to that URL. When it gets to edit, all it has is the ID. Usually that's fine - it looks up the object and keeps going, but of course it's not going to have the non-db field you set.
There are a couple ways to fix this. You can use :render instead to get to the edit page - then #report will have the field set.
#report.mode = "t"
render :action => edit and return
Or, you can make mode a database field.
The problem here is in the redirect_to. When you redirect somewhere else all instance variables are lost. So when you set #report.mode = "t" it sets the attribute. But when you redirect that data is lost.
I am assuming the <%= build_report(#report.mode) %> is in edit_report.html.erb and the code from when you set 'mode' is not in the edit action. If this is the case you may be able to pass the report.mode to the edit action in the url like so:
build_report(#report.mode, :mode => "t")
The problem is the redirect_to; you're returning a response to the client that causes it to redo the request with a different url. In that second request the mode isn't set because you didn't save it before wrapping up the first request.