I'm working on an app that has and agency which has many branches and both the agency and the branches can have addresses. I have created the models for them as shown below:
# agency.rb
has_many :branches
has_one :address
accepts_nested_attributes_for :branches, reject_if: :all_blank, allow_destroy: true
accepts_nested_attributes_for :address, reject_if: :all_blank, allow_destroy: true
# branch.rb
belongs_to :agency
has_one :address
accepts_nested_attributes_for :address, reject_if: :all_blank
# address.rb
belongs_to :agency
belongs_to :branch
I have an agency form which should allow me to create/edit an agency and it's address as well as add/edit/delete branches and their addresses too.
Here is the agency form:
<%= form_for(#agency) do |f| %>
<div class="box-body">
# errors and messages etc etc ...
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name, class: 'form-control' %>
</div>
# more agency fields
<%= f.fields_for :address do |address| %>
<%= render 'addresses/address_fields', f: address %>
<% end %>
#other fields which all work fine
<div id="branches">
<%= f.fields_for :branches do |branch| %>
<%= render 'branch_fields', f: branch %>
<% end %>
<div class="links">
<%= link_to_add_association 'add branch', f, :branches %>
</div>
</div>
</div>
<%= f.submit 'Save Changes', class: 'btn btn-primary' %>
<% end %>
Here are the branch fields (partial form):
# branch name ...
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
# I will explain this bit below
<% if f.object.new_record? %>
<% f.object.build_address %>
<% end %>
###
<%= f.fields_for :address do |address| %>
<%= render 'addresses/address_fields', f: address %>
<% end %>
# other branch fields that work fine
<%= link_to_remove_association "remove branch", f %>
And here is the agencies controller:
class AgenciesController < ApplicationController
before_action :authenticate_user!
before_action :set_agency, only: [:show, :edit, :update]
# before_action :build_address, only: [:new, :edit]
def index
#agencies = Agency.all
end
def show
end
def create
#agency = Agency.new(agency_params)
respond_to do |format|
if #agency.save
format.html { redirect_to #agency, notice: 'Agency was successfully created.' }
format.json { render :show, status: :created, location: #agency }
else
format.html { render :new }
format.json { render json: #agency.errors, status: :unprocessable_entity }
end
end
end
def new
#agency = Agency.new
#agency.build_address
#agency.build_domain_name
#agency.branches.build
#agency.services.build
# #agency.branches.build_addresses
# #agency.branches.each do |branch|
# branch.build_address
# end
end
def edit
end
def update
respond_to do |format|
if #agency.update(agency_params)
format.html { redirect_to #agency, notice: 'Agency was successfully updated.' }
format.json { render :show, status: :ok, location: #agency }
else
format.html { render :edit }
format.json { render json: #agency.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_agency
#agency = Agency.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def agency_params
params.require(:agency).permit(:name, :logo, :description, :phone_number, :alt_phone_number, :email, :alt_email,
services_attributes:
[:id, :name, :description, :_destroy],
address_attributes:
[:id, :first_line, :second_line, :third_line, :city_town, :post_code, :_destroy],
domain_name_attributes:
[:id, :domain],
branches_attributes:
[:id, :name, :description, :phone_number, :alt_phone_number, :_destroy, :email, :alt_email,
services_attributes:
[:id, :name, :description, :_destroy],
address_attributes:
[:id, :first_line, :second_line, :third_line, :city_town, :post_code, :_destroy]
]
)
end
end
Apologies for the lengthy code.
The problem I was facing initially was that when I was adding a new branch, the address fields were not showing up. After some digging, I found a question on SO where someone suggested running f.object.build_address
just before calling the fields for the branch. This worked fine for creating a new branch on the agency form but after saving, and returning to the edit agency page, the address fields for the branch were blank. However, the address was saved correctly to teh database. I think this was caused bu the build_address line overriting the content when editing which is why I attempted to wrap it in the if loop but I'm almost certain this is wrong.
How can I correctly build the nested branch address attributes in the controller so that the fields are shown correctly when adding a new agency and or branch? And how can I ensure that the saved values are displayed correctly when I come back to edit the agency and branch(es) later.
I have done a lot of reading and digging and I cant see any of the normal issues like wrong tags used (<%= / <%) to no avail. Any help would be most appreciated.
Try with these modifications:
<%= f.fields_for #agency.address do |address| %>
<%= render 'addresses/address_fields', f: address %>
<% end %>
#other fields which all work fine
<div id="branches">
<%= f.fields_for #agency.branches do |branch| %>
<%= render 'branch_fields', f: branch %>
<% end %>
Related
I'm working on a small project in Rails loosely following the Rails Tutorial. I have Carrierwave, Fog, and AWS working wonderfully on production for uploading a single image. I wanted to add a gallery of images, so I figured I would follow SSR's answer in the link: Rails 4 multiple image or file upload using carrierwave
Everything seems to work well for my model, and the tests even pass, but when I go to create or edit a listing, the uploader doesn't seem to work. It will hang for minutes without resolving (even on small file sizes), and the console doesn't read that an action was posted on submitting (just reads 200 for the last GET for the form itself). Other than naming conventions (I use Listing as the Post model and listing_gallery instead of post_attachment), the steps were identical. Did Rails 5 change anything about Carrierwave?
listing.rb
class Listing < ApplicationRecord
VALID_PHONE_REGEX = /(\(*(\d{3})\)|(\d{3}-)|(\d{3}))\s*(\d{3})-*(\d{4})/
VALID_ZIP_REGEX = /\d{5}((-)?\d{4})?/
# One use has many listings
belongs_to :user
# Listing_gallery
has_many :listing_galleries
accepts_nested_attributes_for :listing_galleries
# Descending order from newest to oldest as default
default_scope -> { order(created_at: :desc) }
# Carrier Wave mount uploader for images
mount_uploader :picture, PictureUploader
mount_uploader :image, PictureUploader
# Validation of parameters before accepting listing
validates :user_id, presence: true
validates :description, presence: true
validates :street_address, presence: true
validates :city, presence: true, length: { maximum: 30 }
validates :zip_code, presence: true, length: {minimum: 5, maximum: 10}, format: { with: VALID_ZIP_REGEX }
validates :primary_contact, presence: true, length: {minimum: 10, maximum: 15}, format: { with: VALID_PHONE_REGEX }
end
listings_controller.rb
class ListingsController < ApplicationController
before_action :logged_in_user, only: [:new, :create, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]
def new
#listing = Listing.new
#listing_gallery = #listing.listing_galleries.build
end
def create
if current_user.admin?
#listing = current_user.listings.build(listing_params)
#listing.listing_status = "active"
respond_to do |format|
if#listing.save!
params[:listing_galleries]['image'].each do |image|
#listing_gallery = #listing.listing_galleries.create!(:image => image)
end
flash[:success] = "New Listing created!"
redirect_to root_url
else
render 'new'
end
end
else
flash[:failure] = "You must be an admin to create a listing."
redirect_to root_url
end
end
def show
#listing = Listing.find(params[:id])
#listing_galleries = #listing.listing_galleries.all
end
def edit
if current_user.admin?
#listing = Listing.find(params[:id])
render 'edit'
end
end
def update
if current_user.admin?
#listing = Listing.find(params[:id])
respond_to do |format|
if #listing.update_attributes(listing_params)
if params[:listing_galleries] != []
params[:listing_galleries]['image'].each do |image|
#listing_gallery = #listing.listing_galleries.create!(:image => image)
end
end
flash[:success] = "Listing Updated!"
redirect_to #listing
else
render 'edit'
end
end
end
end
def destroy
if current_user.admin?
#listing.listing_status = "deleted"
if #listing.save!
flash[:success] = "Listing DELETED"
redirect_to request.referrer || root_url
else
flash[:failure] = "Could not remove listing"
redirect_to request.referrer || root_url
end
end
end
private
# Check for necessary paramters
def listing_params
params.require(:listing).permit(:description, :street_address, :city, :state,
:zip_code, :primary_contact, :secondary_contact,
:listing_status, :asking_price, :renobb, :picture,
{ image: [] },
listing_galleries_attributes: [:id, :listing_id, :image, :_destroy])
end
# Ensure only the creator of the listing is destroying it
def correct_user
#listing = current_user.listings.find_by(id: params[:id])
if current_user.admin?
return true
end
redirect_to root_url if #listing.nil?
end
end
listings/new.html.erb
<% provide(:title, 'Create Listing') %>
<div id="content">
<div id="sectionbanner">
<p class="goldtext">
Create a New Listing
</p>
</div>
<!-- Article -->
<div id="article">
<div class="form">
<%= form_for(#listing, html: { multipart: true}) do |form| %>
<%= render 'shared/error_messages_listings' %>
<%= form.label :street_address %>
<br>
<%= form.text_field :street_address, class: 'form-control' %>
<br>
<%= form.label :city %>
<br>
<%= form.text_field :city, class: 'form-control' %>
<br>
<%= form.label :state %>
<br>
<%= form.text_field :state, class: 'form-control' %>
<br>
<%= form.label :zip_code %>
<br>
<%= form.text_field :zip_code, class: 'form-control' %>
<br>
<%= form.label :primary_contact %>
<br>
<%= form.text_field :primary_contact, class: 'form-control' %>
<br>
<%= form.label :secondary_contact %>
<br>
<%= form.text_field :secondary_contact, class: 'form-control' %>
<br>
<%= form.label :asking_price %>
<br>
<%= form.number_field :asking_price, class: 'form-control' %>
<br>
<%= form.label :description %>
<br>
<%= form.text_area :description, placeholder: "Details of the lot, rules, etc..." %>
<br>
<%= form.label :renobb %>
<br>
<%= form.check_box :renobb %>
<br>
<span class="picture">
<%= form.file_field :picture, accept: 'image/jpeg, image/gif, image/png' %>
</span>
<br>
<%= form.label :image %>
<br>
<%= form.file_field :image, :multiple => true, name: "listing_galleries[image][]" %>
<br>
<%= form.submit "Create Listing", class: "button" %>
<% end %>
</div>
</div>
</div>
listing_gallery.rb
class ListingGallery < ApplicationRecord
belongs_to :listing
mount_uploader :image, PictureUploader
end
listing_galleries_controller.rb
class ListingGalleriesController < ApplicationController
before_action :set_listing_gallery, only: [:show, :edit, :update, :destroy]
# GET /listing_galleries
# GET /listing_galleries.json
def index
#listing_galleries = ListingGallery.all
end
# GET /listing_galleries/1
# GET /listing_galleries/1.json
def show
end
# GET /listing_galleries/new
def new
#listing_gallery = ListingGallery.new
end
# GET /listing_galleries/1/edit
def edit
end
# POST /listing_galleries
# POST /listing_galleries.json
def create
#listing_gallery = ListingGallery.new(listing_gallery_params)
respond_to do |format|
if current_user.admin?
if #listing_gallery.save
format.html { redirect_to #listing_gallery, notice: 'Listing gallery was successfully created.' }
format.json { render :show, status: :created, location: #listing_gallery }
else
format.html { render :new }
format.json { render json: #listing_gallery.errors, status: :unprocessable_entity }
end
end
end
end
# PATCH/PUT /listing_galleries/1
# PATCH/PUT /listing_galleries/1.json
def update
respond_to do |format|
if current_user.admin?
if #listing_gallery.update(listing_gallery_params)
format.html { redirect_to #listing_gallery, notice: 'Listing gallery was successfully updated.' }
format.json { render :show, status: :ok, location: #listing_gallery }
else
format.html { render :edit }
format.json { render json: #listing_gallery.errors, status: :unprocessable_entity }
end
end
end
end
# DELETE /listing_galleries/1
# DELETE /listing_galleries/1.json
def destroy
if current_user.admin?
#listing_gallery.destroy
respond_to do |format|
format.html { redirect_to listing_galleries_url, notice: 'Listing gallery was successfully destroyed.' }
format.json { head :no_content }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing_gallery
#listing_gallery = ListingGallery.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_gallery_params
params.require(:listing_gallery).permit(:listing_id, :image, { image: [] }, :_destroy)
end
end
EDIT More files from the controllers and views. (Alignment may be funky on SO, but it's alright in project.)
For multiple image upload you need to add this gem to your gemfile
gem 'carrierwave', github: 'carrierwaveuploader/carrierwave'
and permit the params as an open array in your controller: {image: []}
Check gem documentation for more details
https://github.com/carrierwaveuploader/carrierwave
You also seem to have an uploader 'image' which you are not mounting in your model. You only mount 'picture'.
I really don't know if this is a typo, but your problem is on line 1 of your view.
%= form_for(#listing, html: { mulipart: true}) do |form| %>
You are also missing the spelling of Multipart which I suppose is the reason you couldn't upload multiple pictures.
Change it to:
<%= form_for(#listing, html: { multipart: true}) do |form| %>
For more insight, refer to Multiple File Uploads section of Carrierwave Documentation.
I have an "undefined method" issue with my app, and don't find where it comes from :(.
In my app, i have 4 models :
Deal, Pool (which belongs to deal), Facility (which belongs to pool), Facilityschedule (which belongs to Facility).
class Deal < ActiveRecord::Base
has_many :pools, :dependent => :destroy
accepts_nested_attributes_for :pools, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
class Pool < ActiveRecord::Base
belongs_to :deal
has_many :facilities, :dependent => :destroy
accepts_nested_attributes_for :facilities, :allow_destroy => true
end
class Facility < ActiveRecord::Base
belongs_to :pool
has_many :facilityschedules, :dependent => :destroy
accepts_nested_attributes_for :facilityschedules, :reject_if => lambda { |a| a[:date].blank? }, :allow_destroy => true
end
class Facilityschedule < ActiveRecord::Base
belongs_to :facility
end
I have a partial form which allows the user to create all of these :
<%= form_for(#deal) do |f| %>
<% if #deal.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#deal.errors.count, "error") %> prohibited this deal from being saved:</h2>
<ul>
<% #deal.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name, "Deal name"%>
<%= f.text_field :name %>
<br/>
</div>
<div>
<%= f.fields_for :pools do |builder|%>
<%= builder.label :name, "Pool name" %>
<%= builder.text_field :name, :rows => 3 %>
<%= builder.check_box :_destroy %>
<%= builder.label :_destroy, "Remove Pool" %>
<br/>
<%= builder.fields_for :facilities do |fbuilder|%>
<%= fbuilder.label :name, "Facility name" %>
<%= fbuilder.text_field :name, :rows => 3 %>
<%= fbuilder.check_box :_destroy %>
<%= fbuilder.label :_destroy, "Remove Facility" %>
<br/>
<%= fbuilder.fields_for :facilitieschedules do |sbuilder|%>
<%= sbuilder.label :date, "Schedule" %>
<%= sbuilder.text_field :date, :rows => 3 %>
<%= sbuilder.check_box :_destroy %>
<%= sbuilder.label :_destroy, "Remove Schedule" %>
<br/>
</div>
<% end %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And finally, i have my Deal controller where the issue is located (new action) :
class DealsController < ApplicationController
before_action :set_deal, only: [:show, :edit, :update, :destroy]
# GET /deals
# GET /deals.json
def index
#deals = Deal.all
end
# GET /deals/1
# GET /deals/1.json
def show
end
# GET /deals/new
def new
#deal = Deal.new
2.times do
pool = #deal.pools.build
2.times do
**facility = #pool.facilities.build**
1. times { facility.facilityschedules.build }
end
end
end
# GET /deals/1/edit
def edit
end
# POST /deals
# POST /deals.json
def create
#deal = Deal.new(deal_params)
respond_to do |format|
if #deal.save
format.html { redirect_to #deal, notice: 'Deal was successfully created.' }
format.json { render :show, status: :created, location: #deal }
else
format.html { render :new }
format.json { render json: #deal.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /deals/1
# PATCH/PUT /deals/1.json
def update
respond_to do |format|
if #deal.update(deal_params)
format.html { redirect_to #deal, notice: 'Deal was successfully updated.' }
format.json { render :show, status: :ok, location: #deal }
else
format.html { render :edit }
format.json { render json: #deal.errors, status: :unprocessable_entity }
end
end
end
# DELETE /deals/1
# DELETE /deals/1.json
def destroy
#deal.destroy
respond_to do |format|
format.html { redirect_to deals_url, notice: 'Deal was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_deal
#deal = Deal.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def deal_params
params.require(:deal).permit(:name, pools_attributes: [:id, :name, :number, :deal_id, :_destroy, facilities_attributes: [:id, :name, :pool_id, :_destroy, facilityschedules_attributes: [:id, :facility_id, :date, :_destroy]]])
end
end
When i try to create a new deal, the following error message pops up "undefined method `facilities' for nil:NilClass" (in bold in the Deal controller, above).
What am i doing wrong?
Many thanks and have a good week end :)
# GET /deals/new
def new
#deal = Deal.new
2.times do
pool = #deal.pools.build
2.times do
**facility = #pool.facilities.build**
1. times { facility.facilityschedules.build }
end
end
end
In the code above you have never set the #pool variable, but instead set pool.
Undefined method for Nil::NilClass is never about not having declared the method, it's that you're trying to call it on a nil object, which is an object of NilClass.
There are also some strange patterns in this method. I've never seen the ** around code in Rails. Are you trying to comment out the line?
Would this work better?
# GET /deals/new
def new
#deal = Deal.new
2.times do
#pool = #deal.pools.build
2.times do
facility = #pool.facilities.build
facility.facilityschedules.build
end
end
end
I am required to use nested forms on an assignment I am working on and I got stuck because my nested form attributes wont submit to database.
Here is what my controller looks like
def new
#booking = Booking.new
params[:no_of_passengers].to_i.times { #booking.passengers.build }
end
def create
#booking = Booking.new(booking_params)
respond_to do |format|
if #booking.save
format.html { redirect_to '/booking_confirmed', notice: 'Booking was successfully created.' }
format.json { render :show, status: :created, location: #booking }
else
format.html { render :new }
format.json { render json: #booking.errors, status: :unprocessable_entity }
end
end
end
private
def booking_params
params.permit(
:airline, :origin, :destination, :departure_date, :departure_time, :arrival_date,
:arrival_time, :flight_id, :price, :no_of_passengers, :user_id, :booking,
passenger_attributes: [
:id,:booking_id, :name, :email,:done,:_destroy
]
)
end
Here is the association between the models
class Booking < ActiveRecord::Base
has_many :passengers
accepts_nested_attributes_for :passengers, reject_if: lambda { |attributes| attributes['name'].blank? }
end
class Passenger < ActiveRecord::Base
belongs_to :bookings
end
And here is the form
<%= form_for #booking do |b| %>
<%= b.fields_for :passengers do |p| %>
<%= p.text_field :name, placeholder: "Passenger Name" %>
<%= p.text_field :email, placeholder: "Passenger Email" %>
<% end %>
<% end %>
I checked the passenger table using Passenger.all in rails console and it returns nothing.
What am I doing wrong?
After a pairing session with sunnyk, I was able to see the errors.
The first error was that my class Passenger has belongs_to :bookings instead of belongs_to :booking. This is a common error though. The Associations between these classes now looks like:
class Booking < ActiveRecord::Base
belongs_to :flight
has_many :passengers
accepts_nested_attributes_for :passengers, reject_if:
lambda {|attributes| attributes['name'].blank?}, :allow_destroy => true
end
class Passenger < ActiveRecord::Base
belongs_to :booking
end
class Flight < ActiveRecord::Base
has_many :bookings
has_many :passengers, through: :bookings
accepts_nested_attributes_for :passengers
accepts_nested_attributes_for :bookings
end
Next:
Instead of using the default value of no_of_passengers for building my nested form, I used the cocoon gem, which makes nested forms building and management easier. I also crated a new params method, in which I made the flight_id permitted, and then passed it as an argument for my booking instance in my new method alongside my current user. So now my new method looks like this.
def new
#booking = Booking.new(new_booking_params)
#booking.user = current_user if current_user
end
def new_booking_params
params.permit(:flight_id)
end
After that, I had to make another params method for my create method, so as to allow the parameters I want in the bookings table, this include the passengers_attributes. Now my create method looks like this.
def create
#booking = Booking.new(another_booking_params)
respond_to do |format|
if #booking.save
format.html { redirect_to '/booking_confirmed', notice: 'Booking was successfully created.' }
format.json { render :show, status: :created, location: #booking }
else
format.html { render :new }
format.json { render json: #booking.errors, status: :unprocessable_entity }
end
end
end
def another_booking_params
params.require(:booking).permit(:flight_id, :user_id, :no_of_passengers,
passengers_attributes:[:name, :email])
end
Lastly, I had to adjust my form to look like this.
<%= form_for(#booking, url: bookings_path) do |f| %>
<%= f.hidden_field(:flight_id)%>
<%= f.hidden_field(:user_id) %>
<%= f.hidden_field(:no_of_passengers)%>
<%= f.fields_for :passengers do |passenger| %>
<%= render 'passenger_fields', :f => passenger %>
<% end %>
<%= link_to_add_association 'Add Another passenger',f, :passengers, :class => 'btn btn-primary add' %>
<%= submit_tag "Book Now", class: "btn btn-primary book" %>
<% end %>
and passenger_fields partial looks like.
<div class="nested-fields form-inline">
<div class="form-group">
<%= f.text_field :name, :class => "form-control", placeholder: "Passenger Name" %>
</div>
<div class="form-group">
<label>-</label>
<%= f.text_field :email, :class => "form-control", placeholder: "Passenger Email" %>
</div>
<div class="links pull-right">
<%= link_to_remove_association "Delete", f, class: "btn btn-danger" %>
</div>
<hr>
</div>
All that did the trick. I hope this will help others to understand nested forms better
I have a rails 4 application that has an add page and and a edit page. You can add elements easily (there is no issues), but then when you go to edit those and click save, it adds the fields you added initially a second time.
Here is my _form.html.erb
<%= nested_form_for #store do |f| %>
<%= f.fields_for :products do |product_form| %>
<div class='field'>
<%= product_form.text_field :name %>
<%= product_form.hidden_field :_destroy %>
<%= link_to "REMOVE PRODUCT", '#', class: "remove_fields" %>
</div>
<% end %>
<p><%= f.link_to_add "Add PRODUCT", :products %></p>
<%= f.submit 'Save', :class => "primary small" %>
<% end %>
and my store.rb model:
class Store < ActiveRecord::Base
has_many :products, class_name: "StoreProduct"
accepts_nested_attributes_for :products, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
my update action in my controller looks like:
def update
respond_to do |format|
if #store.update(store_params)
format.html { redirect_to store_products_path(#store), notice: 'Store was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #store.errors, status: :unprocessable_entity }
end
end
end
What does store_params look like in your controller? If id isn't one of the permitted values, then you can start to see the nested models created as new records each time the update action occurs. You would want to have something like:
params.require(:store).permit(products_attributes: [:id, :name, :_destroy])
See the documentation on strong parameters for the nested_form gem.
it seems like a lot of people posted this problem as here but the answer there, is not my case I guess.
in my models I have
class Project < ActiveRecord::Base
has_many :questions, dependent: :destroy
validates :name, presence: true, uniqueness: true
validates :category_id, presence: true
end
and
class Question < ActiveRecord::Base
belongs_to :project
validates :question, presence: true
validates :question_type, presence: true
validates :project_id, presence: true
QUESTIONS_TYPES = ['Single', 'Multiple', 'A text']
end
<%= form_for(#question) do |f| %>
tha form:
<div class="field">
<%= f.label :project_id %><br>
<%= f.select :project_id, #project_options %>
</div>
<div class="field">
<%= f.label :question %><br>
<%= f.text_field :question %>
</div>
<div class="field">
<%= f.label :question_type %><br>
<%= f.select :question_type, Question::QUESTIONS_TYPES %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The controller
class QuestionsController < ApplicationController
before_action :set_question, only: [:show, :edit, :update, :destroy]
before_action :set_projects, only: [:new, :edit]
.
.
def create
#question = Question.new(question_params)
.
.
end
.
.
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:question, :question_type, :project_id)
end
def set_projects
#project_options = Project.all.map{|p| [p.name, p.id]}
end
end
The error
undefined method `empty?' for nil:NilClass
Extracted source (around line #16):
<div class="field">
<%= f.label :project_id %><br>
<%= f.select :project_id, #project_options %>
</div>
the post answer I mentioned before says it should be project_id in the form, but it is correct in my code. In my case the error raises only if I have some empty fields otherwise it goes well. could be something wrong with validations?
Thanks!!
Yes it seems it has validation issue and could cot create/update the record.
But the error is: your create and update action probably have a else block in the controller to handle the failed cases. make sure you initiate #project_options there in the else block. What happens is it cant create the record hence tries to render the new/edit form directly(not executing new/edit methods so #project_options is not initialized). put something in your controller in create action like:
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'Question was successfully updated.' }
format.json { head :no_content }
else
format.html do
set_projects #need to call set_projects method here.
render action: "new"
end
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
You should have same thing in your update action as well
The error you have is that empty? method is called on nil. The two objects here are #question and #project_options. Check if you have assigned the proper values to these instance variables in your controller.