Ruby Blog Tutorial - ActionController::InvalidAuthenticityToken - ruby-on-rails

I am completing the Ruby Rails tutorial for a blog and when I try and submit a new post I am getting a ActionController::InvalidAuthenticityToken error from the browser.
I am new to Ruby Rails (hence why I am doing the tutorial) and I have been back through the examples and have looked a various other answers etc and I cannot seem to find what the problem could be? I would like to understand the problem and how to fix it as part of learning.
This is what is shown in the extracted source :
def handle_unverified_request
raise ActionController::InvalidAuthenticityToken
end
end
end
This is from the Server :
Parameters: {"authenticity_token"=>"MijxdOhNKeov89oetl7Xa0KWpSZoeb3WAIuX0RECyIusjfjs/B5megtnH6JFOSG1G5K7g+csApABCn31UxdYGg==", "article"=>{"title"=>"po request"
, "text"=>"I want to buy some cheese"}, "commit"=>"Save Article"}
HTTP Origin header (https://3000-dot-4708054-dot-devshell.appspot.com) didn't match request.base_url (https://127.0.0.1:3000)
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms | Allocations: 499)
ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
And this is the .erb for a new record:
<%= form_with scope: :article, url: articles_path, local: true do |form|
%>
<% end %>
<%= link_to 'Back', articles_path %>
<%= form_with scope: :article, url: articles_path, local: true do |form|
%>
<p>
<%= form.label :title %><br>
<%= form.text_field :title %>
</p>
<p>
<%= form.label :text %><br>
<%= form.text_area :text %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>

The authenticity token is used by rails to ensure that requests come from the site rails is expecting. When it generates a form, it includes the verification token for this purpose. There's a much better explanation of the history / why it's used here:
Understanding the Rails Authenticity Token
If you want to keep the checks in, then the short answer is to include
<%= form_authenticity_token %>
In any views that generate forms. This will ensure the correct token is in the form, and prevent the error from occuring

Related

RoR InvalidAuthenticityToken with Active Storage direct upload

I am trying to use rails active storage to directly upload to an Amazon s3 bucket. However, let's treat this as directly uploading when the storage medium is the local disk, because I can't get that to work either.
I am unable to do this without ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):
errors.
I have followed this guide exactly: https://guides.rubyonrails.org/active_storage_overview.html#direct-uploads
I have even gone so far as to disable csrf application wide with this line of code in my application_controller.rb skip_before_action :verify_authenticity_token
This only happens when I have direct_upload: true in my form.
Here is my form:
<%= form_with url: messages_path do |form| %>
<%= form.label 'Upload' %>
<%= form.file_field :audio_message, class: 'form-control', direct_upload: true, :required => true%>
<%= form.submit 'Upload file', class: 'form-control' %>
<% end %>
Looks like ajax submit did not pick up the token. You can try either one of these:
Tell the form to embed token <%= form_with url: messages_path, authenticity_token: true...%>
add config.action_view.embed_authenticity_token_in_remote_forms = true in config
See if they help you. My guess is purely from this: https://edgeapi.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with

Rails issue with access of nested hash parameter

