Nested fields_for form wont create child objects rails 5 - ruby-on-rails

sale.rb "Parent"
class Sale < ActiveRecord::Base
has_many :branch_history_solds
accepts_nested_attributes_for :branch_history_solds, :reject_if => lambda { |a| a[:content].blank? },
:allow_destroy => true
end
class SalesController < ApplicationController
before_action :set_sale, only: [:show, :edit, :update, :destroy]
# GET /sales
# GET /sales.json
def index
#sales = Sale.all
end
# GET /sales/1
# GET /sales/1.json
def show
end
# GET /sales/new
def new
#sale = Sale.new
#sale.branch_history_solds.build
end
# GET /sales/1/edit
def edit
end
# POST /sales
# POST /sales.json
def create
#sale = Sale.create(sale_params)
# #sale.branch_history_solds.build
respond_to do |format|
if #sale.save
format.html { redirect_to #sale, notice: 'Sale was successfully created.' }
format.json { render :show, status: :created, location: #sale }
else
format.html { render :new }
format.json { render json: #sale.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /sales/1
# PATCH/PUT /sales/1.json
def update
#sale = Sale.find(params[:id])
respond_to do |format|
if #sale.update_attributes(sale_params)
format.html { redirect_to #sale, notice: 'Sale was successfully updated.' }
format.json { render :show, status: :ok, location: #sale }
else
format.html { render :edit }
format.json { render json: #sale.errors, status: :unprocessable_entity }
end
end
end
# DELETE /sales/1
# DELETE /sales/1.json
def destroy
#sale.destroy
respond_to do |format|
format.html { redirect_to sales_url, notice: 'Sale was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_sale
#sale = Sale.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def sale_params
params.require(:sale).permit(:receipt_no, :customer_name, :phone_number, :email, :branch_id, :paid, branch_history_sold_attributes: [:id, :sold, :branch_product_id])
end
end
branch_history_sold.rb "Child"
class BranchHistorySold < ActiveRecord::Base
belongs_to :sale
end
class BranchHistorySoldsController < ApplicationController
def index
#search = BranchHistorySold.ransack(params[:q])
#branch_sold_histories = #search.result(distinct: true).group(:name).sum(:sold)
end
def create
#sale = Sale.find(params[:sale_id]) # Find specific branch_product we will be working with
#branch_history_sold = #sale.branch_history_solds.create(branch_history_sold_params) # Enable whitelisted attributes to get created
flash[:notice] = "New products have been Sold from branch" # flash notice will show immediately after branch_history_sold gets created
redirect_to branch_product_path(#branch_product) # redirect to branch_product show page
end
def destroy
#sale = Sale.find(params[:sale_id]) # Find specific branch_product we will be working with
#branch_history_sold = #sale.branch_history_solds.find(params[:id]) # Find specific branch_history_sold that will be destroyed
#branch_history_sold.destroy # destroy branch_history_sold
flash[:notice] = "Newly sold products have been added back to branch" # flash notice will show immediately after branch_history_sold is destroyed
redirect_to branch_product_path(#branch_product) # redirect to branch_product show page
end
private
def branch_history_sold_params
params.require(:branch_history_sold).permit(:sold, :customer_name) # whitelisted attributes
end
end
And finally my form with the fields_for attribute
<div class="container">
<div class="row">
<%= form_for #sale, html: { class: "form-horizontal" } do |f| %>
<!-- Text input-->
<div class="form-group">
<label class="col-md-1 control-label">R/NO</label>
<div class="col-md-6">
<%= f.collection_select(:branch_id, Branch.all, :id, :name) %>
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-1 control-label">R/NO</label>
<div class="col-md-6">
<%= f.text_field :receipt_no, placeholder: "Receipt number", class: "form-control input-md" %>
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-1 control-label" >Name</label>
<div class="col-md-6">
<%= f.text_field :customer_name, placeholder: "Prince Abalogu", class: "form-control input-md" %>
</div>
</div>
<!-- Appended Input-->
<div class="form-group">
<label class="col-md-1 control-label">Number</label>
<div class="col-md-6">
<%= f.text_field :phone_number, placeholder: "08185438075", class: "form-control input-md" %>
</div>
</div>
<!-- Appended Input-->
<div class="form-group">
<label class="col-md-1 control-label">E-mail</label>
<div class="col-md-6">
<%= f.text_field :email, placeholder: "example#yahoo.com", class: "form-control input-md" %>
</div>
</div>
<!-- Appended Input-->
<%= f.fields_for :branch_history_solds, #sale.branch_history_solds.build do |b| %>
<div class="form-group">
<label class="col-md-1 control-label">Product</label>
<div class="col-md-6">
<%= b.number_field :sold, placeholder: "Quantity" %>
</div>
</div>
<div class="form-group">
<label class="col-md-1 control-label"></label>
<div class="col-md-6">
<% #branch = BranchProduct.where :branch_id, 19 %>
<%= b.collection_select(:branch_product_id, BranchProduct.where(branch_id: params[:branch_id] ), :id, :name ) %> Select Product
</div>
</div>
<% end %>
<!-- Appended Input-->
<div class="form-group">
<label class="col-md-1 control-label"></label>
<div class="col-md-6">
<%= f.check_box :paid %> Paid
</div>
</div>
<!-- Button (Double) -->
<div class="form-group">
<label class="col-md-1 control-label"></label>
<div class="col-md-8">
<%= f.button :submit %>
</div>
</div>
<% end %>
</div>
</div>
The form displays but the only problem im having now is that it doesnt create any branch_history_solds after I submit

The problem is that the lambda you are using to evaluate if the nested records should be rejected will always return true since your form/model does not have a content attribute:
class Sale < ActiveRecord::Base
has_many :branch_history_solds
accepts_nested_attributes_for :branch_history_solds, :reject_if => lambda { |a| a[:content].blank? },
:allow_destroy => true
end
You're also whitelisting the wrong attributes branch_history_sold not branch_history_solds.
You need to change this to be an attribute that is actually passed:
class Sale < ActiveRecord::Base
has_many :branch_history_solds
accepts_nested_attributes_for :branch_history_solds, :reject_if => lambda { |a| a[:branch_product_id].blank? },
:allow_destroy => true
end
However your general setup is just plain strange and I don't know if its just the naming but it does not make much sense.
If you want to create a point of sales system or order management system you would do it like so:
class Order
belongs_to :customer
has_many :line_items
has_many :products, through: :line_items
accepts_nested_attributes_for :line_items,
allow_destroy: true,
reject_if: -> { |li| li[:product_id].blank? || li[:quantity].blank? }
end
# columns:
# - order_id [integer, index, foreign key]
# - product_id [integer, index, foreign key]
# - quantity [decimal or integer]
# - price [decimal]
# - subtotal [decimal]
class LineItem
belongs_to :order
belongs_to :product
end
class Product
has_many :line_items
has_many :orders, through: :line_items
end
class OrdersController
def new
end
def create
#order = Order.new(order_params) do
order.customer = current_user
end
if (#order.save)
else
end
end
private
def order_params
params.require(:order)
.permit(:foo, :bar, line_item_attributes: [:product_id, :quantity])
end
end
Note that you should only let users pass an extremely limited number of params - never take things like prices from the user. The actual pricing logic should be done on the model layer. You also wan't to detach the customer details from the order model - otherwise every repeat order will duplicate data. I would spend some time getting the actual domain model down before adding additional features like search.

Related

Nested attributes in rails 5.0 errored while saving the record

I have User model (for devise ) and then i have member which references User and then portfolio which references member .
i have created a user while signingup .
Now i want the signed up user to update his deatails which is members and portfolio tables .
The portfolio model is :-
class Portfolio < ApplicationRecord
belongs_to :member
validates_presence_of title:
end
class Member < ApplicationRecord
belongs_to :user
has_one :portfolio
accepts_nested_attributes_for :portfolio
end
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one :member
validates_presence_of :name
validates :email, uniqueness: true
after_create :create_member_portfolio
def create_member_portfolio
puts "Test "
end
end
in my members_controller the code i have is :-
class MembersController < ApplicationController
before_action :set_member, only: [:show, :edit, :update, :destroy]
# GET /members
# GET /members.json
def index
#members = Member.all
end
# GET /members/1
# GET /members/1.json
def show
end
# GET /members/new
def new
#member = setup_member(Member.new)
end
# GET /members/1/edit
def edit
end
# POST /members
# POST /members.json
def create
p = member_params
byebug
#member = Member.new(p)
byebug
#member.user_id = current_user.id unless current_user.nil?
respond_to do |format|
if #member.save
format.html { redirect_to #member, notice: 'Member was successfully created.' }
format.json { render :show, status: :created, location: #member }
else
format.html { render :new }
format.json { render json: #member.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /members/1
# PATCH/PUT /members/1.json
def update
respond_to do |format|
if #member.update(member_params)
format.html { redirect_to #member, notice: 'Member was successfully updated.' }
format.json { render :show, status: :ok, location: #member }
else
format.html { render :edit }
format.json { render json: #member.errors, status: :unprocessable_entity }
end
end
end
# DELETE /members/1
# DELETE /members/1.json
def destroy
#member.destroy
respond_to do |format|
format.html { redirect_to members_url, notice: 'Member was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_member
#member = Member.find(params[:id])
end
def setup_member(member)
member.portfolio ||= Portfolio.new
member
end
# Only allow a list of trusted parameters through.
def member_params
# slice(*filter.keys).each{|k,v| puts "#{k}:#{v}"}
#byebug
params.require(:member).permit(
:dob,
:email,
:phone,
portfolio_attributes: [ :title, :subtitle ]
)
end
end
And the html.erb is as given below :-
<%= form_for(#member) do |f| %>
<% if #member.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(member.errors.count, "error") %> prohibited this member from being saved:</h2>
<ul>
<% #member.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-control">
<%= f.label :dob %>
<%= f.datetime_select :dob %>
</div>
<div class="form-control">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="form-control">
<%= f.label :phone %>
<%= f.text_field :phone %>
</div>
<div class="col-md-12">
<h2>Profile Details :</h2>
<div>
<%= f.fields_for :portfolio do |ff| %>
<div class="form-control">
<%= ff.label :title %>
<%= ff.text_field :title %>
</div>
<div class="form-control">
<%= ff.label :subtitle %>
<%= ff.text_field :subtitle %>
</div>
<% end %>
</div>
</div>
<div class="form-group">
<%= f.submit 'Save Member Item', class: 'btn btn-primary btn-block' %>
</div>
<% end %>
But when in the create controller method on save of member object it fails and says that Portfolio.member does not exist .
Although i an getting the portfolio_attributes as key with title and subtitle in the passed in params and those are validated too , but fails on save . Could you please let me know what did i do wrong here ?
The error i am gettng here adter member.save is called is as shown below :-
byebug) #member.errors
#<ActiveModel::Errors:0x00007fa011bceba8 #base=#<Member id: nil, fname: "asdsa", lname: "asdfsda", dob: "2020-06-16 18:59:00", email: "asddfsda#asdfdsa.com", religion_id: nil, phone: "", created_at: nil, updated_at: nil, user_id: 1>, #messages={:"portfolio.member"=>["must exist"]}, #details={:"portfolio.member"=>[{:error=>:blank}]}>
(byebug)
You might be able to isolate which field is causing the error by checking:
#member = Member.new(p)
#member.valid?
#member.errors
For more information, see the valid? and invalid? section of the Active Record Validations and Callbacks documentation.
It seems there is a bug in version rails 5.0 . and to move away from the default behavior(not allowing to save entry without the parent entry ) we'll have to add
class Portfolio < ApplicationRecord
belongs_to :member, optional: true
end
which should do the trick . To follow check this link :-
https://github.com/rails/rails/issues/18233

Creating a dynamic drop down menu raising a Load Error in my controller

I am updating my code to move from static drop down menus to dynamic related drop down menus. I am following some instructions from an online tutorial adapting to fit my needs but have become unstuck . The tutorial I am following is here....https://rubyplus.com/articles/3691-Dynamic-Select-Menus-in-Rails-5
LoadError (Unable to autoload constant Job_category, expected C:/Users/User/Desktop/ServeandProtect/app/models/job_category.rb to define it):
app/views/jobs/listing.html.erb:22:in block in _app_views_jobs_listing_html_erb__816863472_104736972'
app/views/jobs/listing.html.erb:16:in_app_views_jobs_listing_html_erb__816863472_104736972'
** My View/HTML - first drop down has been updated to use models **
<div class="row">
<div class="col-md-3">
<%= render 'job_menu' %>
</div>
<div class="col-md-9">
<div class="panel panel-default">
<div class="panel-heading">
Listing
</div>
<div class="panel-body">
<div class="container">
<%= form_for #job do |f| %>
<div class="row">
<div class="col-md-4 select">
<div class="form-group">
<%= f.label :job_category_id %><br />
<%= f.collection_select :job_category_id, Job_category.order(:job_category),
:id, :job_category, include_blank: true %>
</div>
</div>
<div class="col-md-4 select">
<div class="form-group">
<label>Job Type</label>
<%= f.select :job_type, [["Cleaning", "Cleaning"], ["Gardening", "Gardening"],
["Rubbish Clearance", "Rubbish Clearance"], ["Removals", "Removals"],
["Collection & Delivery", "Collection & Delivery"], ["Car Service & Repairs", "Car Service & Repairs"]],
id: "job_type", prompt: "Select...", class: "form-control" %>
</div>
</div>
<div class="col-md-4 select">
<div class="form-group">
<label>Frequency</label>
<%= f.select :recurrence, [["One Off", "One Off"], ["Daily", "Daily"],
["Weekly", "Weekly"], ["Bi-Monthly", "Bi-Monthly"],
["Once-Monthly", "Once-Monthly"]],
id: "recurrence", prompt: "Select...", class: "form-control" %>
</div>
</div>
</div>
<div><%= f.submit "Save", class: "btn btn-normal" %></div>
<% end %>
</div>
</div>
</div>
</div>
</div>
** My Controller **
class JobsController < ApplicationController
before_action :set_job , except: [:index, :new, :create, :edit, :delete_image_attachment ]
before_action :authenticate_user!, except: [:show]
before_action :is_authorised, only: [:listing, :budget, :description, :photo_upload, :location,
:update, :show, :delete, :featured, :premium ]
# GET /jobs
def index
#jobs = Job.all
end
# GET /jobs/1
def show
end
# GET /jobs/new
def new
#job = current_user.jobs.build
end
def listing
##job = current_user.job
end
# GET /jobs/1/edit
def edit
end
def budget
end
# POST /jobs
def create
#job = current_user.jobs.build(job_params)
if #job.save!
redirect_to listing_job_path(#job), notice: 'Jobs dev was successfully created.'
else
render :new
end
end
# PATCH/PUT /jobs/1
# def update
# if #job.update(job_params)
# redirect_to #job, notice: 'Jobs dev was successfully updated.'
# else
# render :edit
# end
# end
def update
#respond_to do |format|
if #job.update(job_params)
#format.html { redirect_to #job, notice: 'Post was successfully updated.' }
#format.json { render :show, status: :ok, location: #job }
flash[:notice] = 'Saved...'
else
#format.html { render :edit }
#format.json { render json: #job.errors, status: :unprocessable_entity }
flash[:alert] = "Something went wrong..."
end
redirect_back(fallback_location: request.referer)
#end
end
# DELETE /jobs/1
def destroy
#job.destroy
redirect_to jobs_url, notice: 'Job was successfully destroyed.'
end
def delete
end
def featured
##job = current_user.job
end
def premium
##job = current_user.job
end
# DELETE job images
def delete_image_attachment
#image = ActiveStorage::Attachment.find(params[:image_id])
#image.purge
redirect_back(fallback_location: request.referer)
end
private
# Use callbacks to share common setup or constraints between actions.
def set_job
#job = Job.find(params[:id])
end
def is_authorised
redirect_to root_path, alert: "You don't have permission..." unless current_user.id == #job.user_id
end
# Only allow a trusted parameter "white list" through.
def job_params
params.require(:job).permit(:job_category, :job_type, :job_title, :job_description, :recurrence,
:featured, :premium, :budget, images: []
)
end
end
** My Models **
[![class JobCategory < ApplicationRecord
#attr_accessible :job_category
#validates :job_category, :presence => true
has_many :job_types
has_many :jobs
end
class JobType < ApplicationRecord
#attr_accessible :job_type
#validates :job_type, :presence => true
belongs_to :job_category
has_many :jobs
end
class Job < ApplicationRecord
belongs_to :user
#belongs_to :job_category
#belongs_to :job_type
has_many_attached :images
validates :job_category, presence: true
validates :job_type, presence: true
validates :recurrence, presence: true
#validates :job_title, presence: true
#validates :job_description, presence: true
end][1]][1]
** The Error **
Your model is probably not named Job_category but JobCategory. Just change your model name in your view from
<%= f.collection_select :job_category_id, Job_category.order(:job_category),
:id, :job_category, include_blank: true %>
to
<%= f.collection_select :job_category_id, JobCategory.order(:job_category),
:id, :job_category, include_blank: true %>

Nested attributes in Ruby on Rails not saving

I'll preface this by saying I've looked at the following answers and still have not hit a solution that works (however, given the possibility I might have overlooked something, I'm including them for reference):
Ruby on Rails - Not saving User - Nested Attributes and Nested Forms
Nested Attributes in ruby on rails
Ruby on Rails nested attributes not saving into database?
Nested attributes not saving in database? Does not display values - Ruby on Rails
Description of problem: I have a form Block with a nested form for Cue. The form renders correctly and the Block saves correctly, but the Cue does not appear in the Cue table, i.e. the Cue isn't saving when the Block is submitted. I'm using Rails 4.2.5.1. I also don't get any errors on submit, making this a bit difficult to diagnose.
Code:
_form.html.erb - block
<%= form_for(#block) do |f| %>
<% if #block.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#block.errors.count, "error") %> prohibited this block from being saved:</h2>
<ul>
<% #block.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field hidden">
<%= f.label :block_code, class: "hidden" %><br>
<%= f.text_field :block_code, class: "form-control hidden" %>
</div>
<div class="field">
<%= f.label :block_duration %><br>
<div class="input-group">
<%= f.number_field :block_duration, class: 'text_field form-control', :step => 'any' %>
<div class="input-group-addon">seconds</div>
</div>
</div>
<div class="field">
<label>Does this block have a cue associated with it?</label>
<input type="radio" name="cue" value="cueYes" data-type="cueYes" data-radio="cue"> Yes
<input type="radio" name="cue" value="cueNo" data-type="cueNo" data-radio="cue" checked> No
<div class="field" id="cueYes">
<%= f.fields_for :cues do |ff| %>
<div class="field hidden">
<%= ff.label :cue_code, class: "hidden" %><br>
<%= ff.text_field :cue_code, class: "hidden" %>
</div>
<div class="field">
<%= ff.label "Cue Type" %><br>
<%= ff.collection_select(:cue_type_code, CueType.all, :cue_type_code, :cue_type_name, {prompt: "Select a cue type..."}, {class: "form-control"}) %>
</div>
<div class="field">
<%= ff.label "Cue Description" %><br>
<%= ff.text_area :cue_description, class: "form-control" %>
</div>
<div class="field">
<%= ff.label "Cue Method" %><br>
<%= ff.collection_select( :cue_method_code, CueMethod.all, :cue_method_code, :cue_method_name, {prompt: "Select a cue method..."}, {class: "form-control"}) %>
</div>
<% end %>
</div>
</div>
<div class="field">
<%= f.label "Location" %><br>
<%= collection_select :block, :location_code, Location.all, :location_code, :location_name, {prompt: "Select a location..."}, {class: "form-control"} %>
</div>
<div class="field">
<%= f.label "Scene" %><br>
<%= collection_select :block, :scene_code, Scene.all, :scene_code, :actAndScene, {prompt: "Select a scene..."}, {class: "form-control"} %>
</div>
<div class="field">
<%= f.label "Block Description" %><br>
<%= f.text_area :block_description, class: "form-control" %>
</div>
<div class="actions">
<%= f.submit "Create Block", class: "btn btn-primary" %>
</div>
<% end %>
blocks_controller.rb
class BlocksController < ApplicationController
before_action :set_block, only: [:show, :edit, :update, :destroy]
# GET /blocks
# GET /blocks.json
def index
#blocks = Block.all
end
# GET /blocks/1
# GET /blocks/1.json
def show
end
# GET /blocks/new
def new
#block = Block.new
# Set block code as next integer after max block code.
#block.block_code = (Block.maximum(:block_code).to_i.next).to_s(2)
end
# GET /blocks/1/edit
def edit
end
# POST /blocks
# POST /blocks.json
def create
#block = Block.new(block_params)
respond_to do |format|
if #block.save
format.html { redirect_to #block, notice: 'Block was successfully created.' }
format.json { render :show, status: :created, location: #block }
else
format.html { render :new }
format.json { render json: #block.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /blocks/1
# PATCH/PUT /blocks/1.json
def update
respond_to do |format|
if #block.update(block_params)
format.html { redirect_to #block, notice: 'Block was successfully updated.' }
format.json { render :show, status: :ok, location: #block }
else
format.html { render :edit }
format.json { render json: #block.errors, status: :unprocessable_entity }
end
end
end
# DELETE /blocks/1
# DELETE /blocks/1.json
def destroy
#block.destroy
respond_to do |format|
format.html { redirect_to blocks_url, notice: 'Block was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_block
#block = Block.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def block_params
params.require(:block).permit(:block_code, :block_duration, :cue_code, :location_code, :scene_code, :block_description, :cues_attributes => [:cue_code, :cue_type_code, :cue_description, :cue_method_name])
end
end
block.rb
class Block < ActiveRecord::Base
has_one :cue, -> { where processed: true }
accepts_nested_attributes_for :cue, allow_destroy: true
end
cue.rb
class Cue < ActiveRecord::Base
belongs_to :block
end
cues_controller.rb
class CuesController < ApplicationController
before_action :set_cue, only: [:show, :edit, :update, :destroy]
# GET /cues
# GET /cues.json
def index
#cues = Cue.all
end
# GET /cues/1
# GET /cues/1.json
def show
end
# GET /cues/new
def new
#cue = Cue.new
# Set cue code as next integer after max cue code.
#cue.cue_code = (Cue.maximum(:cue_code).to_i.next).to_s(2)
end
# GET /cues/1/edit
def edit
end
# POST /cues
# POST /cues.json
def create
#cue = Cue.new(cue_params)
respond_to do |format|
if #cue.save
format.html { redirect_to #cue, notice: 'Cue was successfully created.' }
format.json { render :show, status: :created, location: #cue }
else
format.html { render :new }
format.json { render json: #cue.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /cues/1
# PATCH/PUT /cues/1.json
def update
respond_to do |format|
if #cue.update(cue_params)
format.html { redirect_to #cue, notice: 'Cue was successfully updated.' }
format.json { render :show, status: :ok, location: #cue }
else
format.html { render :edit }
format.json { render json: #cue.errors, status: :unprocessable_entity }
end
end
end
# DELETE /cues/1
# DELETE /cues/1.json
def destroy
#cue.destroy
respond_to do |format|
format.html { redirect_to cues_url, notice: 'Cue was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cue
#cue = Cue.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def cue_params
params.require(:cue).permit(:cue_code, :cue_type_code, :cue_description, :cue_method_code)
end
end
If anything else is needed, please let me know! (Also sorry if the formatting isn't great).
Any help is much appreciated!! Thanks!!
UPDATE 1
I'm currently getting the error undefined method 'encoding' for 7:Fixnum on the line if #block.save in blocks_controller.rb (above). I have changed the following things based on the answer given by IngoAlbers (below) and the answer found here.
I've changed the following things:
blocks_controller.rb
def block_params
params.require(:block).permit(:block_code, :block_duration, :cue_code, :location_code, :scene_code, :block_description, :cue_attributes => [:id, :cue_code, :cue_type_code, :cue_description, :cue_method_code])
end
_form.html.erb - blocks
<%= f.fields_for :cue, #block.build_cue do |ff| %>
block.rb
class Block < ActiveRecord::Base
has_one :cue
accepts_nested_attributes_for :cue, allow_destroy: true
end
Thanks so much for the help so far! I think I'm really close!
UPDATE 2
So I've added block_id as an attribute to Cue and run the following two migrations:
class AddBlockIdToCues < ActiveRecord::Migration
def self.up
add_column :cues, :block_id, :binary
end
def self.down
remove_column :cues, :block_id
end
end
class AddBelongsToToCues < ActiveRecord::Migration
def change
add_reference :cues, :blocks, index: true
add_foreign_key :cues, :blocks
end
end
I'm still getting the error undefined method 'encoding' for 7:Fixnum on the line if #block.save in the blocks_controller.rb.
The problem should be in your fields_for. It should probably be:
<%= f.fields_for :cue do |ff| %>
Not cues since it is only one. Then you need to build the cue. This can be done either in controller or in the view directly, for example like this:
<%= f.fields_for :cue, #block.build_cue do |ff| %>
In your block params you then also need to change it to cue_attributes, and also allow id.
def block_params
params.require(:block).permit(:block_code, :block_duration, :cue_code, :location_code, :scene_code, :block_description, :cue_attributes => [:id, :cue_code, :cue_type_code, :cue_description, :cue_method_name])
end
You can also read a lot more information here:
http://guides.rubyonrails.org/form_helpers.html#nested-forms
Regarding your second Update:
Your first migration adds a column block_id of type binary. It should definitely be integer instead. That said, you don't even need the first migration at all, because your second migration will handle all of it correctly, if you change blocks to block in add_reference. It should look like this:
class AddBelongsToToCues < ActiveRecord::Migration
def change
add_reference :cues, :block, index: true
add_foreign_key :cues, :blocks
end
end
The add_reference needs to add a reference to one block not multiple. This will then create the right column for you.
See also: http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_reference

Rails 4 - nested attributes with Cocoon gem

I'm trying to make an app with Rails 4.
I'm using Cocoon gem for nested forms with simple form.
I have a qualifications model, nested in a profile model. The associations are:
Qualifications
belongs_to :profile
Profile
has_many :qualifications
accepts_nested_attributes_for :qualifications, reject_if: :all_blank, allow_destroy: true
In my profile form, I incorporate the qualifications attributes with:
<%= f.simple_fields_for :qualifications do |f| %>
<%= render 'qualifications/qualification_fields', f: f %>
<% end %>
In my Qualifications form attributes, I have:
<div class="nested-fields">
<div class="container-fluid">
<div class="form-inputs">
<div class="row">
<div class="col-md-6">
<%= f.input :title, :label => "Your award" %>
</div>
<div class="col-md-6">
</div>
</div>
<div class="row">
<div class="col-md-8">
<%= f.input :pending, :label => "Are you currently studying toward this qualification?" %>
</div>
</div>
<div class="row">
<div class="col-md-4">
<%= f.input :level, collection: [ "Bachelor's degree", "Master's degree", "Ph.D", "Post Doctoral award"] %>
</div>
<div class="col-md-4">
<%= f.input :year_earned, :label => "When did you graduate?", collection: (Date.today.year - 50)..(Date.today.year + 5) %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= link_to_remove_association 'Remove this qualification', f %>
</div>
</div>
</div>
</div>
</div>
In my profiles controller I have:
def new
#profile = Profile.new
#profile.qualifications_build
#profile.build_vision
#profile.build_personality
#profile.addresses_build
authorize #profile
end
# GET /profiles/1/edit
def edit
#profile.build_personality unless #profile.personality
#profile.qualifications_build unless #profile.qualifications
#profile.build_vision unless #profile.vision
#profile.addresses_build unless #profile.addresses
end
# POST /profiles
# POST /profiles.json
def create
#profile = Profile.new(profile_params)
authorize #profile
respond_to do |format|
if #profile.save
format.html { redirect_to #profile }
format.json { render :show, status: :created, location: #profile }
else
format.html { render :new }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /profiles/1
# PATCH/PUT /profiles/1.json
def update
# successful = #profile.update(profile_params)
# Rails.logger.info "xxxxxxxxxxxxx"
# Rails.logger.info successful.inspect
# user=#profile.user
# user.update.avatar
respond_to do |format|
if #profile.update(profile_params)
format.html { redirect_to #profile }
format.json { render :show, status: :ok, location: #profile }
else
format.html { render :edit }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
# DELETE /profiles/1
# DELETE /profiles/1.json
def destroy
#profile.destroy
respond_to do |format|
format.html { redirect_to profiles_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_profile
#profile = Profile.find(params[:id])
authorize #profile
end
# Never trust parameters from the scary internet, only allow the white list through.
def profile_params
params.require(:profile).permit( :title, :hero, :overview, :research_interest, :occupation, :external_profile,
:working_languages, :tag_list,
industry_ids: [],
user_attributes: [:avatar],
personality_attributes: [:average_day, :fantasy_project, :preferred_style],
vision_attributes: [ :long_term, :immediate_challenge],
qualifications_attributes: [ :level, :title, :year_earned, :pending, :institution, :_destroy],
addresses_attributes: [:id, :unit, :building, :street_number, :street, :city, :region, :zip, :country, :time_zone, :latitude, :longitude, :_destroy],
industries_attributes: [:id, :sector, :icon] )
end
end
My problems are:
when I save all of this and try it, each time I update the profile, it creates a new entry for the qualifications, so the list of qualifications displayed duplicates on every update (even when no update is made to the fields).
When I update the profile form and click remove qualification, it does not get removed from the array. I can delete them in the console, but not using the form.
I'm worried that if I remove
#profile.qualifications_build unless #profile.qualifications
from the edit action in the profile controller, I won't be able to update those attributes.
Also, it doesn't make sense to me that removing that would solve the problem with removing qualifications. Do I need to add something to the remove qualification link to force it to remove the entry?
I think you just forgot to add :id in the allowed parameters for qualifications, in your profile_params:
qualifications_attributes: [ :id, :level, :title, :year_earned, :pending, :institution, :_destroy]
Without an ID to match, any qualification will be seen as a new one.

Rails 4 - Associations - nested attributes - unpermitted parameter

I am trying to make an app in Rails 4. I'm having an awful time of getting basic relationships set up.
I have models for user, profile, vision, personality & qualifications.
The associations are:
User.rb
Profile.rb
belongs_to :user
has_one :personality
accepts_nested_attributes_for :personality
has_many :qualifications
accepts_nested_attributes_for :qualifications, reject_if: :all_blank, allow_destroy: true
has_one :vision
accepts_nested_attributes_for :vision, reject_if: :all_blank, allow_destroy: true
Vision.rb
belongs_to :profile
Personality.rb
belongs_to :profile
Qualifications.rb
belongs_to :profile
The controllers are:
User
class UsersController < ApplicationController
before_action :set_user, only: [:index, :show, :edit, :update, :finish_signup, :destroy]
def index
# if params[:approved] == "false"
# #users = User.find_all_by_approved(false)
# else
#users = User.all
# end
end
# GET /users/:id.:format
def show
# authorize! :read, #user
end
# GET /users/:id/edit
def edit
# authorize! :update, #user
end
# PATCH/PUT /users/:id.:format
def update
# authorize! :update, #user
respond_to do |format|
if #user.update(user_params)
sign_in(#user == current_user ? #user : current_user, :bypass => true)
format.html { redirect_to #user, notice: 'Your profile 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
# GET/PATCH /users/:id/finish_signup
def finish_signup
# authorize! :update, #user
if request.patch? && params[:user] #&& params[:user][:email]
if #user.update(user_params)
#user.skip_reconfirmation!
sign_in(#user, :bypass => true)
redirect_to root_path, notice: 'Your profile was successfully updated.'
# redirect_to [#user, #user.profile || #user.build_profile]
# sign_in_and_redirect(#user, :bypass => true)
else
#show_errors = true
end
end
end
# DELETE /users/:id.:format
def destroy
# authorize! :delete, #user
#user.destroy
respond_to do |format|
format.html { redirect_to root_url }
format.json { head :no_content }
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
# params.require(:user).permit(policy(#user).permitted_attributes)
accessible = [ :first_name, :last_name, :email, :avatar ] # extend with your own params
accessible << [ :password, :password_confirmation ] unless params[:user][:password].blank?
# accessible << [:approved] if user.admin
params.require(:user).permit(accessible)
end
end
Profile
class ProfilesController < ApplicationController
before_action :set_profile, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
after_action :verify_authorized
# GET /profiles
# GET /profiles.json
def index
#profiles = Profile.all
authorize #profiles
end
# GET /profiles/1
# GET /profiles/1.json
def show
end
# GET /profiles/new
def new
#profile = Profile.new
#profile.qualifications.build
#profile.build.vision
#profile.build.personality
#profile.addresses.build
authorize #profile
end
# GET /profiles/1/edit
def edit
end
# POST /profiles
# POST /profiles.json
def create
#profile = Profile.new(profile_params)
authorize #profile
respond_to do |format|
if #profile.save
format.html { redirect_to #profile }
format.json { render :show, status: :created, location: #profile }
else
format.html { render :new }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /profiles/1
# PATCH/PUT /profiles/1.json
def update
# successful = #profile.update(profile_params)
# Rails.logger.info "xxxxxxxxxxxxx"
# Rails.logger.info successful.inspect
# user=#profile.user
# user.update.avatar
respond_to do |format|
if #profile.update(profile_params)
format.html { redirect_to #profile }
format.json { render :show, status: :ok, location: #profile }
else
format.html { render :edit }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
# DELETE /profiles/1
# DELETE /profiles/1.json
def destroy
#profile.destroy
respond_to do |format|
format.html { redirect_to profiles_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_profile
#profile = Profile.find(params[:id])
authorize #profile
end
# Never trust parameters from the scary internet, only allow the white list through.
def profile_params
params.require(:profile).permit(:user_id, :title, :hero, :overview, :research_interest, :occupation, :external_profile,
:working_languages, :tag_list,
user_attributes: [:avatar],
personality_attributes: [:average_day, :fantasy_project, :preferred_style],
vision_attributes: [:id, :profile_id, :long_term, :immediate_challenge],
qualifications_attributes: [:id, :level, :title, :year_earned, :pending, :institution, :_destroy],
addresses_attributes: [:id, :unit, :building, :street_number, :street, :city, :region, :zip, :country, :latitude, :longitude, :_destroy],
industries_attributes: [:id, :sector, :icon] )
end
end
Vision
class VisionsController < ApplicationController
before_action :set_vision, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /visions
# GET /visions.json
def index
#visions = Vision.all
authorize #visions
end
# GET /visions/1
# GET /visions/1.json
def show
end
# GET /visions/new
def new
#vision = Vision.new
authorize #vision
end
# GET /visions/1/edit
def edit
end
# POST /visions
# POST /visions.json
def create
#vision = Vision.new(vision_params)
authorize #vision
respond_to do |format|
if #vision.save
format.html { redirect_to #vision }
format.json { render :show, status: :created, location: #vision }
else
format.html { render :new }
format.json { render json: #vision.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /visions/1
# PATCH/PUT /visions/1.json
def update
respond_to do |format|
if #vision.update(vision_params)
format.html { redirect_to #vision }
format.json { render :show, status: :ok, location: #vision }
else
format.html { render :edit }
format.json { render json: #vision.errors, status: :unprocessable_entity }
end
end
end
# DELETE /visions/1
# DELETE /visions/1.json
def destroy
#vision.destroy
respond_to do |format|
format.html { redirect_to visions_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_vision
#vision = Vision.find(params[:id])
authorize #vision
end
# Never trust parameters from the scary internet, only allow the white list through.
def vision_params
params[:vision].permit(:profile_id, :long_term, :immediate_challenge)
end
end
Qualifications
class QualificationsController < ApplicationController
before_action :set_qualification, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /qualifications
# GET /qualifications.json
def index
#qualifications = Qualification.all
authorize #qualifications
end
# GET /qualifications/1
# GET /qualifications/1.json
def show
end
# GET /qualifications/new
def new
#qualification = Qualification.new
authorize #qualification
end
# GET /qualifications/1/edit
def edit
end
# POST /qualifications
# POST /qualifications.json
def create
#qualification = Qualification.new(qualification_params)
authorize #qualification
respond_to do |format|
if #qualification.save
format.html { redirect_to #qualification }
format.json { render :show, status: :created, location: #qualification }
else
format.html { render :new }
format.json { render json: #qualification.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /qualifications/1
# PATCH/PUT /qualifications/1.json
def update
respond_to do |format|
if #qualification.update(qualification_params)
format.html { redirect_to #qualification }
format.json { render :show, status: :ok, location: #qualification }
else
format.html { render :edit }
format.json { render json: #qualification.errors, status: :unprocessable_entity }
end
end
end
# DELETE /qualifications/1
# DELETE /qualifications/1.json
def destroy
#qualification.destroy
respond_to do |format|
format.html { redirect_to qualifications_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_qualification
#qualification = Qualification.find(params[:id])
authorize #qualification
end
# Never trust parameters from the scary internet, only allow the white list through.
def qualification_params
params[:qualification].permit(:profile_id, :level, :title, :year_earned, :pending, :institution)
end
end
Personality
class PersonalitiesController < ApplicationController
before_action :set_personality, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /personalities
# GET /personalities.json
def index
#personalities = Personality.all
authorize #personalities
end
# GET /personalities/1
# GET /personalities/1.json
def show
end
# GET /personalities/new
def new
#personality = Personality.new
authorize #personality
end
# GET /personalities/1/edit
def edit
end
# POST /personalities
# POST /personalities.json
def create
#personality = Personality.new(personality_params)
authorize #personality
respond_to do |format|
if #personality.save
format.html { redirect_to #personality }
format.json { render :show, status: :created, location: #personality }
else
format.html { render :new }
format.json { render json: #personality.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /personalities/1
# PATCH/PUT /personalities/1.json
def update
respond_to do |format|
if #personality.update(personality_params)
format.html { redirect_to #personality }
format.json { render :show, status: :ok, location: #personality }
else
format.html { render :edit }
format.json { render json: #personality.errors, status: :unprocessable_entity }
end
end
end
# DELETE /personalities/1
# DELETE /personalities/1.json
def destroy
#personality.destroy
respond_to do |format|
format.html { redirect_to personalities_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_personality
#personality = Personality.find(params[:id])
authorize #personality
end
# Never trust parameters from the scary internet, only allow the white list through.
def personality_params
params[:personality].permit( :average_day, :fantasy_project, :preferred_style)
end
end
The profile form has:
<div class="container-fluid">
<div class="row">
<div class="col-xs-10 col-xs-offset-1" >
<%= simple_form_for(#profile, multipart: true) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<div class="intpol2">
About you
</div>
<div class="row">
<div class="col-md-4">
<%= f.input :title, autofocus: true %>
</div>
<div class="col-md-8">
<%= f.input :occupation, :label => "Your occupation or job title" %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= render 'users/profileimgform', f: f %>
</div>
<div class="col-md-6">
<%= f.input :hero, as: :file, :label => "Add a background image to your profile page" %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= f.input :working_languages, :label => "Select your working languages" %>
</div>
<div class="col-md-6">
<%= f.input :external_profile, :label => "Add a link to your external profile" %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= f.input :overview, :label => "Tell us about yourself", :input_html => {:rows => 10} %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= render 'industries/industry_selector', f: f %>
</div>
</div>
<div class="row">
<div class="intpol2">
Your professional qualifications
</div>
<%= f.simple_fields_for :qualifications do |f| %>
<%= render 'qualifications/qualification_fields', f: f %>
<% end %>
</div>
<div class="row">
<div class="col-md-6">
<%= link_to_add_association 'Add a qualification', f, :qualifications, partial: 'qualifications/qualification_fields' %>
</div>
</div>
<div class="row">
<div class="intpol2">
Your career
</div>
<%= render 'personalities/form', f: f %>
</div>
<div class="row">
<div class="intpol2">
Your research vision
</div>
</div>
<div class="row">
<div class="intpol2">
Your addresss
</div>
<%= f.simple_fields_for :addresses do |f| %>
<%= render 'addresses/address_fields', f: f %>
<% end %>
</div>
<div class="row">
<div class="col-md-6">
<%= link_to_add_association 'Add an address', f, :addresses, partial: 'addresses/address_fields' %>
</div>
</div>
<div class="form-actions">
<%= f.button :submit, "Submit", :class => 'formsubmit' %>
</div>
<% end %>
</div>
</div>
</div>
</div>
The nested forms are:
Vision
<div class="form-inputs">
<%= f.input :long_term, as: :text, :label => "What is your long term research vision?", :input_html => {:rows => 10} %>
<%= f.input :immediate_challenge, as: :text, :label => "What do you see as the immediate challenge to be addressed in pursuit of your long-term vision?", :input_html => {:rows => 10} %>
</div>
Qualifications
<div class="nested-fields">
<div class="container-fluid">
<div class="form-inputs">
<div class="row">
<div class="col-md-6">
<%= f.input :title, :label => "Your award" %>
</div>
<div class="col-md-6">
</div>
</div>
<div class="row">
<div class="col-md-8">
<%= f.input :pending, :label => "Are you currently studying toward this qualification?" %>
</div>
</div>
<div class="row">
<div class="col-md-4">
<%= f.input :level, collection: [ "Bachelor's degree", "Master's degree", "Ph.D", "Post Doctoral award"] %>
</div>
<div class="col-md-4">
<%= f.input :year_earned, :label => "When did you graduate?", collection: (Date.today.year - 50)..(Date.today.year) %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= link_to_remove_association 'Remove this qualification', f %>
</div>
</div>
</div>
</div>
</div>
Personality
<%= f.simple_fields_for :profile do |f| %>
<%= f.simple_fields_for :personality do |ff| %>
<div class="form-inputs">
<%= ff.input :average_day, :label => "What does your day to day work life involve?", as: :text, :input_html => {:rows => 5} %>
<%= ff.input :fantasy_project, :label => "Describe your fantasy project", as: :text, :input_html => {:rows => 5} %>
<%= ff.input :preferred_style, :label => "How do you like to work (distributed teams, on site, easy going about it)?", as: :text, :input_html => {:rows => 5} %>
</div>
<% end %>
<% end %>
The profile show page has:
<div class="intpol3">
<%= #profile.personality.try(:average_day) %>
</div>
<div class="profilesubhead">
My fantasy league research project
</div>
<div class="intpol3">
<%= #profile.personality.try(:fantasy_project) %>
</div>
<div class="profilesubhead">
Working style
</div>
<div class="intpol3">
<%= #profile.personality.try(:preferred_style) %>
</div>
<div class="profilesubhead">
My research vision
</div>
<div class="profilesubhead">
<%= #profile.vision.try(:long_term) %>
</div>
<div class="profilesubhead">
Immediate research challenge in my field
</div>
<div class="profilesubhead">
<%= #profile.vision.try(:immediate_challenge) %>
</div>
The routes are:
resources :profiles, only: [:show, :edit, :update, :destroy]
resources :qualifications
resources :personalities
resources :visions
resources :users do
resources :profiles, only: [:new, :create]
end
From the above, you can see that I have experimented with a variety of different solutions, including using cocoon gem (which I have used for the qualifications model).
Nothing works. The only attributes displaying on the profiles show page are those stored in the profiles table or the users table. None of the models that belong to profile are displaying in the profiles show. Models that have a polymorphic association with profile are displaying.
Currently, when I save and try this, the local host server shows an error called 'Unpermitted parameter: profile'. I can see for qualifications, that the entries in the form are showing in the server, but they do not appear on the profile page. For each of the rest of the nested attributes - none of them display on the profile show page. The rails console shows all of the attributes for personality (with profile id of the user whose profile page is showing are nil).
In my profiles form, I can't even display the vision form fields at all. I thought that might be because I added this:
reject_if: :all_blank, allow_destroy: true
to the accepts nested attributes for :vision in my profile model - but commenting that section out does not improve the situation.
I previously asked this question but could not find any help.
Rails - Displaying associated attributes - unpermitted parameters
I have tried each of the solutions I listed in that post (I think the site point article I attach at the end of that post is the closest thing to relevant that I've been able to find).
I'm out of ideas for things to try to check or change. Can anyone see what I have done wrong?
The server shows the following output for when I try to update the profile by adding entries to the personalities section of the profile form:
Started PATCH "/profiles/8" for ::1 at 2016-01-09 12:38:04 +1100
Processing by ProfilesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Xul2nPMbg/3MnMPoTMtEIFfVg==", "profile"=>{"title"=>"", "occupation"=>"tester", "working_languages"=>"tester", "external_profile"=>"tester", "overview"=>"tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester tester ", "qualifications_attributes"=>{"0"=>{"title"=>"dfds", "pending"=>"0", "level"=>"Master's degree", "year_earned"=>"1967", "_destroy"=>"false", "id"=>"4"}}, "profile"=>{"personality"=>{"average_day"=>"sdf", "fantasy_project"=>"", "preferred_style"=>""}}}, "industry"=>{"sector"=>"5"}, "commit"=>"Submit", "id"=>"8"}
Profile Load (0.3ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."id" = $1 LIMIT 1 [["id", 8]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 9]]
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 9]]
Unpermitted parameter: profile
(0.1ms) BEGIN
Qualification Load (0.3ms) SELECT "qualifications".* FROM "qualifications" WHERE "qualifications"."profile_id" = $1 AND "qualifications"."id" = 4 [["profile_id", 8]]
(0.1ms) COMMIT
Redirected to http://localhost:3000/profiles/8
Completed 302 Found in 12ms (ActiveRecord: 1.3ms)
TAKING MIHAILS SUGGESTION
I replace the personality form fields with:
<%= f.simple_fields_for :personality do |ff| %>
<div class="form-inputs">
<%= ff.input :average_day, :label => "What does your day to day work life involve?", as: :text, :input_html => {:rows => 5} %>
<%= ff.input :fantasy_project, :label => "Describe your fantasy project", as: :text, :input_html => {:rows => 5} %>
<%= ff.input :preferred_style, :label => "How do you like to work (distributed teams, on site, easy going about it)?", as: :text, :input_html => {:rows => 5} %>
</div>
<% end %>
When I try this, the personality form fields do not render as part of the profiles form at all
TAKING MIHAILS NEXT SUGGESTION
I replace the build personality action in the profiles controller with:
#profile.personality = Personality.new
It was previously: #profile.build.personality
When I try this, I get the same error as previously - I can't see the form fields for personality at all.
TAKING TRH'S SUGGESTION:
If i make the new action:
#profile.build_personality
I still can't see the form for personality fields. No change to the prior attempts
FURTHER UPDATE
It seems the explanation in Mihail's second suggestion is the same effect as TRH's suggestion. Currently, my profiles controller has this new action:
def new
#profile = Profile.new
#profile.qualifications_build
#profile.build_vision
#profile.build_personality
#profile.addresses_build
authorize #profile
end
It's still not working.
TAKING MIHAIL'S NEXT SUGGESTION
def new
#profile = Profile.new
#profile.qualifications_build
#profile.build_vision
#profile.build_personality unless personality
#profile.addresses_build
authorize #profile
end
I still can't see the profile form fields for personality.
SOLUTION:
def new
#profile = Profile.new
#profile.qualifications_build
#profile.build_vision
#profile.build_personality unless #profile.personality
#profile.addresses_build
authorize #profile
end
# GET /profiles/1/edit
def edit
#profile.build_personality unless #profile.personality
end
The problem is in the personality fields partial. If you will look closer on the attributes submitted to server on update, you will see that they are wrong.
"profile"=>{"profile"=>{"personality"=>{"average_day"=>"sdf"}}
So, to fix this you need to check this partial and leave only nested fields block in it.
<%= f.simple_fields_for :personality do |ff| %>
<div class="form-inputs">
<%= ff.input :average_day, :label => "What does your day to day work life involve?", as: :text, :input_html => {:rows => 5} %>
<%= ff.input :fantasy_project, :label => "Describe your fantasy project", as: :text, :input_html => {:rows => 5} %>
<%= ff.input :preferred_style, :label => "How do you like to work (distributed teams, on site, easy going about it)?", as: :text, :input_html => {:rows => 5} %>
</div>
<% end %>

Resources