Rails' link_to method: GETing when it should DELETE - ruby-on-rails-3

I'm following Michael Hartl's Rails Tutorial, and for some reason the following code:
<%= link_to 'delete', user, :method => :delete, :confirm => "You sure?",
:title => "Delete #{user.name}" %>
Issues a GET request (as I verified by checking the rails server log). I also verified that the following line is in my application view:
<%= javascript_include_tag :all %>
One thing I didn't quite understand, and it's probably the source of my problem: where is the "delete" method defined? I verified in Hartl's source code that he defines a "destroy" method in the controller, not "delete". But even if I change the link_to to :method => :destroy, it just issues a GET.
I'm using Rails 3.1. Any tips?

Also check that this is in your application.js:
//= require jquery
//= require jquery_ujs
Apparently I had the jquery without the jquery_ujs and I had the same problem until I added that.
Note that you may need to add these lines above any import statements within application.js.

Most browsers don't actually support the DELETE verb, so Rails fakes it by modifying the HTML it generates. Rails tacks on a HTML5 attribute called data-method and sets it to "delete". So when a user clicks on the link, it is actually issued as a GET request, but the data-method attribute allows for some Rails magic and means your routing code should recognize it as a DELETE request.
edit:
You can test it yourself in the console. Run bundle exec rails c to get into the console, and look at the HTML that this generates:
helper.link_to "delete", "foobar/delete", :method => 'delete'
The HTML should look like this:
delete

You should use the following code
<%= button_to "delete", #user_current, :method => "delete" %>
It will solve the problem or add this line //= require jquery_ujs to application.js and use:
<%= link_to 'delete', user, :method => :delete, data: {:confirm => "You sure?" } ,
:title => "Delete #{user.name}" %>

As browsers don't support the DELETE verb, Rails creates a workaround for this problem by simulating a DELETE request through a standard GET or POST. The way method: :delete works is with a JavaScript handler for all links with data-method="delete" which modifies the request so Rails
processes it as a DELETE. This JavaScript handler is provided by the jquery_ujs library.
There are several things that could have gone wrong:
Make sure you have both jquery and jquery_ujs included in your application.js. Without both nothing will process the data attributes.
Make sure the link in question really has the method: :delete option specified.
Make sure for some reason you haven't stopped the event propagation of the link in question, like so for example:
$( 'a' ).click( function( event ) {
event.stopPropagation()
})
As this would prevent the jquery_ujs handlers from being executed and the request will never be modified and will remain just a standard GET.

I faced the same problem with Michael's tutorial. The data-method="delete" actually works as expected - it does call the destroy action in the controller. The reason it tries to GET (and eventually fail) is the following:
You'll notice that one of the before_filter's in the controller is set to signed_in_user, and in session_helper.rb, you'll notice that signed_in_user calls store_location (private method), which updates session[:return_to] to the current URL.
So, back in your controller's destroy action, it tries to redirect_back_or which results in GET current_url. I modified the signed_in_user helper to only call store_location when user is not signed in already.

On rails 5 :
Have the same problem, all 'DELETE' posts were compromised, affecting my crud pages AND devise signout... to solve the problem all I had to do was :
//= require rails-ujs

All we need is add the below line of code
//= require jquery_ujs
It seems like a bug:))

You want to do this in Rails 6+:
link_to(
'Delete Me',
some_controller_path(model),
data: { method: :delete }
)

Use button_to instead of link_to.

Related

simple_form - how to specify form's action attribute

I am using simple_form gem and have a ordinary rails scaffold which is working perfectly - I am able to update/create/destroy records.
When I add the views in application <%= yield %> a issue occurred - the simple_form gem is rendering a form with action "/" for the new action and I was not able to create new records.
In my controller, the path for create action is
#POST /webinars
So, I edit the action of the form from "/" to "/webinars" (using the browser console) and then successfully create a record.
I suppose that I should override the action of the from somehow, but was not able to find how.
Is this the real problem?
<%= simple_form_for #user, url: '/webinars' do %>
...
<% end %>

