Rails creating a form on a show template with nested_attributes - ruby-on-rails

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.

Related

Rails - How to translate form_for collection_select to simple_form?

How can I translate the following form_for - collection_select to simple_form?
<%= collection_select(:service, :service_menu_id, #service_menus, :id, :name, prompt: true) %>
To...
<%= f.input ...
Update requested:
<div class="col-xs-4">
<%= simple_form_for #service do |f| %>
<div class="field">
<!--Working - selected value saves to db-->
<%= collection_select(:service, :service_menu_id, ServiceMenu.all, :id, :name, {:prompt => true }) %>
<!--Selected value does not save to db-->
<%#= f.input :service_menu, :collection => #service_menus, label_method: :name, value_method: :id, :include_blank => false, prompt: "Select a main service" %>
<%= f.simple_fields_for :styles do |task| %>
<%= render 'style_fields', :f => task %>
<% end %>
</div>
<div class="links">
<%= link_to_add_association 'Add New Style', f, :styles, class: 'btn btn-success' %>
</div><br>
<div class="actions">
<%= f.submit :class => 'btn btn-primary'%>
</div>
<% end %>
controller
class ServicesController < ApplicationController
before_action :set_service, only: [:show, :edit, :update, :destroy]
def index
#services = current_tech.services
end
def show
end
def new
#service = current_tech.services.build
#service_menus = ServiceMenu.all
end
def create
#service = current_tech.services.build(service_params)
respond_to do |format|
if #service.save
format.html { redirect_to #service, notice: 'Service was successfully created.' }
format.json { render :show, status: :created, location: #service }
else
format.html { render :new }
format.json { render json: #service.errors, status: :unprocessable_entity }
end
end
end
def edit
#service_menus = ServiceMenu.all
end
def update
respond_to do |format|
if #service.update(service_params)
format.html { redirect_to #service, notice: 'Service was successfully updated.' }
format.json { render :show, status: :ok, location: #service }
else
format.html { render :edit }
format.json { render json: #service.errors, status: :unprocessable_entity }
end
end
end
def destroy
#service.destroy
respond_to do |format|
format.html { redirect_to services_url, notice: 'Service was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_service
#service = Service.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def service_params
params.require(:service).permit(:name, :service_menu_id, styles_attributes: [:id, :tech_id, :name, :hours, :minutes, :price, :details, :_destroy])
end
end
If you can wrap it as form object (i.e., f.collection_select) then this will work
<%= f.input :service_menu, :collection => #service_menus, :label_method => :name, :value_method => :id, :selected => #service.service_menu_id :include_blank => true %>

Form goes blank after submitting

I don't know what happened but my question form stopped working and now goes blank after submitting.
Here is the form view:
<%= simple_form_for [#comment, Question.new] do |f| %>
<p>
<div class="form">
<%= f.input :title, as: :text, input_html: { rows: "1" } %>
<%= f.input :body, as: :text, input_html: { rows: "10" } %>
<p><%= f.submit "Answer", class: "btn btn-primary" %></p>
</div>
<% end %>
The questions model:
class Question < ActiveRecord::Base
validates :body, presence: true
validates :title, presence: true
validates :user_id, presence: true
belongs_to :user
acts_as_votable
belongs_to :comment
has_many :pictures
end
and the controller:
def create
#comment = Comment.find(params[:comment_id])
#question = #comment.questions.create(question_params)
respond_to do |format|
if #question.save
format.html { redirect_to comment_questions_path, notice: 'Question was successfully created.' }
format.json { render action: 'show', status: :created, location: comment_questions_path }
else
format.html { render action: 'new' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
The main problem was in routing: you can't redirect_to #question for nested resources. Use
url_for([#comment, #question])

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: Showing Error Messages [bootstrap-sass, formtastic]

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

Resources