Rails: Showing Error Messages [bootstrap-sass, formtastic] - ruby-on-rails

I'm using Bootstrap-Sass along with Formstatic. I thought an error message should be automatically shown next to the field with Formstatic like in this picture:
(source: asciicasts.com)
But even if the user puts an invalid input, my app does not show an error message. This seems to be an easy problem but I cant figure out the reason behind.
PostController
# POST /posts
# POST /posts.json
def create
#post = Post.new(params[:post])
#post.view = 0
#post.like = 0
#post.hate = 0
respond_to do |format|
if #post.save
#posts = Post.paginate(:page => params[:page], order: 'like desc', per_page: 10)
format.html { redirect_to posts_path }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
PostModel
validates :name, :presence => true
validates :content, :presence => true,
:length => { :minimum => 10, :maximum => 300}
_form (Post)
<% #post = Post.new %>
<%= semantic_form_for #post do |f| %>
<%= f.semantic_errors :name %>
<%= f.inputs do %>
<%= f.input :name, :label => 'name' %>
<%= f.input :content, :label => 'body' %>
<% end %>
<%= f.actions do %>
<%= f.action :submit, :button_html => { :class => "btn btn-primary" }, :as => :button %>
<%= f.action :cancel, :as => :link %>
<% end %>
UPDATE: In PostController, I deleted the following two lines
#format.html { render action: "new" }
#format.json { render json: #post.errors, status: :unprocessable_entity }
and added
render #post.errors
Then, I got
#messages={:name=>["can't be blank"], :content=>["can't be blank", "is too short (minimum is 10 characters)"]}>
So the problem is that the way I'm rendering json is wrong. Could someone help me how to fix it?

You pass presence validation in name and content and length validation in content that means if you don't enter any value in name or content then it will give error like can't be blank and if content value length is less than 10 and greater then 300 then it will give error.
If you want to pass validation for invalid input then you have to pass validates_format_of validation.
You puts invalid input in name or content?
Can you provide invalid input that you enter?
Update
# in /config/initializers/formtastic_config.rb.
Formtastic::SemanticFormBuilder.inline_errors = :sentence
See Video : http://railscasts.com/episodes/185-formtastic-part-2
Get Code : https://github.com/ryanb/railscasts-episodes/tree/master/episode-185

Related

Rails creating a form on a show template with nested_attributes

