No route matches [POST] - Adding route does not work - ruby-on-rails

My method does not work.
I have a games library, where I can add, show, edit, and destroy. I want to expand it and add one more method clone to it.
Library created with rails g scaffold:
The clone method in games_controller.rb
def clone
#game.clone
respond_to do |format|
format.html { redirect_to games_url, notice: 'Game was successfully cloned.'}
format.json { head :no_content }
end
end
The call code for Clone in index
<% #games.each do |game| %>
<tr>
<td><%= game.title %></td>
<td><%= game.description %></td>
<td><%= link_to 'Show', game %></td>
<td><%= link_to 'Edit', edit_game_path(game) %></td>
<td><%= link_to 'Destroy', game, method: :delete, data: { confirm: '.. sure?' } %></td>
<td><%= link_to 'Clone', game, method: :clone, data: { confirm: '.. sure?' } %></td>
</tr>
<% end %>
The routes code in routes.rb
resources :games do
resources :comments
post 'clone'
end
a view in games library

You are doing it wrong. You have method: :clone which is not valid. The valid values for method option for link_to are post, patch, put and delete.
method: symbol of HTTP verb - This modifier will dynamically create an
HTML form and immediately submit the form for processing using the
HTTP verb specified. Useful for having links perform a POST operation
in dangerous actions like deleting a record (which search bots can
follow while spidering your site). Supported verbs are :post, :delete,
:patch, and :put. Note that if the user has JavaScript disabled, the
request will fall back to using GET. If href: '#' is used and the user
has JavaScript disabled clicking the link will have no effect. If you
are relying on the POST behavior, you should check for it in your
controller's action by using the request object's methods for post?,
delete?, patch?, or put?.
Now coming to your routes, when you do rake routes, you will see the below
game_clone POST /games/:game_id/clone(.:format) games#clone
So, the link_to should look like below
<%= link_to 'Clone', game_clone_path(game), method: :post, data: { confirm: '.. sure?' } %>
Couldn't find Game without an ID
Ok, you are cloning a Game instance. Normally you look for an instance with an :id, but with your current routes, the :game_id will passed in the params which is not appropriate to want you need. You should change your routes to pass :id instead of :game_id. So the final solution will be
Final Solution:
resources :games do
resources :comments
post 'clone', on: :member
end
The above will create a path helper with the below
clone_game POST /games/:id/clone(.:format) games#clone
Now change the link_to with the new path helper and you are good to go
<%= link_to 'Clone', clone_game_path(game), method: :post, data: { confirm: '.. sure?' } %>
Note:
You should be careful when adding custom routes to your resourceful routes. This will create path helpers with unnecessary keys such as :*_id(:game_id in your case). These routes should be added as collection route or a member route depending upon the scenario. For more info refer these guides

Related

Can we attach some variables to route path in ruby on rails 6?

I'm a beginner in ruby-on-rails and I struggled for hours to do this:
There is one variable X in a html page Page1 of one controller C1 in my application. And I want to link to anther route path path1 with that variable X so that I can do something with that variable X in the controller action act1 corresponding to that route path path1.
In my situation is:
<% #courses.each do |course| %>
<tr>
<td><%= link_to 'Enroll', enroll_path, method: :post, data: { confirm: 'Are you sure?' } %></td>
</tr>
This code is in the view page html and I want to link_to enroll_path with the variable course
post '/enroll', to: 'enrollments#enroll'
This is the enroll path route
def enroll
enrollment = Enrollment.new(user_id: current_user.id, course_id: course[id])
enrollment.save
redirect_to root_url
end
This is action that corresponds enroll path and I want use the variable course in it.
I have tried to attach the variable course directly to the enroll_path, Like this:
<td><%= link_to 'Enroll', enroll_path(course), method: :post, data: { confirm: 'Are you sure?' } %></td>
but it did not work out.
How should I do to solve this?
Have you tried
<%= link_to 'Enroll', enroll_path(course_id: course.id), method: :post, data: { confirm: 'Are you sure?' } %>
I believe you will have to change the controller line to this
enrollment = Enrollment.new(user_id: current_user.id, course_id: params[:course_id])
This part (course_id: course.id) sends course_id as a param, so in the controller you can access its value by looking for params[:course_id].

Changing boolean value from view

