Rails 5.0.0.rc1
Ruby 2.2.5 (can update to latest)
I'd like to think this is possible. I'm making a get request that when a field is selected then the user presses the next button, it goes to another page and that page's url looks like:
http://localhost:3000/food/r/new?utf8=%E2%9C%93&id=2&food=Apple&commit=Next
This looks ugly, to me. Could it be more nicer to look like this:
http://localhost:3000/food/r/new/<some_random_short_string/<name-of-page>
I'd imagine the some_random_short_string would be a hash then in the controller would have something like:
hash = params[:some_random_short_string]
hash[:food] #=> "Apple"
etc...
Not sure how to go about this. Any pointers, please?
Rather than deleting my question, I'll answer it as I will come back to it one day.
'get' exposes data in the url so I went for post. No need for a hash just use params to store the values.
Once page is submitted, the url will look like: http://localhost:3000/food/r/new. In the controller, you use your params:
#selected_food = params[:food]
new.html.erb:
<%= #selected_food %> #=> Apple
Related
I have a model 'Item'. It all works fine, however am not completely satisfied with its show path. I want to use certain parameters from items table to construct a more SEO friendly url. So here is my question..
How can I change my Show action url
from
'mysite.com/items/1'
to
'mysite.com/items/item-name/item-city/item-id' where item-name, item-city, and item-id are dynamic for each specific item.
Is it possible to achieve this without a gem? if yes, how? If no, which gem would you suggest to achieve this in simplest way?
Thanks
One approach to this problem is to use route globbing:
http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
You should be able to do something like this:
get 'items/*names/:id', to: 'items#show', as: :item_names_path
And put whatever you want in *names. This would take a little experimentation to get it right. I might add a method to item to create the names array.
def names
[city.name, name].uniq.compact
end
Then I believe you would call item_names_path(#item.names, #item)
You can do something relatively simple and stays true to Rails by adding a to_param method to your model like so:
def to_param
"#{id}-#{name}-#{city.name}"
end
What this does is every time you use a method like the item_path, it will use the #item.to_param method (this is what it does now, and returns :id). Generating the normal route, but replacing the :id param with the SEO friendly one.
And, on the other end, when you go to find(params[:id]) in the controller in your show, edit, delete, or update actions, it will to a to_i on it and turn it back into an id. This is what it does now, but to_i on an int is still an int.
Your urls will look something like
/items/56-boston-itemname
The other benefit to this, if you happen to change the item name or the city name, it will change all the urls appropriately, but old urls that were sent in email will still work.
I am looking for a way to access a model via its :id.
My project looks like this:
First someone can register himself in a form. Then he gets forwarded to a page where he can edit the things he entered. Now I do not want that you can see something in the URL.
Edit:
I was maybe a little unclear:
There is a form, where you can enter some things. After you submitted those things, you will be forwarded to another page with an URL like 'www.example.com/entry'. There I want to show what the person entered. And I do not want an URL like 'www.example.com/entry?id=12'
I hope that clarified some things
Your answer is a bit lacking in details, so I'll do my best here. Essentially, if you do not want to display the url parameters, then you will have to use the post HTTP method to submit your forms (which you should be doing anyway).
In your routes.rb file, you'll need to define your route to look something like this:
post 'route', to: 'controller#action'
Data submitted via the post method is typically submitted via a form. I would recommend using rails conventions like:
the rails form_for helper --> more details
resources since they typically give you the routes you want. To modify your routes beyond the defaults, I'd advise looking at the rails routing guide.
I want to create an Add to Watchlist column + link after the description field ,so the selected movie to be stored on another rb. page from the admin section called "Watchlist".
The concept is similar to a Shopping Cart,passing the data from one page to another.
How's that possible in ActiveAdmin?
I would appreciate your hints and advices.
I'm not familiar with ActiveAdmin, but if your question is how to pass parameters through link_to, try this:
link_to 'Somewhere', some_path(param_1: 'foo', param_2: 'bar')
When you click through, the params should be present in the query string and in the params hash that Rails provides. You can pull out the values with:
params[:param_1]
params[:param_2]
I'm new to rails and still learning the ropes via railstutorial, but the book does all changes to the db via form submissions (http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html). But how would I go about submitting (updating the db) without this, lets say I want to add some score which is computed on page ,(for example via a js counter - for simplicity lets just say its a constant 10) and my db consists of a column called score. Then after pressing a submit button how would I go about updating the db?
Thanks
Two trivial ways:
Use a form
Use a URL parameter with a link
The processing (other than GET v. POST) on the Rails side is identical--it's just a parameter.
If you're using JavaScript, there's not necessarily a reason to not use a form, though, since you could just update a form input element and submit normally.
It is quite simple, actually.
The constant 10 is submitted from the view. The submit needs to point to the controller action that will handle this request. So the submit button should build the url using :controller, :action, :id parameters. In a form, this is handled in the form_for declaration. You will deal with in the button_tag declaration.
The routes should be configured so that this message can reach the controller/ action.
The constant 10 is transported in the params hash. If the field is my_counter, then look for params[:my_counter]. If the form had been for a model, say tweets, then it might be in params[:tweet][:my_counter].
In the controller action, possibly update, you will first fetch the record to change with something like #score = Score.find(:params[:id]). This params[:id] is also coming from the view with the submit. Change the counter here, and save.
def update
#score = Score.find(:params[:id])
#score.counter = params[:my_counter]
#score.save
redirect_to :action => :index # or wherever
end
Good luck.
I am currently using a link_to helper in View to pass parameters like title , author ,image_url and isbn back to controller
<%= link_to 'Sell this item',new_item_path(:title => title, :author => authors, :image_url=>image, :image_url_s=>image_s, :isbn=>isbn, :isbn13=>isbn13 ) %>
Controller will then assign the parameters to an object to be used by a form in View later(in new.html.erb)
def new
#item = Item.new
#item.title = params[:title]
#item.author = params[:author]
#item.image_url = params[:image_url]
#item.image_url_s = params[:image_url_s]
#item.isbn = params[:isbn]
#item.isbn13 = params[:isbn13]
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #item }
end
end
new.html.erb will then be called.
This is all working fine but the url shows all the parameters
http://localhost:3000/items/new?author=Michael+Harvey&image_url=http://ecx.images-amazon.com/images/I/51vt1uVjvLL._SL160_.jpg&image_url_s=http://ecx.images-amazon.com/images/I/51vt1uVjvLL._SL75_.jpg&isbn13=9780307272508&isbn=0307272508&title=The+Third+Rail
Is there any way I can make the parameters not show up on the URL?
Maybe you could encode the parameters and decode them in the controller to deter users who may want to modify the url? Might be overkill but...
>> author=ActiveSupport::Base64.encode64("author=jim")
=> "YXV0aG9yPWppbQ==\n"
>> ActiveSupport::Base64.decode64(author)
=> "author=jim"
A POST can be used to move the parameters out of the URL and into the request, but this is not the "correct" or best practice. HTTP standards are such that non-GET requests are meant to be used only for requests that change state on the server. This is why you get a warning when you refresh a page that was generated in response to a POST.
There is nothing wrong with having parameters in the URL. So much focus should not be made on what appears to the URL bar, let alone what's after the ?. If however you have some need (i.e. insistence of a client) to remove them, you have several options, two of which John mentions.
I'm assuming your "new" action is REST-style, in that it's generating a form that would have to be submitted to change state on the server. Therefore your options might be:
Use POST, even though it's not standard compliant. Not recommended.
Use AJAX GET. This requires javascript, and ajax handling does add requirements such as the use of a JS framework and testing.
Use GET (or POST), but capture the parameters and store them, the redirect the user back to another clean URL that displays those stored value. You could store those in the session hash, or create a database record of them. Actually you really should use POST in this case, since you are effectively changing state on the server by storing those parameters. In this case, if the user refreshes the page he is directed to, those parameters will be preserved. This effectively removes the browser warning on refresh, something I can certainly appreciate.
There are two options that I can see and both involve JavaScript:
Have the link populate hidden form fields for the parameters and then submit the form using an HTTP POST request
Have the link submit an AJAX request to the controller action (using an HTTP GET unless clicking the link changes server-side state, in which case a POST should be used)
I think I would go with the second approach.
Why not write them to the session? It looks like you might have less than 4k in data there. Just remember to wipe it.