I have a rails app with events and event_registrants, someone can essentially register for an event.
Here's my event model:
class Event < ActiveRecord::Base
has_many :event_registrants, :dependent => :destroy
accepts_nested_attributes_for :event_registrants, :reject_if => lambda { |a| a[:first_name].blank? }, :allow_destroy => true
Here's my event_registrant model:
class EventRegistrant < ActiveRecord::Base
belongs_to :event
attr_accessible :comment, :company, :email, :first_name, :last_name, :phone, :event_id
validates_presence_of :company, :email, :first_name, :last_name, :phone
end
On the show template, I'd like to include a form to allow someone to register directly from there.
<%= form_for #event do |f| %>
<%= f.fields_for :event_registrants do |builder| %>
<%= render "registration_form", :f => builder %>
<% end %>
<%= f.submit 'Send it', :class => "blue-btn", :id => "registrant_submit" %>
<% end %>
Partial:
<ul class="form" id="register_form">
<li><%= f.text_field :first_name, :placeholder => "First name *" %> <%= f.text_field :last_name, :placeholder => "Last name *" %></li>
<li><%= f.text_field :email, :placeholder => "Email address *", :class => 'wide' %></li>
<li><%= f.text_field :company, :placeholder => "Company name *", :class => 'wide' %></li>
<li><%= f.text_field :phone, :placeholder => "Phone number *", :maxlength => '14' %></li>
<li><%= f.text_area :comment, :placeholder => "Additional info", :class => 'wide', :rows => 4, :cols => 68 %></li>
</ul>
Finally my events controller'
def show
#event = Event.where(:event_hosting_type => "eureka_event").find_by_permalink(params[:id])
1.times {#event.event_registrants.build}
respond_to do |format|
format.html # show.html.erb
format.json { render json: #event }
end
end
def update
#event = Event.find_by_permalink(params[:id])
respond_to do |format|
if #event.update_attributes(params[:event])
format.html { redirect_to #event, notice: "#{#event.title} updated." }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
def create
#event = Event.new(params[:event])
#event_registrant = #event.build_event_registrant
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'New event created.'}
format.json { render json: #event, status: :created, location: #event }
else
format.html { render action: "new" }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
The issue I'm having is that the current form will display but will only update the current record, having 1.times {#event.event_registrants.build} will add a new, empty form but the previous entry will be there. I'd like someone to submit their info, have the form reset and allow someone else to submit new info.
You can update your code to say
1.times {#event.event_registrants.build} if #event.event_registrants.empty?
Your form will properly show the value of event_registrants if it exists, or build it if not there.
However, if you're looking to dynamically add or remove form fields, you may find the cocoon gem an easy way to handle the javascript/ruby involved with that.

Instance Variable string collection lost after render => 'new'

When I get an error creating a quote, it renders the same page it was just on and displays the errors. Unfortunately two inputs are drop down menus of strings, and they disappear when the refresh happens.
I've looked at Rail 3: instance variable not available after redirection which talks about sessions, which looks like it could be the right way to go but I'm not sure. Any help would be appreciated.
quotes controller
def new
#quote = Quote.new
#quote.items.build
#types = ["T-Shirt", "Hoodie", "Sweatpants"]
#colors = ["White", "Black", "Red", "Blue", "Green"]
end
def create
#quote = Quote.new(params[:quote])
respond_to do |format|
if #quote.save
format.html { redirect_to root_url }
flash[:success] = "Your quote is being approved. You will recieve an email shortly!"
format.json { render json: #quote, status: :created, location: #quote }
else
format.html { render :action => 'new' }
format.json { render :json => #quote.errors, :status => :unprocessable_entry }
flash[:error] = "Quote failed to create! Try again!"
end
end
end
form partial
<!-- item form -->
<%= f.input :make, collection: #types, label: 'Thread Type' %>
<%= f.input :amount, label: 'How Many' %>
<%= f.input :color, collection: #colors %>
<!-- nested form for creating a design of an item -->
<%= f.simple_fields_for :designs, :html => { :multipart => true } do |designform| %>
<%= render "customdesign", g: designform %>
<% end %>
<!-- add/remove another design -->
<%= f.link_to_add "Add Design", :designs %>
<%= f.input :note, :input_html => { :cols => 50, :rows => 3 }, label: 'Special Notes or Requests' %>
<%= f.link_to_remove "Remove" %>
#colors and #types are only set in the new action, and not the create action. Rendering a template does not automatically call the action method in the controller; it goes straight to the view.
A possible solution is to define helper methods for these lists:
# app/helpers/quote_helper.rb
module QuoteHelper
def possible_types
["T-Shirt", "Hoodie", "Sweatpants"]
end
end
And in your view:
<%= f.input :make, collection: possible_types, label: 'Thread Type' %>

getting the selected value from the drop down in rails

enter code here
<h1>Add New Investment Opportunity</h1>
<%= form_for Investopp.new do |f| %>
<div class="field">
<%= f.label :state_id %><br/>
<%= f.collection_select :state_id, Investopp.year_lookup(#state_ids), :label, :value, include_blank: true %>
</div>
<div class="field">
<%= f.label :city_id, "city" %><br />
<%= f.grouped_collection_select :city_id, Investopp.year_lookup(#state_ids), :cities, :value, :id,:name, include_blank: true %>
</div>
<% end %>
<%= link_to 'Back', investopps_path %>
<%= link_to 'Search', investopps_browsedisplay_path %>
class Investopp < ActiveRecord::Base
attr_accessible :Address, :Buildingname, :Desiredinvrole, :Details, :Prefferednoofinvestors, :Salesprice, :Weblisting, :photo, :user_id, :state_id, :city_id, :state, :city
has_attached_file :photo, :styles => { :small => "200x200>" }
belongs_to :user
validates :Buildingname, presence: true
validates :Address, presence: true
validates :Desiredinvrole, presence: true
validates :Weblisting, presence: true
validates :Details, presence: true
has_many :states
has_many :cities
def find_state(id)
if !id || id==0
id=1
end
#states= State.find(id)
#states.name
end
def find_city(id)
if !id || id==0
id=1
end
#cities= City.find(id)
#cities.name
end
def self.year_lookup(state_ids)
#create an emptycollection to hold the LabelValue Objects
years = []
state_ids.each do |yr| y = LabelValue.new()
y.label = yr
y.value = State.find_by_id(yr).name
years.push(y)
end
years
end
def self.state_lookup(state_ids)
years = []
state_ids.each do |yr| y = State.new()
y= State.find_by_id(yr)
years.push(y)
end
years
end
end
class LabelValue
# name the accessors. Label and Value
attr_accessor :label, :value
def cities
cityids=[]
state_cities=[]
investopps=Investopp.find(:all)
investopps.each do |i|
puts i.city_id
cityids <<i.city_id
end
cityids.uniq!
states=State.find_by_id(label)
cityids.each do |c|
if states.cities.find_by_id(c)
state_cities<< states.cities.find_by_id(c)
end
end
state_cities
end
end
class InvestoppsController < ApplicationController
# GET /investopps
# GET /investopps.json
def index
#investopps = Investopp.where(:user_id => current_user.id)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #investopps }
end
end
# GET /investopps/1
# GET /investopps/1.json
def show
#investopp = current_user.investopps.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #investopp }
end
end
# GET /investopps/new
# GET /investopps/new.json
def new
#investopp = Investopp.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #investopp }
end
end
# GET /investopps/1/edit
def edit
#investopp = Investopp.find(params[:id])
end
# POST /investopps
# POST /investopps.json
def create
#params[:investopp][:state_id]= "gopi"
#params[:investopp][:city_id]= "33"
#investopp = current_user.investopps.build(params[:investopp])
respond_to do |format|
if #investopp.save
format.html { redirect_to #investopp, notice: 'Investopp was successfully created.' }
format.json { render json: #investopp, status: :created, location: #investopp }
else
format.html { render action: "new" }
format.json { render json: #investopp.errors, status: :unprocessable_entity }
end
end
end
# PUT /investopps/1
# PUT /investopps/1.json
def update
#investopp = Investopp.find(params[:id])
respond_to do |format|
if #investopp.update_attributes(params[:investopp])
format.html { redirect_to #investopp, notice: 'Investopp was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #investopp.errors, status: :unprocessable_entity }
end
end
end
# DELETE /investopps/1
# DELETE /investopps/1.json
def destroy
#investopp = Investopp.find(params[:id])
#investopp.destroy
respond_to do |format|
format.html { redirect_to investopps_url }
format.json { head :no_content }
end
end
def lis
#state_names=[]
#state_ids=[]
#city_ids= []
#city_names=[]
#investopp = Investopp.find(:all)
#investopp.each do |item|
#state_names<< State.find_by_id(item.state_id).name
#state_ids<< item.state_id
#city_names<< City.find_by_id(item.city_id).name
#city_ids << item.city_id
end
puts #state_ids.uniq!{|i| i}
puts #city_ids.uniq!{|i| i}
puts "gopi"
respond_to do |format|
format.html { render "investopps/lis", :locals => { :state_ids => #state_ids, :city_ids => #city_ids, :investopps => #investopp } }
format.json { render json: #investopp }
end
end
end
Instead of using <%= link_to 'Search', investopps_browsedisplay_path %> you should use <%= f.submit %> and specify the action correctly. So your form view will look like this:
<h1>Add New Investment Opportunity</h1>
<%= form_for Investopp.new, :action => investopps_browsedisplay_path do |f| %>
<div class="field">
<%= f.label :state_id %><br/>
<%= f.collection_select :state_id, Investopp.year_lookup(#state_ids), :label, :value, include_blank: true %>
</div>
<div class="field">
<%= f.label :city_id, "city" %><br />
<%= f.grouped_collection_select :city_id, Investopp.year_lookup(#state_ids), :cities, :value, :id,:name, include_blank: true %>
</div>
<%= link_to 'Back', investopps_path %>
<%= f.submit 'Search' %>
<% end %>
Then you'll also need a controller method handling things as the investopps_browsedisplay_path route, which I don't see in your code anywhere. This, of course, is not a RESTful way to handle this, and there's a needed caveat that your architecture will probably confuse the problem, but so far as sending the form data, the correct way to do it is with a form submit, not a link_to, which solves the basic problem at hand.

Don't save record after install sorcery or formtastic

I try to rails console for me table object but when I install sorcery or formtastic (i don't know) my record don't save.
Model
class Depositi < ActiveRecord::Base
attr_accessible :code, :description
validates_presence_of :code, :message => 'Code required!'
end
View
<%= semantic_form_for(#depositi) do |f| %>
<%= f.inputs 'Dati Deposito' do %>
<%= f.input :code, :label => 'Codice Deposito:' , :wrapper_html => { :class => 'fl' }, :required => true %>
<%= f.input :description, :label => 'Descrizione:', :wrapper_html => { :class => 'fl'}, :input_html => {:size => '15'} %>
<% end %>
<%= f.actions do %>
<%= f.action :submit, :as => :button, :label => 'Save' %>
<% end %>
<% end %>
this is my debug:
utf8 ✓
authenticity_token kVQ5OOkmGxqoZgbvteJ80M+lLHwopWEY0SI4YetQYsg=
depositi {"code":"001","description":"Test this is test"}
button
action new
Controller
def create
#depositi = Depositi.new(params[:depositi])
respond_to do |format|
if #depositi.save
format.html { redirect_to #depositi, notice: 'Record salvato con successo!' }
format.json { render json: #depositi, status: :created, location: #depositi }
else
format.html { render action: "new" }
format.json { render json: #depositi.errors, status: :unprocessable_entity }
end
end
end
This record don't save! I'm property login, i don't have error..why don't save?
RESOLVED: The problem was in my view up of <%= semantic_form_for(#depositi) do |f| %>
I write that was in conflict with formtastic render form.

rails: "unknown action" message when action is clearly specified

I had hard time to figure out why I've been getting "unknown action" error message when I was do some editing:
Unknown action
No action responded to 11. Actions: bin, create, destroy, edit, index, new, observe_new, show, tag, update, and vote
you can see that Rails did mention each action in the above list - update. And in my form, I did specify action = "update".
I wonder if some friends could kindly help me with the missing links...
here is the code:
edit.rhtml
<h1>Editing tip</h1>
<% form_tag :action => 'update', :id => #tip do %>
<%= render :partial => 'form' %>
<p>
<%= submit_tag_or_cancel 'Save Changes' %>
</p>
<% end %>
_form.rhtml
<%= error_messages_for :tip %>
<p><label>Title<br/>
<%= text_field :tip, :title %></label></p>
<p><label>Categories<br/>
<%= select_tag('categories[]', options_for_select(Category.find(:all).collect {|c| [c.name, c.id] }, #tip.category_ids), :multiple => true ) %></label></p>
<p><label>Abstract:<br/>
<%= text_field_with_auto_complete :tip, :abstract %></label></p>
<p><label>Name: <br/>
<%= text_field :tip, :name %></label></p>
<p><label>Link: <br/>
<%= text_field :tip, :link %></label></p>
<p><label>Content<br/>
<%= text_area :tip, :content, :rows => 5 %></label></p>
<p><label>Tags <span>(space separated)</span><br/>
<%= text_field_tag 'tags', #tip.tag_list, :size => 40 %></label></p>
class TipsController < ApplicationController
before_filter :authenticate, :except => %w(index show)
# GET /tips
# GET /tips.xml
def index
#tips = Tip.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #tips }
end
end
# GET /tips/1
# GET /tips/1.xml
def show
#tip = Tip.find_by_permalink(params[:permalink])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #tip }
end
end
# GET /tips/new
# GET /tips/new.xml
def new
#tip = session[:tip_draft] || current_user.tips.build
end
def create
#tip = current_user.tips.build(params[:tip])
#tipMail=params[:email]
#if tipMail
# TipMailer.deliver_email_friend(params[:email], params[:name], tip)
# flash[:notice] = 'Your friend has been notified about this tip'
#end
#tip = current_user.tips.build(params[:tip])
#tip.categories << Category.find(params[:categories]) unless params[:categories].blank?
#tip.tag_with(params[:tags]) if params[:tags]
if #tip.save
flash[:notice] = 'Tip was successfully created.'
session[:tip_draft] = nil
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def edit
#tip = Tip.find(params[:id])
end
def update
#tip = Tip.find(params[:id])
respond_to do |format|
if #tip.update_attributes(params[:tip])
flash[:notice] = 'Tip was successfully updated.'
format.html { redirect_to(#tip) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #tip.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#tip = Tip.find(params[:id])
#tip.destroy
respond_to do |format|
format.html { redirect_to(tips_url) }
format.xml { head :ok }
end
end
def observe_new
session[:tip_draft] = current_user.tips.build(params[:tip])
render :nothing => true
end
end
the quick answer is that form_tag doesn't support :action as an option, you want to be passing a string as a path in. A slightly longer answer is you shouldn't be using form_tag anyways for a model edit form, you should be using form_for.
what rails are you using? .rhtml is pretty old, rails generators should be giving you .html.erb files. if it is something even remotely recent, you should be able to use
<% form_for #tip do |f| %>
<%= f.label :title, 'Title' %><br />
<%= f.text_field %>
... etc
<% end %>

Resources