Validation errors are not displaying at multipart form in rails - ruby-on-rails

I have a model BookingPost that has many Reservations.
In booking_posts/show.html.erb I have:
<div class="card-action">
<%= form_for([#reservation.booking_post, #reservation], html: {multipart: true}, class: "col s12") do |f| %>
<% if #reservation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reservation.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #reservation.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="col s6">
<%= f.label :start %>
<%= f.date_field :start, placeholder: "start time", class: "datepicker" %>
</div>
<div class="col s6">
<%= f.label :end %>
<%= f.date_field :end, placeholder: "end time", class: "datepicker" %>
</div>
<div class="col s6">
<%= f.label :reservation_time %>
<%= f.time_field :reservation_time, placeholder: "time", class: "timepicker", id: "timepicker", type: "time" %>
</div>
<div class="input-field col s6">
<%= f.label :name %>
<%= f.text_field :name, class: "validate" %>
</div>
<div class="input-field col s6">
<%= f.label :email %>
<%= f.text_field :email, class: "validate" %>
</div>
<div class="input-field col s6">
<%= f.label :phone_number %>
<%= f.text_field :phone_number, class: "validate" %>
</div>
<div class="waves-effect waves-light btn">
<%= f.submit t(:submit_reservation)%>
</div>
<% end %>
<br>
</div>
booking_posts_controller:
# GET /booking_posts/1
# GET /booking_posts/1.json
def show
#booking_picture = #booking_post.booking_pictures.build
#booking_pictures = #booking_post.booking_pictures
#reservation = #booking_post.reservations.build
#reservations = #booking_post.reservations
end
reservations_controller:
# GET /reservations/new
def new
#reservation = Reservation.new
end
def create
#booking_post = BookingPost.find(params[:booking_post_id])
#email= User.where(admin: true).first.email
#reservation = #booking_post.reservations.build(reservation_params)
respond_to do |format|
if #reservation.save
#saved_reservation = #reservation
format.html { redirect_to :back, notice: 'Reservation was successfully created.' }
format.json { render :show, status: :created, location: #reservation }
ReservationMailer.fresh_message(#saved_reservation, #email).deliver_now
else
format.html {redirect_to :back
flash[:info] = #reservation.errors.full_messages do |m|
m
end}
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
But I can't see any validation errors, even like presence: true.
Seems like I don't have correct #reservation, because I have a deal with Array in my form_for. Help me please to solve this issue, thanks!

The reason you are not seeing validation errors is because you are issuing a redirect_to :back when validations fails instead of rendering :new action which already includes any errors you might have inside the #reservation instance object.
Also you were trying to add the error messages into the flash message while trying to display them using the #reservation object.
this should be the correct else clause
else
format.html { render :new }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end

Related

AJAX not working in Rails same-page update

I am trying to build a Q&A app with Ajax on the Index.html.erb. I manage to get the form remotely loading, but when saving the records, the AJAX does not work and the user is taken to the normal show.html.erb. Apart from the Ajax not kicking off, everything works well.
My code is as below:
index.html.erb (Contain a partial for input, and a partial for results)
<div>
<h3 class="section_title"> Q&A </h3>
<hr>
<div id="qanda-form" style="display:none;"> </div>
</div>
<div id="qandas">
<%= render 'qandas/qanda' %>
</div>
_qanda.html.erb (is the partial for results)
<% #qandas.each do |my_qanda| %>
<div class="col-md-9">
<div>
Created <%= local_time(my_qanda.created_at) %>, by <%= User.find_by(id: my_qanda.user_id).full_name %>
</div>
</div>
<% end %>
_form.html.erb (is the input form - has nested form via Cocoon)
<%= simple_form_for #qanda, remote: true do |f| %>
<%= f.error_notification %>
<%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
<div class="col-md-12 form-inputs">
<div class="col-md-8">
<%= f.input :title, label: 'Q&A Title:' %>
</div>
</div>
<div class="qandasquestions">
<%= f.simple_fields_for :qandasquestions do |builder| %>
<% render 'qandas/qandasquestion_fields', f: builder %>
<% end %>
<div class="links btn-group" style="min-height: 34px !important">
<%= f.button :submit, "Publish Q&A", class: "btn btn-default" %>
<%= link_to_add_association 'Add Question', f, :qandasquestions, class: 'btn btn-default', data: {association_insertion_node: '.qandasquestions', association_insertion_method: :append} %>
<%= link_to 'Back', qandas_path, class: "btn btn-default" %>
<%= f.input :company, :as => :hidden, :input_html => {:value => current_user.company} %>
</div>
</div>
<% end %>
Controller:
def index
#qandas = Qanda.all
respond_to do |format|
#qandas = Qanda.all
format.html
format.json
end
end
def create
#qanda = current_user.qandas.build(qanda_params)
respond_to do |format|
if #qanda.save!
#qandas = Qanda.all
format.html { redirect_to #qanda, notice: 'Qanda was successfully created.' }
format.json {render :layout => false}
else
format.html { render :new }
format.json { render json: #qanda.errors, status: :unprocessable_entity }
end
end
end
create.js.erb
$('#qandas').html("<%= j render partial: 'qandas/qanda' %>");
$('#qanda-form').slideUp(350);
new.js.erb
$('#qanda-form').html("<%= j render 'qandas/form' %>");
$('#qanda-form').slideDown(350);
Anybody can see why the Ajax does not kick off please? why am I redirected to the traditional SHOW page please?
Try updating your code to this and let me know if it's working?
def create
#qanda = current_user.qandas.build(qanda_params)
if #qanda.save!
#qandas = Qanda.all
else
#errors = #qanda.errors
end
end

Displaying items captured via a nested form

I'm trying to build a small expense tracking app. Using the nested_form gem to add line items. There is an Expense model which accepts nested attributes. Items belong to expenses and there is a foreign key association. Here's the expense controller:
class ExpensesController < ApplicationController
def new
#expense = Expense.new
#item = #expense.items.build
end
def index
#expenses = Expense.all
##items = Item.where(:expense_id => #expense.id)
end
def show
#expense = Expense.find(params[:id])
#items = Item.where(:expense_id => #expense.id)
end
def create
#expense = Expense.new(expense_params)
respond_to do |format|
if #expense.save
format.html { redirect_to #expense, notice: 'Expense Report Submitted.' }
format.json { render :show, status: :created, location: #expense }
else
format.html { render :new }
format.json { render json: #expense.errors, status: :unprocessable_entity }
end
end
end
def edit
#expense = Expense.find(params[:id])
end
def update
#expense = Expense.find(params[:id])
if #expense.save(expense_params)
flash[:notice] = "Expense Report Updated"
redirect_to #expense
else
render 'edit'
end
end
def destroy
#expense = Expense.find(params[:id])
#expense.destroy
redirect_to 'root'
end
private
def expense_params
params.require(:expense).permit(:department_id, :expense_type_id, :notes, items_attributes: [:id, :description, :amount, :issue_date, :_destroy])
end
end
The form looks like:
<%= nested_form_for (#expense) do |f| %>
<% if #expense.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#expense.errors.count, "error") %> prohibited
this expense from being saved:</h2>
<ul>
<% #expense.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class"row">
<div class="col-md-8">
<div class="form-group">
<%= f.label :department_id %><br>
<%= f.collection_select(:department_id, Department.all, :id, :department_name, prompt: true, class: "dropdown-menu") %>
</div>
<div class="form-group">
<%= f.label :expense_type_id %><br>
<%= f.collection_select(:expense_type_id, ExpenseType.all, :id, :expense_name, prompt: true, class: "form-control") %>
</div>
<%= f.fields_for :items do |i| %>
<div class="form-group">
<%= i.label :description%>
<%= i.text_field :description, class: "form-control" %>
</div>
<div class="form-group">
<%= i.label :amount%>
<%= i.text_field :amount, class: "form-control" %>
</div>
<div class="form-group">
<%= i.label :issue_date%>
<%= i.date_select :issue_date, class: "form-control" %>
</div>
<%= i.link_to_remove "Remove", class: "btn btn-default" %>
<% end %>
<div><p><%= f.link_to_add "Add Expense", :items, class: "btn btn-default" %></p></div>
<div class="form-group">
<%= f.label :notes %>
<%= f.text_area :notes, class: "form-control" %>
</div>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
When I hit submit, the expense and items are saved. I checked with Sqlite browser and the foreign key values are captured for each item.
The index file looks like:
<% #expenses.each do |expense| %>
<tr>
<td><%= expense.item.description %></td>
<td><%= number_to_currency(expense.item.amount) %></td>
<td><%= expense.item.issue_date %></td>
<% end %>
I tried the usual combinations (like expense.item.description) by passing through a block, but they aren't working. I would like to know how to display the expense and the associated items in the show and index pages.
Looking at your new action, in your models you would have
class Expense < ActiveRecord::Base
has_many :items
accepts_nested_attributes_for :items
end
So when you are doing expense.items in your view it gives you an active record relation(since expense has many items), try this:
<% #expenses.each do |expense| %>
<% expense.items.each do |item| %>
<tr>
<td><%= item.description %></td>
<td><%= number_to_currency(item.amount) %></td>
<td><%= item.issue_date %></td>
</tr>
<% end %>
<% end %>

undefined method `i18n_key' for Address:Class

I get this error when I load a page that contains a form (like edit.html.erb or new.html.erb). It freezes on the labels. I need to underline that I am not using ActiveRecord as an ORM in my app but Perpeuity gem which is an implementation of the Datamapper pattern. Leaving Activerecord behind has proved a bit problematic so maybe someone will be able to help.
The form partial:
<%= form_for(#address) do |f| %>
<% if #address.errors.to_a.any? %>
<div id="error_explanation">
<h2><%= pluralize(#address.errors.count, "error") %> prohibited this address from being saved:</h2>
<ul>
<% #address.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row collapse">
<div class="small-3 columns">
<% require 'debugger'; debugger %>
<%= f.label :line1, class: "right inline" %>
</div>
<div class="small-7 columns left">
<%= f.text_field :line1 %>
</div>
</div>
<div class="row collapse">
<div class="small-3 columns">
<%= f.label :line2, class: "right inline" %>
</div>
<div class="small-7 columns left">
<%= f.text_field :line2, :placeholder => "(optional)" %>
</div>
</div>
<div class="row collapse">
<div class="small-3 columns">
<%= f.label :postcode, class: "right inline" %>
</div>
<div class="small-7 columns left">
<%= f.select :postcode, Address::POSTCODES, :prompt => 'Select a postcode (optional)' %>
</div>
</div>
<div class="row collapse">
<div class="small-3 columns">
<%= f.label :city, class: "right inline" %>
</div>
<div class="small-7 columns left">
<%= f.text_field :city %>
</div>
</div>
<div class="row collapse">
<div class="small-3 columns">
<%= f.label :county, class: "right inline" %>
</div>
<div class="small-7 columns left">
<%= f.select :postcode, Address::COUNTIES, :prompt => 'Select a county (optional)' %>
</div>
</div>
<div class="row collapse">
<div class="small-9 small-offset-3 columns">
<%= f.submit %>
</div>
</div>
The model:
class Address
extend ActiveModel::Naming
extend ActiveModel::Translation
include Perpetuity::RailsModel
def errors
#errors ||= ActiveModel::Errors.new(self)
end
def read_attribute_for_validation(attr)
send(attr)
end
def save
validate!
errors.empty? ? super : false
end
def validate!
#place custom validations here e.g.
errors.add(:name, "cannot be blank.") if self.name = ""
errors.add(:number,"must be less than 7.") if self.number >= 7
end
attr_accessor :name, :city, :county, :line1, :line2, :postcode
attr_reader :errors
end
The controller with relevant methods:
class AddressesController < ApplicationController
def new
#address = Address.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #address }
end
end
def edit
#require 'debugger'; debugger
#address = Perpetuity[Address].find(params[:id])
end
def create
#address = Address.new(params[:address])
Perpetuity[Address].insert #address
respond_to do |format|
if #address.save
format.html { redirect_to #address, notice: 'Address was successfully created.' }
format.json { render json: #address, status: :created, location: #address }
else
format.html { render action: "new" }
format.json { render json: #address.errors, status: :unprocessable_entity }
end
end
end
def update
#address = Perpetuity[Address].find(params[:id])
respond_to do |format|
if #address.update_attributes(params[:address])
format.html { redirect_to #address, notice: 'Address was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #address.errors, status: :unprocessable_entity }
end
end
end
end
I am using Rails 3.2 and ActiveModel gem installed has version 3.2.13. I had a look at the gem code and cannot find method i18n_key in it, while this documentation here [link]http://www.rubydoc.info/docs/rails/3.1.1/ActiveModel/Name:i18n_key indicates that it should be in there (similarly it is in 3.2.8 docs). Is it a bug or am I doing something wwrong? Thank your for your help.
I was getting this error and it turned out that I was using what appeared to be a reserved keyword in one of my classes. In my case it was model_name
Renaming it solved the issue for me.

Rails4 Displaying Nested Form saves only one row

I need a form that allows users to accept 4 set of inputs to invite four users into an entity. The following is the code.
# GET /company_members/new
def new
#company_member = CompanyMember.new
#company_member.company_members.build
end
# POST /company_members
# POST /company_members.json
def create
#company_member = CompanyMember.new(company_member_params)
#company_member.user_id = 1
#company_member.company_id = 1
respond_to do |format|
if #company_member.save
format.html { redirect_to #company_member, notice: 'Company member was successfully created.' }
format.json { render action: 'show', status: :created, location: #company_member }
else
format.html { render action: 'new' }
format.json { render json: #company_member.errors, status: :unprocessable_entity }
end
end
end
Form:
<%= form_for(#company_member) do |f| %>
<!--<% if #company_member.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#company_member.errors.count, "error") %> prohibited this company_member from being saved:</h2>
<ul>
<% #company_member.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>-->
<%= f.fields_for #company_member do |yes| %>
email: <%= yes.text_field :email %> role: <%= yes.collection_select :company_member_role_id, CompanyMemberRole.all, :id, :name, :prompt => "Please select" %>
<% end %><br>
<%= f.fields_for #company_member do |yes| %>
email: <%= yes.text_field :email %> role: <%= yes.collection_select :company_member_role_id, CompanyMemberRole.all, :id, :name, :prompt => "Please select" %>
<% end %><br>
<%= f.fields_for #company_member do |yes| %>
email: <%= yes.text_field :email %> role: <%= yes.collection_select :company_member_role_id, CompanyMemberRole.all, :id, :name, :prompt => "Please select" %>
<% end %>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
<%= show_errors(#company_member, :email) %>
</div>
<!--<div class="field">
<%= f.label :company_id %><br>
<%= f.collection_select :company_id, Company.all, :id, :name %>
</div>-->
<div class="field">
<%= f.label :company_member_role_id %>
<%= f.collection_select :company_member_role_id, CompanyMemberRole.all, :id, :name, :prompt => "Please select" %>
<%= show_errors(#company_member, :company_member_role_id) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It just saves one Row in the Database while it has to save 4 rows. Also is there a way to remove the un filled rows if any?

After submit form I want to stay in the same page and display :notice messages

All my code is working nicely, I want to render the same page :new after a user submits a form with your order. The problem is about the :notice message that I want to display Pedido enviado com sucesso. in the page after a submission but it doesn't work. My validation error messages are displayed nicely but I don't know why my success message doesn't.
Any tips?
(Sorry about my code indentation)
My pedidos_controller goes down:
class PedidosController < ApplicationController
def new
#pedido = Pedido.new
1.times do
pessoa = #pedido.build_pessoa
produto = #pedido.produtos.build
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #pedido }
end
end
def create
#pedido = Pedido.new(params[:pedido])
respond_to do |format|
if #pedido.save
PedidosMailer.delay.registro_do_pedido(#pedido)
PedidosMailer.delay.email_para_cotar_produtos(#pedido)
format.html { redirect_to action: "new", notice: 'Pedido enviado com sucesso.' }
format.json { render json: #pedido, status: :created, location: #pedido }
else
format.html { render action: "new" }
format.json { render json: #pedido.errors, status: :unprocessable_entity }
end
end
end
end
my new.html.erb view:
<p id="notice"><%= notice %></p>
<%= render 'form' %>
my _form.html.erb view:
<%= form_for(#pedido, :html => { :class => "form-contato"}) do |f| %>
<% if #pedido.errors.any? %>
<div id="error_explanation">
<h2>Ocorreram <%= pluralize(#pedido.errors.count, "erro") %></h2>
<ul>
<% #pedido.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="span4">
<h1>Dados pessoais</h1>
<%= f.fields_for :pessoa do |builder| %>
<%= render 'pessoa_fields', f: builder %>
<% end %>
</div>
<div class="span8">
<h1>Ítens</h1>
<%= f.fields_for :produtos do |builder| %>
<%= render 'produto_fields', f: builder %>
<% end %>
</div>
<div class="span10">
<%= link_to_add_fields "Adicionar mais produtos", f, :produtos %>
</div>
<%= button_tag "Enviar", class: "btn btn-red span10", name: "commit" %>
</div>
<% end %>
my _pessoa_fields.html.erb view:
<fieldset>
<%= f.text_field :nome, class: "span4", placeholder: "Nome" %>
<br />
<%= f.text_field :telefone, class: "span4", placeholder: "Telefone" %>
<br />
<%= f.text_field :email, class: "span4", placeholder: "Email" %>
</fieldset>
my _produto_fields.html.erb view:
<% #lista_de_produtos = ["Qualibom standard", "Qualibom premium", "Bomdemais standard", "Bomdemais premium"] %>
<fieldset class="campos-produtos span10">
<div class="span3">
<%= f.select :nome, options_for_select(#lista_de_produtos, :selected => f.object.nome), :prompt => 'Selecione um produto' %>
</div>
<div class="span3">
<%= f.text_field :quantidade, class: "span3", placeholder: "Quantidade" %>
</div>
</fieldset>
You need to use flash[:notice], not notice, in your view:
<% if flash[:notice] %>
<p id="notice"><%= flash[:notice] %></p>
<% end %>
When you pass a message via the notice: parameter of redirect_to, it's placed into the flash array, which is a special pseduo-session which persist for a single request:
From the ActionController::Redirecting documentation:
It is also possible to assign a flash message as part of the redirection. There are two special accessors for the commonly used flash names alert and notice as well as a general purpose flash bucket.

Resources