Question

First of all sorry about my English and about my knowledge of Rails, I am beginner who just started.

I have 2 models with relations:

CargoItems:

class CargoItem < ActiveRecord::Base
  belongs_to :cargo
  attr_accessible :cargo_id, :height, :length, :pieces, :weight, :width
  validates :cargo, :height, :length, :width, :weight, :pieces, presence: true
  validates :height, :length, :width, :pieces, numericality: { only_integer: true, greater_than_or_equal_to: 1}
  validates :weight, numericality: { only_integer: true, greater_than_or_equal_to: 100}
end

Cargos:

class Cargo < ActiveRecord::Base
  belongs_to :airport
  belongs_to :user
  belongs_to :cargo_state
  belongs_to :cargo_price
  belongs_to :cargo_description
  has_many :cargo_items, :inverse_of => :cargo, :dependent => :destroy

  attr_accessible :departure_date, :cargo_state_id, :airport_id, :cargo_price_id, :cargo_description_id, :cargo_items_attributes
  accepts_nested_attributes_for :cargo_items, :allow_destroy => true, :reject_if => :all_blank
  validates_associated :cargo_items
  validates :departure_date, :cargo_state, :airport, :cargo_price, :cargo_description, presence: true
  validates :departure_date, date: { after: Proc.new { Date.today - 1.day }, before: Proc.new { Time.now + 1.year } }, :on => :create
  default_scope :order => 'departure_date DESC'
end

I use following GEMs: simple_forms, nested_forms. This is form to add new Cargo with multiple CargoItems (they have possibility to be added dynamically) belonging to Cargos:

<%= simple_nested_form_for @cargo, :wrapper => false do |f| %>
<%= f.association :airport, :label_method => :full_airport_name, :value_method => :id , :order => :iata_code %>
<%= f.input :departure_date , as: :date, start_year: Date.today.year,
end_year: Date.today.year + 16,
order: [:day, :month, :year] %>
<%= f.association :cargo_description, :label_method => :description, :value_method => :id, :order => :description %>
<%= f.association :cargo_price, :label_method => :price, :value_method => :id %>
<%= f.association :cargo_state, :label_method => :state, :value_method => :id %>
<hr>
<table>
    <tr>
        <th><%= :length %></th>
        <th><%= :width %></th>
        <th><%= :height %></th>
        <th><%= :weight %></th>
        <th><%= :pieces %></th>
    </tr>
    <%= f.simple_fields_for :cargo_items, @cargo_item do |cargo_items_fields| %>
    <tr class="fields">
        <td><%= cargo_items_fields.text_field :length %></td>
        <td><%= cargo_items_fields.text_field :width %></td>
        <td><%= cargo_items_fields.text_field :height %></td>
        <td><%= cargo_items_fields.text_field :weight %></td>
        <td><%= cargo_items_fields.text_field :pieces %></td>
        <td><%= cargo_items_fields.link_to_remove "Remove this item", :confirm => 'Are you sure you want to remove this item?' %></td>
    </tr>
    <% end %>
</table>
<%= f.link_to_add "Add a item", :cargo_items %>

<div class="actions">
    <%= f.button :submit %>
</div>
<% end %>

Cargo controller:

  def new
    @cargo = Cargo.new
    @cargo_item = CargoItem.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @cargo }
    end
  end

  def create
    @cargo = Cargo.new(params[:cargo])
    @cargo.user_id = current_user[:id]

    respond_to do |format|
      if @cargo.save
        format.html { redirect_to @cargo, notice: 'Cargo was successfully created.' }
        format.json { render json: @cargo, status: :created, location: @cargo }
      else
        format.html { render action: "new" }
        format.json { render json: @cargo.errors, status: :unprocessable_entity }
      end
    end
  end

My problem is, validation errors are not shown for CargoItems, model is actually validating. I am not able to save Cargos with CargoItems which does not fulfill validating rules. But in case validations are not met, Cargo is not saved and it just stayed on the same page without any notification that CargoItems fields are invalid. Cargos fields validation errors are shown properly.

Thanx a lot for helping me.

Was it helpful?

Solution

You need to add this errors notication before your form. Take a look at mine for example

<% if @author.errors.any? %>
    <div class="alert alert-block">
        <ul>
            <% @author.errors.full_messages.each do |msg| %>
                <li><%= msg %></li>
            <% end %>
        </ul>
    </div>
<% end %>
<% if @book.errors.any? %>
    <div class="alert alert-block">
        <ul>
            <% @book.errors.full_messages.each do |msg| %>
                <li><%= msg %></li>
            <% end %>
        </ul>
    </div>
<% end %>

<%= form_for([@author, @book], html: { class: "well" }) do |f| %>
#labels and buttons...
<% end %>

I have an Author who has many Books, like so:

Author:

class Author < ActiveRecord::Base
  attr_accessible :name
  has_many :books, dependent: :destroy

  accepts_nested_attributes_for :books, allow_destroy: true

  validates :name, presence: true
  validates :name, length: { minimum: 3 }
end

Book:

class Book < ActiveRecord::Base
  attr_accessible :name, :year
  belongs_to :author

  validates :name, :year, presence: true
  validates :year, numericality: { only_integer: true, less_than_or_equal_to: Time.now.year }
end

OTHER TIPS

Simple Form also allows you to use label, hint, input_field, error and full_error helpers. for more detail documentation --> https://github.com/plataformatec/simple_form

Example code with error,

<%= simple_form_for @user do |f| %>
  <%= f.label :username %>
  <%= f.input_field :username %>
  <%= f.hint 'No special characters, please!' %>
  <%= f.error :username, id: 'user_name_error' %>
  <%= f.full_error :token %>
  <%= f.submit 'Save' %>
<% end %>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top