lundi 20 février 2017

Ruby on Rails validation does not show error messages for a form created with Simple_Form Gem, which is based on (MTI) Multiple Table Inheritance

My problem is a little related to this question, and the corresponding solution has proved useful and helpful, however there is a little digression from the that question which I like to explain further:

I have used active_record-acts_as gem over devise gem to create a model with multiple SignUp forms and a single SignIn Form, such that I have a Devise model called Client and other client types such as Company and Individual act as the Client Devise model, and all these MTI crafting was based on a layout different from application.html.erb layout, and I called it client_authentication_layout.html.erb

To summarize my question, I have controllers for each and every of my models with corresponding views and I did override the client devise model views such that I could render the Company and Individual forms/views as a tabbed form, which was successful.

For clarity, here are the models:

client.rb

class Client < ActiveRecord::Base
  actable
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  validates :email, :encrypted_password, presence: true
end

company.rb

class Company < ActiveRecord::Base
  acts_as :client

  validates :company_name,
            :company_url,
            :country,
            :contact_person,
            :phone_number,
            presence: true
end

individual.rb

class Individual < ActiveRecord::Base
  acts_as :client
end

For clarity, here is company controller:

class CompaniesController < ApplicationController


  # GET /companies/new
  def new
    @company = Company.new
  end

  # POST /companies
  # POST /companies.json
  def create
    @company = Company.new(company_params)
    if @company.save
      redirect_to root_path, notice: 'Company was successfully created.'
    else
      redirect_to new_client_registration_path
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
  def set_company
    @company = Company.find(params[:id])
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def company_params
    params.require(:company).permit(:company_logo, :company_name, :company_url, :country, :contact_person, :phone_number, :email, :password, :password_confirmation)
  end
end

For clarity, here are my view:

company/new.html.erb

<%= simple_form_for(Company.new) do |f| %>
  <div class="form-row">
    <%= f.input :company_name, placeholder: 'Company Name', label: false %>
    <%= f.input :company_url, placeholder: 'Company URL', label: false %>
    <%= f.input :country, placeholder: 'Country', label: false %>
    <%= f.input :contact_person, placeholder: 'Contact Person', label: false %>
    <%= f.input :phone_number, placeholder: 'Phone Number', label: false %>
    <%= f.input :email, required: true, autofocus: true, placeholder: 'Email', label: false %>
    <%= f.input :password, required: true, placeholder: 'Password', label: false %>
    <%= f.input :password_confirmation, required: true, placeholder: 'Password Confirmation', label: false %>
  </div>
  <%=    render 'shared/two_breaks' %>
  <div class='form-row'>
    <div class="col-md-12 form-group">
      <%= f.submit 'Get Started', class: 'btn btn-company' %>
    </div>
    <%=  render 'shared/four_breaks' %>
  </div>
<% end %>

individual/new.html.erb

<%= simple_form_for(Individual.new) do |f| %>

    <div class="form-inputs">
      <%= f.input :first_name, placeholder: 'First Name', label: false %>
      <%= f.input :last_name, placeholder: 'Last Name', label: false %>
      <%= f.input :about_me, placeholder: 'Type in a little details about yourself.', label: false %>
      <%= f.input :gender, placeholder: 'Choose gender', label: false %>
      <%= f.input :country, placeholder: 'Country', label: false %>
      <%= f.input :phone_number, placeholder: 'Phone Number', label: false %>
      <%= f.input :email, required: true, autofocus: true, placeholder: 'Email', label: false %>
      <%= f.input :password, required: true, placeholder: 'Password', label: false %>
      <%= f.input :password_confirmation, required: true, placeholder: 'Password Confirmation', label: false %>
    </div>
    <%=  render 'shared/two_breaks' %>
    <div class='form-row'>
      <div class="col-md-12 form-group">
        <%= f.submit 'Get Started', class: 'btn btn-individual' %>
      </div>
      <%=    render 'shared/four_breaks' %>
    </div>
<% end %>

client_authentication_layout.html.erb

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="ROBOTS" content="NOODP" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>FarFlung Jobs</title>
  <!-- /.You can include style.css into stylesheet_link_tag too. If you do so, dont forget to add style.css in asset.rb -->
  <%= stylesheet_link_tag    'clients_authentication', media: 'all' %>
  <%= javascript_include_tag 'clients_authentication' %>
  <%= csrf_meta_tags %>
</head>
<body>
  <%= yield %>
</body>
</html>

My Tabbed Form rendering Company and Individual Views on Client Devise View

<div class="container">
  <div class="row">
    <div class="col-md-6 col-md-offset-3">
      <!--col-sm-6 col-sm-offset-3 col-xs-4 col-xs-offset-3-->
      <div class="panel panel-login">
        <div class="panel-heading">
          <div class="row">
            <div class="col-xs-6 tabs">
              <a href="#" class="active" id="company-form-link"><div class="company">COMPANY</div></a>
            </div>
            <div class="col-xs-6 tabs">
              <a href="#" id="individual-form-link"><div class="individual">INDIVIDUAL</div></a>
            </div>
          </div>
        </div>
        <div class="panel-body">
          <div class="row">
            <div class="col-lg-12">
              <div id="company-form" role="form" style="display: block;">
                <h2>COMPANY</h2>
                <%= render 'companies/form' %>
              </div>
              <div id="individual-form" role="form" style="display: none;">
                <h2>INDIVIDUAL</h2>
                <%= render 'individuals/form' %>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

<div class="container">
  <div class="row">
    <div class="col-md-12 text-center">
      <span class="agreement">
        <p>By clicking Get Started, you agree to the FarFlung <a tabindex="2" href="http://ift.tt/1nBMTjM">User Agreement</a>, </p>
        <p><a tabindex="2" href="http://ift.tt/1geczMX">Privacy Policy</a>, and <a tabindex="2" href="http://ift.tt/1FRQVhm">Cookie Policy</a>.</p>
      </span>
    </div>
  </div>
</div>

Rails console

>> c = Company.new
#<Company id: nil, company_logo: nil, company_name: nil, company_url: nil, country: nil, contact_person: nil, phone_number: nil, created_at: nil, updated_at: nil>
>> c.valid?
false
>> c.errors.full_messages
["Email can't be blank", "Email can't be blank", "Password can't be blank", "Encrypted password can't be blank", "Company name can't be blank", "Company url can't be blank", "Country can't be blank", "Contact person can't be blank", "Phone number can't be blank"]
>> c.errors
#<ActiveModel::Errors:0x74f6ee0 @base=#<Company id: nil, company_logo: nil, company_name: nil, company_url: nil, country: nil, contact_person: nil, phone_number: nil, created_at: nil, updated_at: nil>, @messages={:email=>["can't be blank", "can't be blank"], :password=>["can't be blank"], :encrypted_password=>["can't be blank"], :company_name=>["can't be blank"], :company_url=>["can't be blank"], :country=>["can't be blank"], :contact_person=>["can't be blank"], :phone_number=>["can't be blank"]}>

However, if I submit an empty form, and validations takes effect, it just doesn't show on the simple_form created forms where the underlying error is.

To solve this problem, I did follow the aforementioned solution stated above, which proved successful. But it affects all other successful validating forms in other layouts of my application. Only the forms powered with client_authentication_layout.html.erb are not showing validation on the browser.

How do I solve this problem? Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire