How do i remove the authenticity_token from rails forms - ruby-on-rails-3

I have worked out how to disable the authenticity_token in the controller but rails still creates the field in the forms. How do i turn this off as the server i am posting the form to needs a very specific set of field names.

In rails after 3.2.x you can pass a parameter into the form generator as suggested in another answer:
form_for #invoice, :url => external_url, :authenticity_token => false do |f|
...
<% end %>
In any rails version you can disable globally in config/application.rb, as in another answer:
config.action_controller.allow_forgery_protection = false
In rails 3.0.x you can disable on a page load basis in the controller by overriding the following method. Unfortunately, there seems to be no way to do this at the form level.
protected
def protect_against_forgery?
if ...
# results in the meta tag being ommitted and no forms having authenticity token
return false
else
# default implementation based on global config
return allow_forgery_protection
end
end

To disable it across your application, you can add this line to your config/application.rb:
config.action_controller.allow_forgery_protection = false

For external urls you can turn this of per form as follows:
<%= form_for #invoice, :url => external_url, :authenticity_token => false do |f|
...
<% end %>
Source: http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for

Related

Set local: true as default for form_with in Rails 5

I'm working on a project where we won't be using ajax calls for submitting the forms, so I need to put local: true in every form in the project, as indicated in the rails docs:
:local - By default form submits are remote and unobstrusive XHRs. Disable remote submits with local: true.
Is there any way to set the local option as true by default?
We're using Rails 5 form_with helper like this:
<%= form_with(model: #user, local: true) do |f| %>
<div>
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div>
<%= f.label :email %>
<%= f.email_field :email %>
</div>
<%= f.submit %>
<% end %>
As you've stated it can be set on a per form basis with local: true. However it can be set it globally use the configuration option [form_with_generates_remote_forms][1]. This setting determines whether form_with generates remote forms or not. It defaults to true.
Where to put this configuration? Rails offers four standard spots to place configurations like this. But you probably want this configuration in all enviroments (i.e. development, production, ...). So either set it in an initializer:
# config/initializers/action_view.rb
Rails.application.config.action_view.form_with_generates_remote_forms = false
Or maybe more commonly set in config/application.rb.
# config/application.rb
module App
class Application < Rails::Application
# [...]
config.action_view.form_with_generates_remote_forms = false
end
end
Consider overriding the form_with method:
# form_helper.rb
def form_with(options)
options[:local] = true
super options
end
That should solve it for every form in your application.
The Rails configurations can be set in config/application.rb file.
module App
class Application < Rails::Application
# [...]
config.action_view.form_with_generates_remote_forms = false
end
end
Guy C answer is good, but it's more idiomatic to put all config in this file rather than a separate initializer; That's where most of the Rails dev would expect it.
Note that this would spell disaster if you put it config/development.rb only or other env specific files.

How do I render a reply into turbolinks 5 with rails 5

I have a controller action where I'd like to receive form data, execute some business logic, then refresh the form. This works Ok if I save the object in the database then use a redirect_to. I would prefer the controller edit the object in memory and render the response directly.
For example, take a standard rails 5.1.4 generated app generated like so:
rails new turbolinks_example
rails g scaffold Thing name
rails db:migrate
The form, slightly edited for brevity and to enable turbolinks:
<%= form_with(model: thing) do |form| %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, id: :thing_name %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
A) Now we edit the controller to change the object. This uses a redirect to edit and works:
ThingsController < ApplicationController
...
def update
if #thing.update(thing_params)
#thing.update name: "#{#thing.name} is OK"
redirect_to edit_thing_path(#thing)
end
end
B) This uses a render and does not work:
class ThingsController < ApplicationController
...
def update
if #thing.update(thing_params)
#thing.name = "#{#thing.name} is OK"
render :edit
end
end
end
With A)
- Update request is received by controller
- Object is modified (& saved)
- Redirect is returned
- Rediredted url is rendered
- DOM is updated
With B)
- Update request is received by controller
- Object is modified (in memory)
- Response is rendered
- Response is received by browser, but ignored
The response received, looks correct. Full HTML, with the changes made to the object. How do I get turbolinks to notice it and replace document.body like normal?
The full project, including development.log is on Github
The problem is that, in Rails 5:
Forms are remote by default: they are sent via AJAX unless local: true provided
When rendering HTML as a response to an AJAX call, nothing happens unless, of course, there is custom javascript in the client handling the response
Turbolinks is enabled by default, which handles redirect_to properly, but does nothing for render
I think this is an inconsistency in Rails that causes much confusion, such as the problem you exposed with your code. I created a gem turbolinks_render to deal with this problem. I also wrote a little post on this very same problem.
I hope that, one way or other, this gets fixed in future Rails versions.