recaptcha_tags rendering escaped HTML in erb

I'm migrating my app to Rails 3.2.8 from 2.3.5. One form uses reCAPTCHA (in an erb file). Right now, all the HTML tags that the recaptcha_tags puts out are in escaped HTML. (i.e. <...> instead of <...>). So I see the tags themselves in the HTML page, instead of the reCAPTCHA box.
Here's what my erb looks like. I've verified that it doesn't matter where in the erb I put the recaptcha tags (inside the form_for or outside):
register.html.erb
...
<%= recaptcha_tags :public_key => RECAPTCHA_PUBLIC_KEY %>
...
Other things, like form_for don't have this problem. They output straight HTML.
Gemfile
gem "recaptcha", :require => 'recaptcha/rails'
Thanks in advance!
Turns out I needed to prefix the recaptcha_tags call with "raw":
register.html.erb
...
<%= raw recaptcha_tags :public_key => RECAPTCHA_PUBLIC_KEY %>
...
One of the major changes between Rails 2.3.5 and 3.X was some changes having to do with cross site scripting. You may want to start your upgrade by upgrading to 2.3.14 and adding the rails_xss gem. The rails_xss gem (https://github.com/rails/rails_xss) will switch the HTML safety default to escape, so it will cause the issue you're seeing with recaptcha_tags. This will allow you to see what strings in your app need to be marked as html_safe.
Or, if recaptcha_tags is the only issue, you may be able to fix it by telling rails not to escape the recaptcha_tags.
Something like:
<%= raw recaptcha_tags :public_key => "_________" %>
Thanks for doing the research. :)

how to post :create from the default update url, rails 3

I'm sure this is pretty basic, but I'm somewhat new to rails and struggling to find a solution via search.
I'm implementing a message model to enable private messaging on a forum. I have the models resource nested within a users resource.
Currently the model works, but I want to enable a user to reply to a private message directly on the message show page. I.e users/1/messages/16 instead of users/1/messages/new. Currently this is the default route for 'update' within the MessagesController. Is there anyway to make the form on this page hit the 'create' action within the controller, instead of the 'update'?
Thanks.
Sure, I would try something like this:
On your show page just add a new form.
<%= form_for :message, :url => new_user_message_path do |f| %>
...
<% end %>
You can check the routes of your application using this command:
bundle exec rake routes
I suggest you to read the rails guide: http://guides.rubyonrails.org/

Rails login partial in different controller

