How to add routes for a new template?

I am new to Ruby and Rails and am a bit confused about rendering and adding routes for a new template.

I have a 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 the controller and action is the name of the method in the SimulationController .

I added this to 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 ie method

  def current_state byebug end 

My problem? routes are not redirected to the current_state method. Instead, it redirects to http://localhost:3000/simulations/{someID}

This redirect invokes the show action.

 def show ... end 

How can I do this work and make the line <%= @simulation.dat %> available in new.html.erb . The location new.html.erb is in the following path

 views/simulations/index.html.js views/similations/show.html.js views/simulations/new.html.erb 

This may be the main question, but I'm new to rails 4. Thanks in advance.

Edit-1

Defect 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 
+7
ruby ruby-on-rails ruby-on-rails-4
source share
1 answer

You have too many misses in your code.

Firstly, you do not need 2 resources :simulations , just combine 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 has been changed to a member block.
The difference between the collection block and the member block is that you need to provide a resource identifier for each route in the member block, while a resource identifier is not required for those in the collection .

Also note that I added action: 'xxx' to each route, so you need to add these 2 actions to your SimulationsController , one for GET requests and one for POST requests.

UPDATE

In both of these steps, add render 'new' to the end.

END OF UPDATE

Run rake routes in your console (or bundle exec rake routes if you have several versions of rails installed), and you will see all the routes along with the hell helper methods listed here, for example:

  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 ... 

In 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 shorter

 <%= link_to 'Show Current State', [:current_state, simulation], :class => 'btn btn-primary'%> 

UPDATE FOR Edit-1

Do not perform return in actions because return does not stop rendering.
Instead, use raise ActionController::RoutingError.new('Not Found') to redirect users to page 404.

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 change your SimulationsController :

 def get_state @simulation = current_user.simulations.find(params[:id]) not_found! unless @simulation # ... render 'new' end 

Best practice
For dynamic web applications, do not display views for requests other than GET!

Why? Because if the POST user passes some data to your web application and then updates his / her browser, this request again gets POSTED and your database is corrupted. The same goes for PATCH, PUT, and DELETE queries.

You can redirect the user to the GET path if the non-GET request succeeds, or 400 pages if the non-GET request failed.

+6
source share

All Articles