I have a model organismereferent which has a boolean value named active. What I'm trying to do is depending on what value it has do a different action.
So if it's active the button shows deactivate and allows the user to set active to false. So after that the button should show activate which will allow the user to set active back to true.
I tried making a method in my controller then calling that method from my index view but it gives me a No route matches [POST] "/organismereferents/8". I'm pretty new to Ruby on Rails so there must be an easier way to accomplish that
View:
<table class="table table-hover">
<tr>
<th>Nom Organisation</th>
<th>Site Web</th>
</tr>
<% #organismes.each do |organisme| %>
<tr>
<td><%= organisme.nom_organisation %></td>
<td><%= organisme.site_web %></td>
<td><%= link_to 'Show', organismereferent_path(organisme), class: 'btn btn-info' %></td>
<td><%= link_to 'Edit', edit_organismereferent_path(organisme), class: 'btn btn-warning' %></td>
<% if organisme.active == false %>
<td><%= link_to 'Activate', organismereferent_path(organisme), class: 'btn btn-danger',
method: :activate,
data: { confirm: 'Are you sure?' } %></td>
<% else %>
<td><%= link_to 'Deactivate', organismereferent_path(organisme), class: 'btn btn-danger',
method: :deactivate,
data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
<% end %>
</table>
Controller:
def index
#organismes = Organismereferent.all
end
def deactivate
#organisme = Organismereferent.find(params[:id])
#organisme.active = false
end
def activate
#organisme = Organismereferent.find(params[:id])
#organisme.active = true
end
If you need any more information I will be glad too add it.
Routes:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
get 'master/index'
resources :organismereferents
# Notre page principal
root 'master#index'
end
We have a few problems here.
First, in your views, the link_to helper method parameter doesn't want to know the name of your controller action. It wants to know the http method to use. For the actions you are doing, I think the most appropriate would be PATCH. So change those lines to method: :patch.
Second, you need to update your routes.rb file to include the routes you need. You can do that by replacing resources :organismereferents with the following:
resources :organismereferents do
member { patch :activate }
member { patch :deactivate }
end
Using the member designation indicates to Rails that you want to include an :id param in the URL. Now when you run rake routes you should see, in addition to what you already have, the following:
activate_organismereferents PATCH /organismereferents/:id/activate(.:format) organismereferents#activate
deactivate_organismereferents PATCH /organismereferents/:id/deactivate(.:format) organismereferents#deactivate
Third, you need to fix your path helpers. The first column returned by rake routes tells you the name of the Rails helper path that you can use in your link_to helpers. So in your Activate link, you'll need to change organismereferent_path(organisme) to activate_organismereferent_path(organisme), and in your Deactivate link, use deactivate_organismereferent_path(organisme).
Finally, in your controller actions, you are not saving the records after you change the boolean value. You will need to call #organisme.save to persist the change. Or if you would prefer to make the change and save it in a single line, you can use #organisme.update(active: true) and #organisme.update(active: false).

Issue in rails 4.0 with creating a link_to for a delete action

This is my first project in rails, which is to create a table that will store data about games. I'm able to display data from the table about winner score, loser score, etc. However, I have issues with my table column that contains delete links for each game.
Here's my code in the games controller for the delete method:
def delete
#game = Game.find(params[:game])
#game.destroy()
redirect_to :action => 'index'
end
A snippet of my table code, which includes the line for the link_to command
<% #games_items.each do |t| %>
<tr>
<td><%= t.winner.name %></td>
<td><%= t.loser.name %></td>
<td><%= t.challenger.name %></td>
<td><%= t.winner_score %></td>
<td><%= t.loser_score %></td>
<td><%= link_to 'Delete', delete_game_path(id: t.id)%></td>
</tr>
<% end %>
In the routes file I called
resources :games
Which, to my knowledge, helps generate the base routing. Could anyone help me figure out why my link_to is not working?
If you use (which is adviced) resources:
a) Your action for deleting records should be named destroy.
b) Game is searched for with :id parameter:
def destroy
#game = Game.find(params[:id])
#game.destroy
redirect_to :action => 'index'
end
c) Your link should be:
<%= link_to 'Delete', t, method: :delete %>
since the path is the same as for the show action, the only thig that changes is HTTP method.
The format for the delete call is:
<%= link_to 'Delete', game_path(t.id), :method => :delete %>
use rake routes to learn about the available routes, including generated route helpers, and the controller/action handling the request.
I had similar issue on rails 4.2.1, even with the :method => :delete on link_to it still routes to show method.
But using button_to method as below works!
<%= button_to "delete", article_path(:id => article.id), :method => :delete %>
button_to creates a form around the button and then posts to the delete method, by adding a hidden field named _method with value delete rails uses this to route to the destroy method in your controller.
Try to use <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script> before <%= javascript_include_tag "application" %> in your layout, and also delete
//= require jquery
line in your application.js.
This was the case for me. No idea why it didn't worked with original rails jquery.js file.

CRUD operation for nested model in rails 3