Hey,
I'm pretty new to rails and for learning effect, I try to implement my own authorization system.
Right now I'm having a Page Controller to control some static pages and nothing more, and a Session Controller where I plan to implement most of the authorization process.
My problem is, I have no clue how to get my partial to use the sessions-controller, when I add it to one of the static pages controlled by the pages controller.
It stated out with this http://ruby.railstutorial.org/chapters/sign-in-sign-out#top but i don't want it on an extra page.
so I tried setting the routes and I got an exception "no path found for '/'" as soon as I deleted "resources :sessions" it worked fine again.
my partial looks like this:
<%= form_for(User.new) do |f| %>
<%= f.submit "Login" %>
<% end %>
there's also a div class="action" block around the submit but can't find out how to escape it
this is included into my home via
<%= render 'sessions/new' %>
Thanks for your help
edit my solution:
I added to routes.rb:
resources :sessions
Furthermore I changed form_for(#user) to
<%= form_for(:session, url => sessions_path)
so this works.
I Highly recommed that you look at the railscast http://railscasts.com/episodes/250-authentication-from-scratch , it will give you an idea how to create authentication without forgetting some important steps.
Then you can use the gem devise which is an excellent authentication gem.
Have you tried putting your functions and everything for authentication within a Session Helpers file? Then, in your Application Controller if you add "include SessionsHelper" this should give you access to all the helper functions from Session that you should need

Rails 3 :method=> :delete doesn't work in Internet Explorer

I am going through the rails 3 tutorial at railstutorial.org. I have just created an extremely simple scaffold Users.
The scaffold-generated destroy link does not work in Internet Explorer. It redirects to the show action instead of deleting the user.
This problem only happens in IE9 and IE8 (the only IE versions I've tested so far) The problem DOES NOT happen in Firefox. Can anyone tell me why this is happening?
The view:
<%= link_to 'Destroy', user, :confirm => 'Are you sure?', :method => :delete %>
Generated HTML:
Destroy
The controller:
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to(users_url) }
format.xml { head :ok }
end
end
In Rails 3.1 with the asset pipeline, all the javascript is in application.js. So, rather than :defaults, you need "application".
<%= javascript_include_tag "application" %>
Make sure you have <%= javascript_include_tag :defaults %>
JS is now unobtrusive in rails 3, so the include is required to make it work.
Replace public/javascripts/rails.js of your application with this one:
https://github.com/rails/prototype-ujs/raw/master/src/rails.js
This is updated recently (2010/11/13).
The rails.js bundled with Rails 3.0.0/3.0.1 does not work well on Internet Explorer.
You need to upgrade your prototype distribution to 1.7 instead of 1.7rc2 (which doesn't have full support for IE 9). The latest Rails gem (at time of writing( in the gem repo is bundling 1.7rc2. Go to the prototype homepage, download the new 1.7 release and replace this with the bundled prototype.js.
I couldn't get it to work with IE9 with the default javascript libraries, so I installed jquery-rails and it works just fine. Not perhaps the ideal solution, but if it works...
By default, new rails projects are created with Prototype javascript libraries, with some prototype-specific helper functions in "public/javascript/rails.js". The scaffolding relies on some of these helpers to handle some things, like destroying a record, since there isn't a good javascript-free way of making a DELETE request, etc.
Make sure that your pages are loading both the javascript libraries and the "rails.js" file, which are needed to make the scaffolding work (see theschmitzer's answer, or check in Firebug).
Second, if you are using jQuery, install the 'jquery-rails' gem and then run "rails g jquery:install". This will remove the Prototype libraries, install the jQuery libraries, and update the helpers to use jQuery.
Try replacing your javascript default include with:
<%= javascript_include_tag "jquery" %>
<%= javascript_include_tag "jquery.min" %>
<%= javascript_include_tag "rails" %>
after following the steps above to get the latest jquery.js, jquery.min.js, and rails.js. That worked for me, anyway.
Or, replace the meaning of :defaults in application.rb:
config.action_view.javascript_expansions[:defaults] = %w(jquery jquery.min rails)
And then your application layout can still look have
<%= javascript_include_tag :defaults %>
This is probably because the loading of your script (rails.js and/or application.js) happens in head. At script execution time, there are no elements in your DOM with the attributes data-confirm and data-method.
So, the solution is to move the javascript tag to the end of <body>. At this time, the DOM has most likely been loaded and the javascript will find your elements.
I experience the same problem, regardless of web browser.
theschmitzer's answer didn't help me.
I found that as long as I am using the jquery javascript library the destroy method in the controller is never called.
In my case I had a conflict between the javascript libraries (jQuery and Prototype) which was hard to figure out for such a newbie. I changed completely to jQuery - as in the end of this railcast: http://railscasts.com/episodes/205-unobtrusive-javascript
I had the same problem. I was using the <%= javascript_include_tag :defaults %> as well as the jQuery library. When I removed the jQuery library, things worked. Also, you could use noConflict().
I notice that in rails 4, link_to puts the :method as a html attribute "data-method" but :confirm goes to an attribute "confirm" where the javascript needs it to be "data-confirm".
Not sure if this is a bug in rails, but you can work around it by doing this:
<%= link_to 'Destroy', user, :data => {:confirm => 'Are you sure?'}, :method => :delete %>