Form_tag 'create' vs '/create' - ruby-on-rails

I'm exploring all options for form_tag and I noticed that if I use form_tag(action:'create') it would do post 'create'.
However, if I use form_tag('/create') or form_tag('create') I get this error in browser\
No route matches [POST] "/create"
I merely extrapolate from the example given in the Rails documentation on form_tag to use '/create' (http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag).
Does anyone know why I'm getting this error?

form_tag needs whatever is necessary to find a path for sending data.
action: 'create', which is resolved to {action: 'create'}, a Hash, invokes a routing system (with rules defined in routes.rb) to find a route in the same controller (the current view is in) for create action.
Otherwise, it's more commonly used with path helpers, returning paths as strings. When you specify a string manually, it's used as a path directly. Most of the time this is not what you want. All path helpers can be found by invoking rake routes. For a bare-bones app I threw together for a test this is what I get:
Prefix Verb URI Pattern Controller#Action
root GET / application#index
This means that you have methods root_path and root_url (Prefix hints) that routes path '/' into ApplicationController, action index. If I had something accepting a POST on the same path (the table above says I don't), I would have written this:
form_tag(root_path) # parentheses are optional, it's Ruby!
PS: routing anything to ApplicationController is bad practice. So yes, it's an impractical example, which nevertheless explains what's this all about.

Related

how to give names to rails generated routes?

when using the following on routes.rb: resource :my_model
I get a few automatically generated routes. Some of them have a name (just like when manually defining them with 'as' keyword) but some of them don't.. so how can I give them names?
Or maybe it's a 'hint' given to me by rails that I'm not supposed to use these routes?
What do you refer to when you say "name", the Prefix when you run rake routes? Many of the HTTP requests (i.e. patch, put, delete) are handled by the controllers and are intended to then either redirect to another path or alter the DOM of the current page if you're using javascript, so they wouldn't have a prefix associated with them as those requests don't have an associated view.
When using a singular resource, all CRUD routes will be generated with the exception of an index route. You do not need names for these paths if you are looking to use them as intended. What is your intent for using these routes?
As per the docs:
A singular resourceful route generates these helpers:
new_resourceName_path returns /re/new
edit_geocoder_path returns /geocoder/edit
geocoder_path returns /geocoder
Please post your output via: bundle exec rake routes
You'll notice the show and create controller actions share the same path with the only difference being one expects a POST request and the other a GET request. This is some of the magic provided by Rails allowing you to use similarly named routes that map to different actions.
Try resources instead of resource. If you want a helper for PATCH, PUT or DELETE, just use the helper for the show action (that you'll get from resources) and specify the HTTP method with method:.
The second answer here has a decent explanation about your resource call.
These routes expect a different request method (this implies additional data in request), and do not need separate name, just use generic global_preferences_path and for example - set method for unobtrusive js in link:
<%= link_to 'Set preference', global_preferences_path(some_parameter:'foo'),
confirm:'Are you sure?', method: :put %>
or use html form or so

Ruby on Rails 4 Routing/Views/Path

I have 2 questions:
I have a controller called homepage. I have a view called samplegraph in my homepage's view directory. I want to get the routing working correctly such that www.homepage.com/samplegraph takes me to the samplegraph page.
As far as I can tell, the route for it in routes.rb should be something like this:
GET 'homepage/samplegraph' => 'homepage#showgraph1'
If I'm understanding rails routing correctly, this statement routes GET requests to homepage/samplegraph to the homepage controller's showgraph1 action. At this point I'm not particularly sure what the showgraph1 action should be in order to render the view page(samplegraph). At the moment the action is simply empty. I don't really know what to put here.
Second question:
Also, while I was researching rails routing, I was looking into resource based routing. For my purposes, I don't need most of the stuff generated by that. One thing I am interested in is that invoking resource based routing automatically generates Paths for you via helpers(I think?).
How would I generate a Path for my route, such that I'd be able to use a link_to method to link various parts of the application together? Any help/comments would be greatly appreciated.
Firstly, if you want to get 'samplegraph' page rendered by hitting 'www.homepage.com/samplegraph', you will need to update your route.
Replace
get 'homepage/samplegraph' => 'homepage#showgraph1'
with
get '/samplegraph' => 'homepage#showgraph1'
Now in showgraph1 action of your homepage controller, you will need to render samplegraph view page at last line of the action.
render 'samplegraph'
As of you second question, just hit rake routes on your terminal from your app directory. It will show all routes with helpers which you can use with link_to. You will need to append _path to those routes while using with link_to
Like #RAJ said first of all you need to change your route to
get '/samplegraph' => 'homepage#showgraph1'
At this point I'm not particularly sure what the showgraph1 action should be in order to render the view page(samplegraph)
Rails doesn't care if your action is empty or not, it'll still render your actions view even if it's empty. Since your action is named showgraph1 so it'll make rails look for showgraph1.html.erb with path views/homepage/showgraph1.html.erb
To change this behavior you need to use render 'samplegraph' in your action
One thing I am interested in is that invoking resource based routing automatically generates Paths for you via helpers(I think?)
Rails generate path and url helpers for each route and it doesn't depend on how your routes are defined but you can customize your helper methods by specifying as: option
get 'homepage/samplegraph' => 'homepage#showgraph1', as: 'showgraph'
This will make your helper methods showgraph_path and showgraph_url

Custom route mistaken for object id in Rails

I have the following route:
view_all_styles /styles/view_all(.:format) styles#view_all
When I point my broswer at xyz.com/styles/view_all I receive the error:
ActiveRecord::RecordNotFound at /styles/view_all
Couldn't find Style with id=view_all
I'm also routed to the show action??
Request parameters
{"action"=>"show", "controller"=>"styles", "id"=>"view_all"}
It sounds like you've got your routes defined in the wrong order - you'll want to define your custom route before the resource routes of styles. Otherwise, you'll run into exactly this problem.
Since your route, /styles/view_all also fits into the route for #show, /styles/:id ('view_all' being the :id), it will match and pass along the request to #show before it even tries to match your custom route.

Bound Parameters in Ruby on Rails

I’ve previously asked a question related to this topic as well and with the aid of that question I’ve found the name of exactly what I wanted: “bound parameters”.
I have managed to create a routing like "user/:id/dosomething" by adding a member to the routes.rb. However, this type of URL is not the solution I was looking for.
My question is, how do you provide the 'user/dosomething/:id' to match with action user's dosomething action with id sent as parameter?
Here is the section I’ve read in order to get the idea:
3.1 Bound Parameters
When you set up a regular route, you supply a series of symbols that
Rails maps to parts of an incoming HTTP request. Two of these symbols
are special: :controller maps to the name of a controller in your
application, and :action maps to the name of an action within that
controller. For example, consider this route:
get ':controller(/:action(/:id))'
If an incoming request of /photos/show/1 is processed by this route
(because it hasn’t matched any previous route in the file), then the
result will be to invoke the show action of the PhotosController, and
to make the final parameter "1" available as params[:id]. This route
will also route the incoming request of /photos to
PhotosController#index, since :action and :id are optional
parameters, denoted by parentheses.
You can add a custom route:
get 'user/doesomething/:id' => 'users#do_something', :as => 'do_something_user'
This will route HTTP GET requests that match the URL user/dosomething/:id to the UsersController's do_something action. The :as => 'do_something_user' part names the route, so that you can use do_something_user_path and do_something_user_url helpers to generate the URLs.
For more information on routing, see Rails Routing from the Outside In.

What is the difference between a restful route method for getting an index vs. creating a new object?

According to rake routes, there's the same path for getting an index of objects as there is for creating a new object:
cars GET /cars(.:format) {:controller=>"plugs", :what=>"car", :action=>"index"}
POST /cars(.:format) {:controller=>"plugs", :what=>"car", :action=>"create"}
Obviously, the HTTP verb is what distinguishes between them. I want the "create" version of the cars_path method, not the "index" version. My question is what route method do you invoke to choose the one you want? I'm telling cucumber what path to generate with this:
when /the car plug preview page for "(.+)"/
cars_path(:action => :create, :method => :post)
...but it always chooses the "index" action, not "create". I've tried lots of combinations for the hash argument following cars_path and nothing changes it from choosing "index" instead of "create".
I'll get an error like this:
cars_url failed to generate from {:controller=>"plugs", :method=>:post,
:what=>"car", :action=>"create"}, expected: {:controller=>"plugs", :what=>"car",
:action=>"index"}, diff: {:method=>:post, :action=>"index"}
(ActionController::RoutingError)
This seems like a very simple question but I've had no luck googling for it, so could use some advice. Thanks.
Since the URL is the same for both actions, you can use cars_path (without arguments) in both cases. You just simply have to make sure that the form's method-parameter is set to :post. You can not set the method via the URL, you need to set it for the form (and you can't reach the create action by using a link, you need to use a form).
The difference is that one is accessed when a POST is performed, the other is accessed when a GET is performed. Typing a URL into the browser or (typically) clicking a link is the equivalent of a GET action. POST actions are typically performed by form submissions.

Resources