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])
Related
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.
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 %>
When I'm trying to create a new "participation" in my Rails4 application and it seems like there is something wrong with my parameters. Actually this is not causing any problems in application (or I didn't notice it) but still I would like to fix it. You can see 2 "examination_id" parameters one of them is null and the other one is equal to 1.
REQUEST PARAMETERS:
{"utf8"=>"✓",
"authenticity_token"=>"XZ71eV0zxrnTBilzvEtLlHLwoAb+qKdDfxOHjrAHUPg=",
"participation"=>
{
"language_preference"=>"Türkçe",
"exam_center_preference"=>"1",
"disability"=>"1",
"user_id"=>"1",
"examination_id"=>""
},
"commit"=>"Sınava Başvur",
"examination_id"=>"1"
}
routes.rb:
resources :examinations do
resources :participations do
member do
get :update_profile_information
end
end
end
participation.rb:
class Participation < ActiveRecord::Base
belongs_to :user
belongs_to :examination
before_save :verification_key_generator
end
participations_controller.rb:
class ParticipationsController < ApplicationController
before_filter :authenticate_user!
before_action :set_participation, only: [:show, :edit, :update, :destroy]
before_filter :get_examination
def get_examination
#examination = Examination.find(params[:examination_id])
end
def index
#participations = #examination.participations
end
def show
#participation = #examination.participations.find(params[:id])
end
def new
#participation = Participation.new
end
def create
#participation = #examination.participations.new(participation_params)
#participation.user = current_user
respond_to do |format|
if #participation.save
format.html { redirect_to [#examination, #participation], notice: 'Başvuru işlemi başarıyla tamamlandı!' }
format.json { render action: 'show', status: :created, location: [#examination, #participation] }
else
render 'new'
format.html { render action: 'new' }
format.json { render json: #participation.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #participation.update(participation_params)
format.html { redirect_to [#examination, #participation], notice: 'Başvurunuz Başarıyla Güncellendi!' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: participation.errors, status: :unprocessable_entity }
end
end
end
private
def set_participation
#participation = Participation.find(params[:id])
end
def participation_params
params.require(:participation).permit(:user_id, :examination_id, :payment_status, :language_preference, :exam_center_preference, :disability)
end
end
app/views/participations/_form.html.erb:
<%= simple_form_for([#examination, #participation], html:{class: "well"}) do |f| %>
<%= f.input :user_id, :as => :hidden, :input_html => { :value => current_user.id } %>
<%= f.input :examination_id, as: :hidden %>
<%= f.input :language_preference, collection: ["Türkçe", "İngilizce", "Rusça"], label: 'Sınav Dili Tercihi' %>
<%= f.input :exam_center_preference, collection:ExamCenter.all, label: 'Sınav Merkezi Seçiniz', label_method: :city %>
<%= f.input :disability, inline_label: 'Yardımcı İstiyorum', label: false %>
<%= f.button :submit, "Sınava Başvur" %>
<% end %>
app/views/participations/new.html.erb:
<%= simple_form_for([#examination, #participation]) do |f| %>
<%= f.error_notification %>
<%= f.input :language_preference, collection: ["Türkçe", "İngilizce", "Rusça"], label: 'Sınav Dili Tercihi' %>
<%= f.input :exam_center_preference, collection:ExamCenter.all, label: 'Sınav Merkezi Seçiniz', label_method: :city %>
<%= f.input :disability, inline_label: 'Yardımcı İstiyorum', label: false %>
<%= f.input :user_id, :as => :hidden, :input_html => { :value => current_user.id } %>
<%= f.input :examination_id, as: :hidden %>
<%= f.button :submit, "Sınava Başvur" %>
<% end %>
sa
When you're using
<%= simple_form_for([#examination, #participation], html:{class: "well"}) do |f| %>
to generate the form, it will set the action to be /examinations/[examination_id]/participations so the routes/action will know the examination_id from the url itself.
So, you don't need to pass examination_id separately as hidden field that you're setting as
<%= f.input :examination_id, as: :hidden %>
Once you remove this hidden field the request parameters will look like:
{"utf8"=>"✓",
"authenticity_token"=>"XZ71eV0zxrnTBilzvEtLlHLwoAb+qKdDfxOHjrAHUPg=",
"participation"=>
{
"language_preference"=>"Türkçe",
"exam_center_preference"=>"1",
"disability"=>"1",
"user_id"=>"1"
},
"commit"=>"Sınava Başvur",
"examination_id"=>"1"
}
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.
My nested form fields for friends will not show no matter what i do..have the accepts_nested_attributes setup properly i believe?..
views/user_steps/show.html.erb
<%= simple_form_for #user do |f| %>
<%= f.input :city %>
<%= f.input :address %>
<%= f.input :zipcode %>
<%= f.input :date_of_birth %>
<%= f.input :gender, :collection => ['male','female'] %>
<%= f.association :interests, :as => :check_boxes, :label => false %>
<%= f.association :holidays, :as => :check_boxes, :label => false %>
<%= f.simple_fields_for :friends do |friend_f| %>
<%= friend_f.input :name %>
<%= friend_f.input :dob %>
<%= friend_f.input :gender %>
<% end %>
<%= f.button :submit %>
<%end%>
class UserStepsController < ApplicationController
def show
#user = current_user
end
def update
#user = current_user
#user.attributes = params[:user]
#friend = Friend.new(params[:friend])
end
def new
#user = User.new
#user.build_friend
end
end
class UsersController < ApplicationController
before_filter :authenticate_user!
def index
authorize! :index, #user, :message => 'Not authorized as an administrator.'
#users = User.paginate(:page => params[:page])
end
def show
#user = User.find(params[:id])
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'Friend birthday(1) was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
end
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :interests_attributes, :remember_me, :city, :zipcode, :date_of_birth, :gender, :address, :interest_ids, :holiday_ids
has_and_belongs_to_many :holidays
has_and_belongs_to_many :interests
has_many :friends
accepts_nested_attributes_for :friends, allow_destroy: true
accepts_nested_attributes_for :interests, allow_destroy: true
accepts_nested_attributes_for :holidays, allow_destroy: true
class Friend < ActiveRecord::Base
belongs_to :user
attr_accessible :dob, :gender, :name
end
My guess is that #user has no friends, so there's nothing to render.
If this is creating a new user and you want them to be able to fill in their friends as well, do a #user.friends.build somewhere, which will add an empty friend to them, and should allow the nested fields to render.
I've found this answer several times on the net. I'm using ruby-2.2.0 with rails 4.2.0. I'd like to know if this has changed, or if it's something specific to me.
I had to use. #user.build_friends