Instance Variable string collection lost after render => 'new' - ruby-on-rails

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' %>

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.

Rails 4 - Nested Routes and Form Parameters

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"
}

Saving data into a model from another controller

I have a controller, which saves fine for that specific controller and model (accesspoint). However, i want to save a particular data into another model (radhuntgroup) - which i do not know how.
def create
#accesspoint = Accesspoint.new(params[:accesspoint])
#accesspoint.user_id = current_user.id
o = [('a'..'z'), ('1'..'9'), ('A'..'Z')].map { |i| i.to_a }.flatten
#accesspoint.secret = (0...30).map{ o[rand(o.length)] }.join
respond_to do |format|
if #accesspoint.save
format.html { redirect_to accesspoints_path, notice: 'Access Point has been added.' }
format.json { render json: #accesspoint, status: :created, location: #accesspoint }
else
format.html { render action: "new" }
format.json { render json: #accesspoint.errors, status: :unprocessable_entity }
end
end
end
the above looks fine for accesspoint controller and model (saves all the parameters from form into the accesspoint table) however, i want to save one particular data into another field into the radhuntgroup table.
accesspoint view.
%= simple_form_for #accesspoint, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<div class="controls">
<%= f.input :shortname, :label => false, :autofocus => true, :placeholder => 'Access Point Name', :hint => 'example: quadifi_hotspot' %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
accesspoints_path, :class => 'btn' %>
</div>
<% end %>
in this case, i hope to duplicate the "shortname" column in the accesspoint table into the radhuntgroup table in the "groupname" column. - which i am looking at using the controller to do this.
If i were to do it in PHP for example, this would be a lot easier but i am dealing with legacy databases which most parts of backend is already "hardcoded" this way and i cannot fully follow the conventions.

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

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