I am new in rails 3, and following the guide in ruby site I build the first blog application.
However in the app,the model "Comment" do not have edit/update/delete operation.
Then I tried to add it,but I fails.
Instead of just generate model for model "Comment",I create the scaffold for model "Comment" using:
rails generate scaffold Comment commenter:string body:text post:references
And in the post.show page,I modify it like this:
<% #post.comments.each do |comment| %>
<tr>
<td><%= comment.commenter %></td>
<td><%= comment.body %></td>
<td><%= link_to 'Edit', edit_comment_path(comment) %></td>
<td><%= link_to 'Destroy', comment, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
They are listed,but when I click the 'edit' or 'delete' link,it will try to jump to:
http://localhost:3000/comments/1
And Then I will get the error:
No route matches [GET] "/comments/3/edit" or
No route matches [DELETE] "/comments/3"
I have no idea now.
Is there any demo out of box I can learn?
UPdate:
In the routes.rb:
resources :posts do
resources :comments
end
Note:the following is confided manually by myself.
config generated by rails is :
resources :posts
resources :comments
Why I modify it is that in the comment build form,the post url should be "/posts/1/comments" for create new Comment,otherwise the post url will be "/comments" which will not associate the post and the comment.
Did you configure your routes? Your config/routes.rb should contain
resources :comments
you can also run rake routes to see what are the available url for your application based on your resource configuration.
Edit:
For a demo you can try this video on youtube. However, you can find lots of videos in web regarding this.
Edit:
So seems you need your comment resource in two ways. Both as a nested resource of posts and top level resource as well. So you can have two things together then
resources :posts do
resources :comments
end
resources :comments
Since you've nested resources, you should use:
edit_post_comment_path(#post, comment)
to be even clearer:
<td><%= link_to 'Edit', edit_post_comment_path(#post, comment) %></td>
<td><%= link_to 'Destroy', post_comment_path(#post, comment), confirm: 'Are you sure?', method: :delete %></td>

How to create custom method in Rails?

I'm currently trying to use a custom method in Rails and I do not know how to do so. Apart from the default methods in the controller, I wanted to add the following:
def cancel
#newsletter = Newsletter.find(params[:id])
respond_to do |format|
#SendGrid Newsletter API - Delete Newsletter Schedule
SendGrid.delete_schedule(#newsletter.name)
#newsletter.status = "CANCELLED"
#newsletter.save
format.html { redirect_to newsletters_url }
format.json { head :no_content }
end
end
The method is just like the default :destroy method but it doesn't actually destroys the object.
In my view, I had the following:
<% #newsletters.each do |newsletter| %>
<tr>
<td><%= newsletter.identity %></td>
<td><%= newsletter.name %></td>
<td><%= newsletter.recipients %></td>
<td><%= newsletter.subject %></td>
<td><%= newsletter.html %></td>
<td><%= newsletter.text %></td>
<td><%= newsletter.schedule %></td>
<td><%= newsletter.status %></td>
<td><%= link_to 'Show', newsletter %></td>
<td><%= link_to 'Edit', edit_newsletter_path(newsletter) %></td>
<td><%= link_to 'Destroy', newsletter, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<td><% if newsletter.status == "SCHEDULED" %><%= link_to 'Cancel', newsletter, method: :cancel, data: { confirm: 'Cancel Schedule?' }%><% end %></td>
</tr>
<% end %>
I got the error: No route matches [POST] "_newsletter url__"
When I rake routes, there isn't any route for the error above. May I know how to add the route and why is the route needed?
UPDATE
Currently, I still have the no route matches error. Below are all my files related to the 'Cancel' method:
routes.rb
resources :newsletters do
match '/cancel/:id' => 'newsletters#cancel', :as => :cancel
end
newsletters_controller.rb
def cancel
#newsletter = Newsletter.find(params[:id])
respond_to do |format|
#SendGrid Newsletter API - Delete Newsletter Schedule
SendGrid.delete_schedule(#newsletter.name)
#newsletter.status = "CANCELLED"
#newsletter.save
format.html { redirect_to newsletters_path(#newsletter) }
format.json { head :no_content }
end
end
newsletters/index.html.erb
<%= link_to 'Cancel', newsletter_cancel_path(newsletter) %>
You should have a line like this in your config/routes.rb file
resources :newsletters
You'll want to change it to this
resources :newsletters do
member do
put 'cancel'
end
end
You'll want to take a look at the routing guide that Иван Бишевац posted. You'll also want to understand basic restful routing and how Rails handles GET, POST, PUT, DELETE, etc.
I think you're mistaking the method: argument in the link_to as corresponding to the method in the controller. Actually it is referring to the RESTful HTTP verb i.e. :post, :delete and :put. So you don't pass the controller action through this way.
Instead you can pass in :controller and :action arguments...
Better still create a route in routes.rb and use the path that rails generates.
match "/cancel/:id", to: "controller#cancel", as: :cancel
and then the link_to would be something like:
link_to 'Cancel', cancel_path(newsletter)
Update:
The error you're getting is with the redirect_to in your cancel method (in the controller). Change the newsletters_url to newsletter_path(#newsletter) instead.
If you want to redirect back to the show page for a single newsletter, then you need to do the above (where you pass in the #newsletter parameter), if you want it to go back to the newsletters index page then it'll be newsletters_path.
You can check the existence of the routes by typing rake routes in your terminal. You'll see all the route names there.
Do you still get an error after changing to redirect_to newsletter_path(#newsletter)?
The thing that doesn't quite strike true is that you're getting a no POST route defined - which usually points to a malformed form_for. Examine your newsletter related forms especially any where you don't do the regular form_for #newsletter do |f|.
Here is complete explanation about routing:
http://guides.rubyonrails.org/routing.html

Resources