I have in rails the following form in a view
<%= form_for (#account) do |f| %>
<%= f.label :comments,"Comments" %>
<%=f.text_area :comments %>
<%= f.submit "Confirm",:name=>"conf" %>
<%= f.submit "Reject" %>
<% end %>
When I submit the form I get the following hash in the log before the update of the database
Started PATCH "/accounts/12" for 127.0.0.1 at 2015-08-13 21:31:18 +0200
Processing by UseractionsController#answer_with_comments as HTML
Parameters: {"utf8"=>"✓", "account"=>{"comments"=>"mycomments"}, "conf"=>"Confirm", "id"=>"12"}
I am trying to access the input in the comments text area in the controller. I tried
params[:account][:comments]
but it does not seem to work. Could anyone give me the appropriate syntax? Thanks.
EDIT
This is my controller code. Right now the if loop return false and nothing is added to the database even though there is something submitted ("mycomments" see above in the param nested hash)
if params[:bankaccount][:comments]
#bankaccount.update_attribute(:comments, params[:bankaccount][:comments])
end
It is only the appropriate syntax for your view. It assumes that you have content field on your Comment model.
<%= form_for (#account) do |f| %>
<%= f.label :comments,"Comments" %>
<%= f.fields_for :comments do |ff| %>
<%= ff.text_field :content %>
<% end %>
<%= f.submit "Confirm",:name=>"conf" %>
<%= f.submit "Reject" %>
<% end %>
You also will have to declare nested attributes in your Account model and your params hash should be different.
You should watch these two Railscasts part 1 and part 2 to learn more about nested attributes.
Since you mention strong parameters as a tag you probably want to build this a bit differently.
private
def account_params
#the permit method might need to be altered depending on your model and view
params.require(:account).permit(:comments)
end
Somewhere else in your controller you would then do:
#bankaccount.update_attributes(account_params)
Please take a read: http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters

My form isn't going to the post route even tho I'm listing the correct path

or at least I think its the correct path. This is the error I'm getting:
No route matches [POST] "/terms/new"
And this is my code:
<h1>New Terms</h1>
<%= form_for :term, url: terms_path do |t| %>
<p>
<%= t.label :term %><br>
<%= t.text_field :term %>
</p>
<p>
<%= t.label :definition %><br>
<%= t.text_field :definition %>
</p>
<%= t.submit %>
<% end %>
and this is my rake routes
terms GET /terms(.:format) terms#index
POST /terms(.:format) terms#create
new_term GET /terms/new(.:format) terms#new
edit_term GET /terms/:id/edit(.:format) terms#edit
term GET /terms/:id(.:format) terms#show
PATCH /terms/:id(.:format) terms#update
PUT /terms/:id(.:format) terms#update
DELETE /terms/:id(.:format) terms#destroy
Putting the url to terms_path in my form should send the object to the terms/create if I'm not mistaken? Obviously still a rails newbie here. Help!
This is also my controller if that helps
def new
#term = Term.new(params[:term])
end
Instead of pointing to 'terms_path', try:
<%= form_for #term, url: {action: "create"} do |f| %>
PS: If you're just getting your feet wet with Rails & RESTful/CRUD basics, you can try generating a scaffold on the CLI to see exactly the right code for this sort of thing (on your CLI):
rails g scaffold term

turkee: undefined method `reverse_merge!' for nil:NilClass

In trying to get turkee working, I'm getting an undefined methodreverse_merge!' for nil:NilClass` error.
My Code:
class MechanicalTurksController < ApplicationController
def new
#mechanical_turk = MechanicalTurk.new
#disabled = Turkee::TurkeeFormHelper::disable_form_fields?(params)
end
end
<%= turkee_form_for(#mechanical_turk, params) do |f| %>
<%= f.label :first_name %>
<%= f.text_field :first_name, disabled: #disabled %>
<br />
<%= f.submit "Save", class:"btn btn-primary", disabled: #disabled %>
<% end %>
class MechanicalTurk < ActiveRecord::Base
end
I think the problem is the params hash. I think it's missing something. The documentation says
Mechanical Turk is now requiring that the hitId, workerId, and the
turkSubmitTo parameters be passed in along with the assignmentId and
form parameters.
Here's the output from my logs:
Started GET "/mechanical_turks/new?assignmentId=ASSIGNMENT_ID_NOT_AVAILABLE&hitId=2Z2MN9U8P9Y3B78UW1US1YIM5R7VEG" for 208.54.40.228 at 2012-05-08 17:35:24 -0400
Processing by MechanicalTurksController#new as HTML
Parameters: {"assignmentId"=>"ASSIGNMENT_ID_NOT_AVAILABLE", "hitId"=>"2Z2MN9U8P9Y3B78UW1US1YIM5R7VEG"}
Rendered mechanical_turks/new.html.erb within layouts/application (0.9ms)
Completed 500 Internal Server Error in 2ms
ActionView::Template::Error (undefined method `reverse_merge!' for nil:NilClass):
1: <%= turkee_form_for(#mechanical_turk, params) do |f| %>
2: <%= f.label :first_name %>
3: <%= f.text_field :first_name, disabled: #disabled %>
4:
app/views/mechanical_turks/new.html.erb:1:in `_app_views_mechanical_turks_new_html_erb___897197135_79286580'
I've also posted an issue on GitHub.
Used most recent release from github and it works now.

validations for the model form

I have got a form which is generated by model object.
<%= form_for(#pages) do |f| %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<% end %>
Here is the controller method for this:
def new
#pages = Page.new
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #post }
end
end
Here is the model code:
class Page < ActiveRecord::Base
validates :title, :presence => true
end
Now, how can I validate the form on submission.(i know that submit button is not there, i will add it later). I have used <%= f.error_messages %> in the form but it is giving me error :
NoMethodError in Pages#new
Showing C:/rorapp/app/views/pages/_form.html.erb where line #2 raised:
undefined method `error_messages' for #<ActionView::Helpers::FormBuilder:0x49b9ca8>
Extracted source (around line #2):
1: <%= form_for(#pages) do |f| %>
2: <%= f.error_messages %>
3: <p>
4: <%= f.label :title %><br />
5: <%= f.text_field :title %>
Trace of template inclusion: app/views/pages/new.html.erb
Rails.root: C:/rorapp
Application Trace | Framework Trace | Full Trace
app/views/pages/_form.html.erb:2:in `block in _app_views_pages__form_html_erb__975660997_39217440'
app/views/pages/_form.html.erb:1:in `_app_views_pages__form_html_erb__975660997_39217440'
app/views/pages/new.html.erb:2:in `_app_views_pages_new_html_erb___256256638_47476836'
app/controllers/pages_controller.rb:11:in `new'
Request
Parameters:
{"title"=>"",
"author"=>"",
"email"=>"",
"body"=>"",
"reference"=>"Google"}
Show session dump
Show env dump
Response
Headers:
None
How can I validate it?
My Rails experience is mostly with version 2.3.14, so I can't be 100% sure about this, but it looks like f.error_messages was depreciated in Rails version 3.0
Does this previous question help?
f.error_messages in Rails 3.0
Edit: basically what I'm saying is it looks like you're trying to display errors the old way, which is probably incompatible with your Rails version. The link I posted above has a few suggestions.
If I'm understanding your question correctly, you want to know how to validate the form on submission and how to display errors when there are some?
The validations you have in your model currently will validate the field "title" when you hit the submit button. So I think you're already good in that respect since that seems to be your only one.
To get errors to show up in your views, you want to use something like this is your form:
<%= form_for #pages do |f| %>
<h2><%= "#{pluralize(#pages.errors.count, "error")} prohibited this from being saved:" %></h2>
<% #pages.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<% end %>
This handles any errors in an elegant way. If there is more than one error, the pluralize method handles the pluralization of the word error so the sentence reads something like "2 errors have prohibited this from being saved." That way, should you decide to add more fields, you're already good to go.
Then pages.errors.full_messages displays each error in a sentence that is understandable to a user.

Resources