File Handling with Paperclip

I'm using Paperclip in a gem I built for a specific use case. My gem creates an interface for non-programmers to create and edit forms and then allows users to answer those forms.
I want to use Paperclip in order to provide a "File Upload" input type for questions, so my forms are more versatile. However, this means that I need to use the file_field_tag method to display the file input and I need to manually save whatever information is submitted through that input into the appropriate model object. Currently I'm sending the information through with the name question_1 and then trying to pull the uploaded data out with params["question_1"].
My code looks like this:
answer.update_attributes(upload: params["question_1"])
But I'm getting a No handler found for <image_name> error and I can't figure out what I'm doing wrong. I thought Paperclip handles everything after I pass it the data from a file_field?
Solution:
My form looked like this: <%= form_for #answer_set, multipart: true do %> when it should have looked like this: <%= form_for #answer_set, html: { multipart: true } do %>.
I use
has_attached_file :image
validates_attachment_presence :image
validates_attachment_content_type :image, :content_type => ['image/jpeg', 'image/png', 'image/jpg', 'image/pjeg']
and then:
#upload = Upload.find(params[:id])
#upload.update_attributes(params[:upload])
config/environment.rb
Rails::Initializer.run do |config|
config.gem "paperclip", version: "~> 2.7"
end
This thread also suggests checking the multi-part on the form
https://stackoverflow.com/a/10076046/1354978
answer_form_for #upload, :html => {:multipart => true} do |f|
There are also other possible solutions on that page.

Is view_context no longer available in Rails 3 views?

in a current Rails 3.0.9 app of mine I had a few .js.erb templates that were using view_context in them so I could call fields_for on it during a ajax request. This was letting me build some nested attribute form fields via ajax. But upon upgrading to Rails 3.1 I'm getting the follow error:
ActionView::Template::Error (undefined local variable or method `view_context' for #<#:0x1057b9f70>):
Was this removed/deprecated recently? Is there another way I can build nested fields_for inputs without having the parent FormBuilder handy? It seems view_context is still available in the controller, but I was hoping to keep this markup generation in the View layer.
My .js.erb template looked like this
<% meal_item_fields = view_context.fields_for :meal_items, Meal.new.meal_items.new, :child_index => "new_meal_items" do |f|
render :partial => 'meal_items/meal_item_fields', :locals => {:meal_item_form => f}
end
%>
$("#meal-items").append("<%= escape_javascript(meal_item_fields) %>");
According to api docs it is deprecated in >= 3. Source of 3.0.9 returned self for view_context. I think if you were to try without view_context it would just work.
<% meal_item_fields = fields_for :meal_items, Meal.new.meal_items.new, :child_index => "new_meal_items" do |f|
render :partial => 'meal_items/meal_item_fields', :locals => {:meal_item_form => f}
end %>
$("#meal-items").append("<%= escape_javascript(meal_item_fields) %>");
You might want to add helper_method :view_context in your controller.

render :inline => "<%= yield %>" not working

I'm upgrading from Rails 2.3.8 to 3.0.3 and notice that my code for nested layouts isn't working.
In my main Application layout I have the line
<%= controller.sub_layout %>
which then looks to the controller, who has:
def sub_layout
render :inline => "<%= yield %>"
# or otherwise some partial for the sub-layout
end
The problem is, this doesn't get rendered! If I put a direct <%= yield %> statement in the layout, it does work. So the question is, what's happening here, and how do I fix it?
This worked beautifully in Rails 2.3.8
How about a much saner approach:
render :layout => false
Related: http://guides.rubyonrails.org/layouts_and_rendering.html#using-render
So you all have some more of a background on this, the whole sub-layout approach was based on this blog post: Sorta Nested Layouts (The solution is given in the comments section.)
Instead of making a controller method sub_layout, any controller that uses a sublayout needs to define a before_filter method that sets a variable:
def inner_layout
#inner_layout = 'layouts/sublayout_partial_name'
end
then in the main layout.html.erb (i.e. application.html.erb), where you would otherwise put your yield statement:
<%= #inner_layout ? render(:partial => "#{#inner_layout}") : yield %>
the assumtion is that the sublayout partial file will have its own yield statement in there somewhere.