3

Am new to ruby on rails. Here am trying to post html form to ruby on rails (5.2.3 versions) To this effect, I reference solution found here link

<form accept-charset="UTF-8" method='post' action='http://localhost:3000/user1s'>

      
        <label for='name'>Name</label>
            <input type="text" name='name' placeholder='Enter your name'> <br>
        <label for='password'>password</label>
            <input type="text" name='password' placeholder='Enter your password'> <br>
        <label for='email'>confirm pass</label>
            <input type="text" name='password_confirmation' placeholder='Enter your password_confirmation'> <br>
     
            <input type="submit" value='Save'>
    </form>

user1 controller

class User1sController < ApplicationController
    

  # POST /user1s
  # POST /user1s.json
  def create
    @name = params[:name]
    @password = params[:password]
    @password_confirmation = params[:password_confirmation]
    @user1 = User1.new(name=>@name, password=>@password , password_confirmation=>@password_confirmation)

    respond_to do |format|
      if @user1.save
        format.html { redirect_to @user1, notice: 'User1 was successfully created.' }
        format.json { render :show, status: :created, location: @user1 }
        #format.json {status: :created }
      else
        format.html { render :new }
        format.json { render json: @user1.errors, status: :unprocessable_entity }
      end
    end
  end

  
end

Here is config/routes.rb

Rails.application.routes.draw do
  #resources :user1s
  post '/user1s', to: 'user1s#create', as: 'user1s'  
end

When I run the code am getting the following error

The browser returned a 'null' origin for a request with origin-based forgery protection turned on. This usually means you have the 'no-referrer' Referrer-Policy header enabled, or that the request came from a site that refused to give its origin. This makes it impossible for Rails to verify the source of the requests. Likely the best solution is to change your referrer policy to something less strict like same-origin or strict-same-origin. If you cannot change the referrer policy, you can disable origin checking with the Rails.application.config.action_controller.forgery_protection_origin_check setting.

To mitigate the error above, I referenced link here which suggests solutions below yet cannot get it to work. link 2

at config/application.rb i have

Bundler.require(*Rails.groups)

module Saverecord
  class Application < Rails::Application
    Rails.application.config.action_controller.forgery_protection_origin_check = false
    config.action_controller.allow_forgery_protection = false

    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

  end
end

at application controller I have

class ApplicationController < ActionController::Base   
  # Prevent CSRF attacks by raising an exception.   
  # For APIs, you may want to use :null_session instead.   
  #protect_from_forgery with: :exception   
  protect_from_forgery with: :null_session

  
end  
Human programmer
  • 408
  • 4
  • 11
Nancy Moore
  • 2,322
  • 2
  • 21
  • 38
  • if this app is just for testing purposes, you can disable `protect_from_forgery` by changing `protect_from_forgery with: :null_session` to `skip_before_action :verify_authenticity_token` – Yurii Verbytskyi Apr 13 '19 at 21:30
  • But you also can add csrf token to your form by adding `<%= csrf_meta_tags %>` – Yurii Verbytskyi Apr 13 '19 at 21:33
  • Thanks Yuriy. The error is now gone. Now when I try to submit the form. it says paramater missing or value is empty. I have also try implementing the code below but with no luck @user1 = User1.new(user1_params) def user1_params params.require(:user1).permit(:name, :password, :password_confirmation) end – Nancy Moore Apr 13 '19 at 22:35
  • if its real your form, posted here, you should fix, take a look at example in `devise` gem, that is highly recommended for users set up in Rails https://github.com/RailsApps/rails-devise/blob/master/app/views/devise/registrations/new.html.erb – Yurii Verbytskyi Apr 13 '19 at 22:49
  • Thanks alot Yurij – Nancy Moore Apr 13 '19 at 23:19
  • Why don't you generate your form with Rails form helpers ?? It will automatically attach a verification token and it is also much easier. https://guides.rubyonrails.org/form_helpers.html – Maxence Apr 13 '19 at 23:46
  • A word of advice - be a bit more critical of your sources. Stackoverflow answers are usually a solution to a particular problem often posted by someone that has no clue what they are doing. They are not reflective of good practices. Use the [Rails Guides](https://guides.rubyonrails.org) or [Rails Tutorial](https://www.railstutorial.org/). You are just going to waste a bunch of time if you try to learn rails by googling the error messages. – max Apr 14 '19 at 10:35

1 Answers1

5

This is much easier if you just follow the rails conventions.

Start by using strong parameters instead of copying variables twice from the params hash.

class User1sController < ApplicationController
  # POST /user1s
  # POST /user1s.json
  def create
    # Use strong parameters instead  
    @user1 = User1.new(user1_parameters)

    respond_to do |format|
      if @user1.save
        format.html { redirect_to @user1, notice: 'User1 was successfully created.' }
        format.json { render :show, status: :created, location: @user1 }
        #format.json {status: :created }
      else
        format.html { render :new }
        format.json { render json: @user1.errors, status: :unprocessable_entity }
      end
    end
  end

  # ...
  private 
  def user1_parameters
    params.require(:user1).permit(:name, :email, :password, :password_confirmation)
  end
end

Ruby (and Rails) have fantastic features for manipulating hashes. If you are ever copying keys manually from one hash to another you are doing it wrong.

Then use the form helper instead of manually creating a form:

<%= form_with(model: @user1) do |form| %>
  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>
  <div class="field">
    <%= form.label :email %>
    <%= form.email_field :email %>
  </div>
  <div class="field">
    <%= form.label :password %>
    <%= form.password_field :password %>
  </div>
  <div class="field">
    <%= form.label :password_confirmation %>
    <%= form.password_field :password_confirmation %>
  </div>
  <div class="actions">
    <% form.submit %>
  </div>
<% end %>

Rails has built in Cross Site Reference Forgery (CSRF) countermeasures which means that Rails will reject form submission that do not contain a valid CSRF token. When you create a form with form_with (or the older form_tag and form_for) Rails includes a CSRF token as a hidden input in the form.

That means your hand-crafted form is a no go unless you disable the CSRF protection or provide the token which is much more complicated then just using the form helpers.

Your form also does not use the correct name attributes for a nested hash. Rails by convention uses nested hashes:

{
  users1: {
    name: 'foo',
    email: 'foo@example.com'
    ...
  }
}

The form helper do this by setting the correct name attribute on the inputs:

<input type="email" name='user1[email]' ...>

Which works with params.require(:user1).permit(...). Your form will give an ActionController::ParameterMissing error. You can work around this to use flat hashes but you might as well learn the Rails Way which avoids potential name collisions.

max
  • 96,212
  • 14
  • 104
  • 165