I am new in Ruby and Rails and little bit confused about rendering and adding routes for a new template.
I have following link_to
tag
<td colspan="3">
<%= link_to 'Show Current State', simulation, :action => :current_state, :class => 'btn btn-primary'%>
</td>
Where simulation
is the name of controller and action is name of the method in SimulationController
.
I added this in my routes.rb
resources :simulations, except: [:edit]
resources :simulations do
collection do
get 'current_state'
post 'current_state'
end
end
In my SimulationController
class I added a new method i.e.
def current_state
byebug
end
My problem? routes is not re-directing to current_state
method. Instead, it is redirecting to http://localhost:3000/simulations/{someID}
This redirection is calling show
action.
def show
...
end
How can I make this work out and make <%= @simulation.dat %>
line accessible in new.html.erb
. Location of new.html.erb
is in following path
views/simulations/index.html.js
views/similations/show.html.js
views/simulations/new.html.erb
This could be a basic question but I am new to rails 4. Thanks in advance.
Def of get_state
method in controller
def get_state
@simulation = current_user.simulations.find(params[:id])
return not_found if @simulation.nil?
.....
/// How to send `@simulation` into `state.html.erb` formally as `new.html.erb`
end
A Route template is as its name implies a template for a route, which is used to create routes from a set of input parameters. In other words, route templates are parameterized routes. Route template + input parameters ⇒ route. From a route template you can create one or more routes.
Routing is used to map requests to route handlers. Routes are configured when the application starts up, and can extract values from the URL that will be used for request processing.
You have too many misses in your code.
First, You don't need 2 resources :simulations
, just merge them into one:
resources :simulations, except: :edit do
member do
get 'current_state', action: 'get_state'
post 'current_state', action: 'change_state'
end
end
Note that the original collection
block is changed to a member
block.
The difference between a collection
block and a member
block is that you need to provide an resource id for each routes in the member
block, while no resource id is required for those in the collection
block.
Also note that I added action: 'xxx'
in each route, so you have to add these 2 actions in your SimulationsController
, one for GET requests, and the other for POST requests.
In both of these actions, add render 'new'
at the end.
Run rake routes
in your console (or bundle exec rake routes
if you have multiple versions of rails installed), and you will see all the routes along with there url helper methods listed, like this:
Prefix Verb URI Pattern Controller#Action
current_state_simulations GET /simulations/:id/current_state simulations#get_state
current_state_simulations POST /simulations/:id/current_state simulations#change_state
...
According to the Prefix column, the link in the view should be
<%= link_to 'Show Current State', current_state_simulations_path(simulation), :class => 'btn btn-primary'%>
Or in short
<%= link_to 'Show Current State', [:current_state, simulation], :class => 'btn btn-primary'%>
Don't return
in actions, because return
doesn't stop rendering.
Instead, use raise ActionController::RoutingError.new('Not Found')
to redirect users to the 404 page.
You can define an instance method in ApplicationController
:
class ApplicationController < ActionController::Base
private
def not_found!
raise ActionController::RoutingError.new('Not Found')
end
end
And modify your SimulationsController
:
def get_state
@simulation = current_user.simulations.find(params[:id])
not_found! unless @simulation
# ...
render 'new'
end
Best Practice
For dynamic page web applications, don't render views for non-GET requests!
Why? Because if a user POSTs some data to your web app, and then refreshes his/her browser, that request gets POSTed again, and your database got tainted. Same for PATCH, PUT and DELETE requests.
You can redirect the user to a GET path if the non-GET request succeeds, or to a 400 page if the non-GET request fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With