I have set up polymorphic resource using accepts_nested_attributes_for but for some reason whenever I try to update, instead of just updating the current record, it just create a new one instead. Can anyone tell me what the problem is? Thanks.
vendors_controller.rb
class VendorsController < ApplicationController
before_action :authenticate_user! #check if user logged in
before_action :set_vendor, only: [:show, :edit, :update, :destroy]
def index
#vendors = current_company.vendors
end
def new
#vendor = current_company.vendors.build
#vendor.addresses.build
end
def create
#vendor = current_company.vendors.build(vendor_params)
if #vendor.save
flash[:notice] = 'New Vendor Added'
redirect_to vendors_url
else
flash[:error] = 'Could not save vendor information. Please try again.'
render 'new'
end
end
def show
end
def edit
##vendor = Vendor.find(params[:id])
##vendor.addresses.find_or_initialize_by(addressable_id: #vendor.id, addressable_type: 'Vendor')
end
def update
##vendor = Vendor.find(params[:id])
if #vendor.update(vendor_params)
flash[:notice] = 'Vendor Updated'
redirect_to vendors_path
else
flash[:error] = 'Could not save vendor information. Please try again.'
render 'edit'
end
end
def destroy
#Vendor.find(params[:id]).destroy
#vendor.destroy
flash[:notice] = "Asset deleted"
redirect_to vendors_url
end
private
def vendor_params
params.require(:vendor).permit(:name, :vendorID, :contact, :email, :phone, :image, :remove_image, addresses_attributes: [:street_1, :street_2, :city, :state, :zip] )
end
def set_vendor
#vendor = Vendor.find(params[:id])
end
def current_company
current_user.company
end
end
_form.html.erb
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="card card-block" style="background-color:#f5f5f5">
<%= form_for #vendor do |f| %>
<div class="form-group">
<%= f.label :name, 'Vendor Name' %><br />
<%= f.text_field :name, autofocus: true, required: true, class:'form-control' %>
</div>
<div class="form-group">
<%= f.label :vendorID, 'Vendor ID/Number' %><br />
<%= f.text_field :vendorID, class:'form-control' %>
</div>
<div class="form-group">
<%= f.label :contact, 'Main Contact Person' %><br />
<%= f.text_field :contact, class:'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %><br />
<%= f.email_field :email, class:'form-control' %>
</div>
<div class="form-group">
<%= f.label :phone %><br />
<%= f.phone_field :phone, class:'form-control' %>
</div>
<%= f.fields_for :addresses do |a| %>
<div class="form-group">
<%= a.label :street_1, 'Street' %><br />
<%= a.text_field :street_1, class:'form-control' %>
</div>
<div class="form-group">
<%= a.label :street_2, 'Street 2 (Optional)' %><br />
<%= a.text_field :street_2, class:'form-control' %>
</div>
<div class="form-group">
<%= a.label :city, 'City' %><br />
<%= a.text_field :city, class:'form-control' %>
</div>
<div class="form-group">
<%= a.label :state, 'State' %><br />
<%= a.text_field :state, class:'form-control' %>
</div>
<div class="form-group">
<%= a.label :zip, 'Zip Code' %><br />
<%= a.text_field :zip, class:'form-control' %>
</div>
<% end %>
<div class="actions form-group"><br>
<%= f.submit 'Save Vendor', class: 'btn btn-primary' %>
<%= link_to 'Cancel', :back, class: 'btn btn-default' %>
</div>
<% end %>
</div>
vendor.rb
class Vendor < ActiveRecord::Base
belongs_to :company
has_many :asset
has_many :addresses, as: :addressable, dependent: :destroy
accepts_nested_attributes_for :addresses, reject_if: RejectDeeplyNested.blank?
end
address.rb
class Address < ActiveRecord::Base
belongs_to :addressable, polymorphic: true
end
you need to change your permitted parameters like this
params.require(:vendor).permit(:name, :vendorID, :contact, :email, :phone, :image, :remove_image, addresses_attributes: [:street_1, :street_2, :city, :state, :zip, :id] )
You need to add optional: true to your relationship:
class Address < ApplicationRecord
belongs_to :addressable, polymorphic: true, optional: true
end
Forgot to mention, that optional is available only on Rails > 5
Related
validates_confirmation_of :password does not work when I submitted my form. Even if the password confirmation is not the same, the user is signed up.
I wrote the same thing that the guide. during my research , I did not found anything that explain that.
Do you know what is happening and how can I solve it?
Here is my code:
My view:
<%= form_for User.new do |f| %>
<div class="row">
<div class="col-md-6">
<%= f.label :Prénom %> :
<%= f.text_field :first_name, class: "form-control" %><br />
</div>
<div class="col-md-6">
<%= f.label :Nom %> :
<%= f.text_field :last_name, class: "form-control" %><br />
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= f.label :Pseudo %> :
<%= f.text_field :user_name, class: "form-control"%><br />
</div>
<div class="col-md-6">
<%= f.label :Email %> :
<%= f.email_field :email, class: "form-control" %><br />
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= f.label :Mot_de_passe %> :
<%= f.password_field :password, class: "form-control" %><br />
</div>
<div class="col-md-6">
<%= f.label :Confirmation_mot_de_passe %> :
<%= f.password_field :password_confirmation, class: "form-control" %><br />
</div>
</div>
<%= f.label :Club_favori %> :
<%=f.select(:club) do%>
<%= options_from_collection_for_select(Club.all,:id ,:name) %>
<% end %>
<br>
<%= f.submit class: "btn btn-primary" %>
<% end %>
My model:
class User < ActiveRecord::Base
has_merit
has_secure_password
has_many :comments
validates_length_of :password, minimum: 5, too_short: 'please enter at least 5 characters', on: :create
validates_presence_of :user_name, :message => 'Vous devez remplir tout les champs.', on: :create
validates_uniqueness_of :user_name, :case_sensitive => false, :message => "Ce pseudo n'est pas disponible.", on: :create
validates_confirmation_of :password, on: :create
end
My controller:
class UsersController < ApplicationController
def create
#user = User.new(user_params)
if #user.save
#user.add_badge(1)
session[:user_id] = #user.id
redirect_to '/feed'
else
redirect_to '/signup', flash: {error_message: #user.errors}
end
end
private
def user_params
params.require(:user).permit( :user_name, :first_name, :last_name, :email, :password, :sash, :club)
end
def new
#user = User.new
#clubs =Club.all
end
end
Thank you in advance for your help.
You override your current #user when you enter your form.
Just change:
<%= form_for User.new do |f| %>
to
<%= form_for #user do |f| %>
I have to insert some values into another table during sign up. This is what I have tried so far.
The two tables are employees and organizations. This is the form that I am currently using:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), :html => {:id => "example-advanced-form"}) do |f| %>
<h3>Account</h3>
<fieldset>
<legend>Account Information</legend>
<%= f.label :email %><br>
<%= f.text_field :email, :id => "email-2", :class => "required email" %>
<%= f.label :password %><br>
<%= f.password_field :password, :id => "password-2", :class => "required" %>
<%= f.label :password_confirmation %><br>
<%= f.password_field :password_confirmation, :name => "confirm", :id => "confirm-2", :class => "required" %>
<p>(*) Mandatory</p>
</fieldset>
<h3>Profile</h3>
<fieldset>
<legend>Profile Information</legend>
<div class="container-fluid">
<div class="row">
<div class="col-lg-6">
<%= f.label :first_name %><br>
<%= f.text_field :first_name, :id => "name-2", :class => "required" %>
<%= f.label :middle_name %><br>
<%= f.text_field :middle_name, :id => "surname-2", :class => "required" %>
<%= f.label :last_name %><br>
<%= f.text_field :last_name, :id => "surname-2", :class => "required" %>
<label>Designation</label><br>
<select class="required">
<option value="Developer">Developer</option>
<option value="Tester">Tester</option>
<option value="Manager">Manager</option>
<option value="Other">Other</option>
</select>
<br>
<%= f.fields_for :organisation do |o| %>
<%= o.label :org_name %><br>
<%= o.text_field :org_name, :id => "name-2", :class => "required" %>
<label>organisation Business Type</label><br>
<select class="required">
<option value="Business">Business</option>
<option value="Finance">Finance</option>
<option value="IT">IT</option>
<option value="Other">Other</option>
</select><br>
</div>
<div class="col-lg-6">
<label>Number Of Employees</label><br>
<select class="required">
<option value="0-10">0-10</option>
<option value="10-50">10-50</option>
<option value="50-100">50-100</option>
<option value="100-500">100-500</option>
<option value="500-1000">500-1000</option>
<option value="1000 above">1000 above</option>
</select><br>
<%= o.label :address %><br>
<%= o.text_field :address, :id => "address-2", :class => "required" %>
<%= o.label :city %><br>
<%= o.text_field :city, :class => "required" %>
<%= o.label :state %><br>
<%= o.text_field :state, :class => "required" %>
<%= o.label :country %><br>
<%= o.text_field :country, :class => "required" %>
<%= o.label :email_id %><br>
<%= o.text_field :email_id, :id => "email-2", :class => "required email" %>
<% end %>
</div>
</div>
</div>
</fieldset>
<h3>Finish</h3>
<fieldset>
<legend>Terms and Conditions</legend>
<p>We have sent you a mail for Activation of your Account. Kindly Activate your through the mail. If you haven't received any mail, please click </p>
<%= link_to "here" %>
</fieldset>
<% end %>
The form items within below block
<%= f.fields_for :organisation do |o| %>
<% end %>
are not visible in the browser. And also the values are not stored in the database.
Here are the models and view controllers.
class EmployeesController < ApplicationController
before_action :authenticate_employee!
def index
#employees = Employee.all
end
def new
#employee = Employee.new
#employee.build_organisation
end
def edit
#employee = Employee.find(params[:id])
end
def create
#employee = Employee.new(employee_params)
if #employee.save
flash[:notice] = "Employee was successfully created"
redirect_to employees_path
else
flash[:notice] = "Employee was not created"
end
end
def update
#employee = Employee.find(params[:id])
if #employee.update(employee_params)
flash[:notice] = "Employee was successfully updated"
redirect_to employees_path
else
render 'new'
end
end
def destroy
#employee = Employee.find(params[:id])
#employee.destroy
redirect_to employees_path
end
private
def employee_params
params.require(:employee).permit(:employee_id, :org_id, :role_id, :first_name, :last_name, :middle_name, :dob, :gender, :email_id, :blood_group, :join_date, :left_date, :left_reason, :referred_by, :job_code, :department_code, :encrypted_password, :is_admin, :is_activated, :remarks, :status, :created_by, :updated_by,organisation_attributes: [:org_name,:country,:state,:city,:address,:email_id])
end
end
class OrganisationsController < ApplicationController
def index
#organisations = Organisation.all
end
def show
#org = Organisation.find(params[:id])
#clients = Client.where(org_id: #org.org_id)
end
end
class Employee < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :tasks
belongs_to :organisation
belongs_to :role
accepts_nested_attributes_for :organisation
validates :first_name, presence: true, length: { minimum: 5 }
validates :last_name, presence: true, length: { minimum: 5 }
end
class Organisation < ApplicationRecord
has_many :clients
has_many :employees
end
I have a user which is a nested resource of account, and I'm trying to create the account and the user in 1 form. The account is saving correctly, however no user record is being written.
user.rb:
class User < ApplicationRecord
belongs_to :account
validates :email, presence: true
end
account.rb:
class Account < ApplicationRecord
has_many :users, :dependent => :destroy
accepts_nested_attributes_for :users
end
accounts_controller.rb:
class AccountsController < ApplicationController
def new
#account = Account.new
#user = #account.users.build
end
def create
#account = Account.new(account_params)
#account.secret = SecureRandom.uuid
if #account.save
flash[:success] = "You've successfully created your account, now it's time to create your first team."
redirect_to dashboard_path
else
flash[:danger] = "There was a problem creating your account"
redirect_to signup_path
end
end
private
def account_params
params.require(:account).permit(:name, user_attributes: [:first_name, :last_name, :email, :password, :password_confirmation, :secret])
end
end
accounts/new.html.erb:
<h1>Signup</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#account) do |form| %>
<%= form.label "Account name" %>
<%= form.text_field :name, class: "form-control" %>
<%= form.fields_for :user do | f| %>
<%= f.label :first_name %>
<%= f.text_field :first_name, class: "form-control" %>
<%= f.label :last_name %>
<%= f.text_field :last_name, class: "form-control" %>
<%= f.label :email %>
<%= f.text_field :email, class: "form-control" %>
<%= f.label :password %>
<%= f.password_field :password, class: "form-control" %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: "form-control" %>
<% end %>
<%= form.submit "Signup", class: "btn btn-primary" %>
<% end %>
</div>
</div>
When I submit the the form and check my logs, I'm seeing:
Processing by AccountsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"p5+CRICRp3ZilIg1NtehEQG7Gh2amnFFUD5NawtqkICJ4uRDvvJxf2WTbd7+rnfG9zdblT1QWgfJ62NNxcc2RA==", "account"=>{"name"=>"Streame", "user"=>{"first_name"=>"Jeremy", "last_name"=>"Kirkham", "email"=>"jeremy#streame.com.au", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}, "commit"=>"Signup"}
Unpermitted parameter: user
The answer was quite simple in the end - I needed to change the form from
<%= form.fields_for :user do | f| %>
to
<%= form.fields_for :users do | f| %>
(note user -> users), and the controller from
params.require(:account).permit(:name, user_attributes:
to
params.require(:account).permit(:name, users_attributes:
(again note user -> users).
Basically it came down to pluralisation!
So this may be somewhat related to my question that I asked earlier, so here is a link to it, just in case.
So, currently I'm getting the error undefined method 'location' for #<Block:0x6503478>.
I've already gotten the has_one relation for cue working, but what seems to be the problem is the has_many relations with block_block and block_character.
The parameters being passed are:
{"utf8"=>"✓",
"authenticity_token"=>"blahblahblah",
"block"=>{"block_code"=>"1",
"block_duration"=>"",
"cue"=>"no",
"cue_attributes"=>{"cue_code"=>"",
"cue_type_code"=>"",
"cue_description"=>"",
"cue_method_code"=>""},
"location_code"=>"1",
"scene_code"=>"1",
"block_description"=>"",
"block_block"=>{"block_block_code"=>"",
"primary_block_code"=>"",
"secondary_block_code"=>"",
"block_block_start"=>""},
"block_character"=>{"block_character_code"=>"",
"character_code"=>"",
"block_code"=>"",
"character_action"=>"",
"character_motivation"=>""}},
"blockblock"=>{"block"=>"no"},
"blockblockdirect"=>{"blockdirect"=>"before"},
"blockchar"=>{"character"=>"no"},
"commit"=>"Create Block"}
Here is my form for block (views/block/_form.html.erb):
<%= 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 "cue", "Does this block have a cue associated with it?" %>
<!-- Add whether it is specific/generic cue -->
<%= radio_button_tag "block[cue]", "yes", false %> Yes
<%= radio_button_tag "block[cue]", "no", true %> No
<div class="field" id="cue_fields" style="display:none;">
<%= f.fields_for :cue, #block.build_cue 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", required: true} %>
</div>
<div class="field">
<%= f.label "Scene" %><br>
<%= f.collection_select :scene_code, Scene.all, :scene_code, :actAndScene, {prompt: "Select a scene..."}, {class: "form-control", required: true} %>
</div>
<div class="field">
<%= f.label "Block Description" %><br>
<%= f.text_area :block_description, class: "form-control" %>
</div>
<!-- This needs work -->
<div class="field">
<%= label "blockblock", "Is this block associated with any other blocks?" %>
<%= radio_button_tag "blockblock[block]", "yes", false %> Yes
<%= radio_button_tag "blockblock[block]", "no", true %> No
<div class="field" id="blockblock_fields" style="display:none;">
<ol>
<li>
<%= label "blockdirect", "Does this block come directly before or after another block?" %>
<%= radio_button_tag "blockblockdirect[blockdirect]", "before", true %> Before
<%= radio_button_tag "blockblockdirect[blockdirect]", "after", false %> After
<%= f.fields_for :block_block do |gg| %>
<div class="field hidden">
<%= gg.label :block_block_code, class: 'hidden' %><br>
<%= gg.text_field :block_block_code, class: 'hidden' %>
</div>
<div class="field" id="blockblock_after_fields" style="display:none;">
<%= gg.label "Primary Block Code" %><br>
<%= gg.text_field :primary_block_code, class: 'form-control' %>
</div>
<div class="field" id="blockblock_before_fields">
<%= gg.label "Secondary Block Code" %><br>
<%= gg.text_field :secondary_block_code, class: 'form-control' %>
</div>
<div class="field">
<%= gg.label "Block Start" %><br>
<p><i>This field indicates the amount of time after the first block starts that the second block should begin, i.e. if you type "1" here, then the second block will start 1 second after the first block starts</i></p>
<div class="input-group">
<%= gg.number_field :block_block_start, class: 'text_field form-control', :step => 'any' %>
<div class="input-group-addon">seconds</div>
</div>
</div>
<% end %>
</li>
</ol>
</div>
</div>
<!-- This needs work -->
<div class="field">
<%= label "character", "Are any characters associated with this block?" %>
<%= radio_button_tag "blockchar[character]", "yes", false %> Yes
<%= radio_button_tag "blockchar[character]", "no", true %> No
<div class="field" id="character_fields" style="display:none;">
<ol>
<%= f.fields_for :block_character do |hh| %>
<li>
<div class="field hidden">
<%= hh.label :block_character_code, class: 'hidden' %><br>
<%= hh.text_field :block_character_code, class: 'hidden' %>
</div>
<div class="field">
<%= hh.label "Character" %><br>
<%= hh.collection_select :character_code, Character.all, :character_code, :character_name, {prompt: "Select a character..."}, {class: "form-control"} %>
</div>
<div class="field hidden">
<%= hh.label :block_code, class: 'hidden' %><br>
<%= hh.text_field :block_code, class: 'hidden' %>
</div>
<div class="field">
<%= hh.label :character_action %><br>
<%= hh.text_field :character_action, class: 'form-control' %>
</div>
<div class="field">
<%= hh.label :character_motivation %><br>
<%= hh.text_area :character_motivation, class: 'form-control' %>
</div>
</li>
<% end %>
</ol>
</div>
</div>
<div class="actions">
<%= f.submit "Create Block", class: "btn btn-primary" %>
</div>
<% end %>
Additionally, here are the models associated with block, block_character, and block_block, respectively:
class Block < ActiveRecord::Base
validates_presence_of :location
validates_presence_of :scene
has_one :cue
has_many :block_blocks
has_many :block_characters
accepts_nested_attributes_for :cue, allow_destroy: true
accepts_nested_attributes_for :block_blocks, allow_destroy: true
accepts_nested_attributes_for :block_characters, allow_destroy: true
attr_accessor :block_blocks
attr_accessor :block_characters
end
class BlockBlock < ActiveRecord::Base
belongs_to :block
end
class BlockCharacter < ActiveRecord::Base
belongs_to :block
end
Here is the controller for block:
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, :cue_attributes => [:id, :cue_code, :cue_type_code, :cue_description, :cue_method_code], :block_block_attributes => [:id, :block_block_code, :primary_block_code, :secondary_block_code, :block_block_start], :block_character_attributes => [:id, :block_character_code, :character_code, :block_code, :character_action, :character_motivation])
end
end
And finally, the migrations I added for id and foreign_key for both block_block and block_character:
class AddBelongsToToBlockBlocks < ActiveRecord::Migration
def change
add_reference :block_blocks, :block, index: true
add_foreign_key :block_blocks, :blocks
end
end
class AddBelongsToToBlockCharacters < ActiveRecord::Migration
def change
add_reference :block_characters, :block, index: true
add_foreign_key :block_characters, :blocks
end
end
Honestly, thank you all so much for your help through this, I am by no means an advanced Rails user and this has all been amazingly helpful. Please let me know if you need any more information!
UPDATE 1
So I changed the following in block.rb (the model file), as suggested by Vijay (thanks so much!!!):
class Block < ActiveRecord::Base
validates_presence_of :location_code
validates_presence_of :scene_code
has_one :cue
has_many :block_blocks
has_many :block_characters
accepts_nested_attributes_for :cue, allow_destroy: true
accepts_nested_attributes_for :block_blocks, allow_destroy: true
accepts_nested_attributes_for :block_characters, allow_destroy: true
attr_accessor :block_blocks
attr_accessor :block_characters
end
At this point, the block saves (and appears in the index view), but the block_block and block_character do not do so. There is no associated error however...
UPDATE 2
This is currently what the params submitted look like:
Which is odd because it says that cue, block_block, and block_character are unpermitted parameters, even though, in the controller they are:
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], :block_block_attributes => [:id, :block_block_code, :primary_block_code, :secondary_block_code, :block_block_start], :block_character_attributes => [:id, :block_character_code, :character_code, :block_code, :character_action, :character_motivation])
end
Are you triggering the error in the validation?
validates_presence_of :location
From your code it looks like it should be
validates_presence_of :location_code
Not sure why you've added these in Rails 4
attr_accessor :block_blocks
attr_accessor :block_characters
Try removing them and see if they are interfering with the controller (I'm guessing, but happy to play if you put up a jsfiddle)
First things first
Using:
rails4
oracle enhanced adapter rails4 branch
I have a many to many relationship mapped on an existing database.
My models look as such:
class EventMap < ActiveRecord::Base
self.table_name="TAKE_PART"
self.primary_key="id"
belongs_to :event, foreign_key: "lottery_event_id"
belongs_to :entrant, foreign_key: "address_id"
end
class Event < ActiveRecord::Base
self.table_name="THE_EVENT"
self.primary_key="id"
has_many :event_maps, :foreign_key => "lottery_event_id"
has_many :entrants, :through => :event_maps
accepts_nested_attributes_for :entrants, :reject_if => :all_blank
end
class Entrant < ActiveRecord::Base
self.table_name="ADDRESSES"
self.primary_key="id"
self.set_date_columns :date_of_birth
has_many :events, :through => :event_maps
has_many :event_maps, :foreign_key => "address_id"
end
static page controller for my voting page
...
def vote
#event=Event.find_by(id: 4227)
#entrants=#event.entrants
#entrant=#event.entrants.build
end
...
vote view:
<%= form_for(#event) do |f| %>
<%= f.fields_for :entrant do |builder| %>
<%= render "/entrants/fields", :f => builder %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
entrant/fields partial:
<% if #entrant.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#entrant.errors.count, "error") %> prohibited this entrant from being saved:</h2>
<ul>
<% #entrant.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :id %>
<div class="field">
<%= f.label :lastname %><br>
<%= f.text_field :lastname %>
</div>
<div class="field">
<%= f.label :firstname %><br>
<%= f.text_field :firstname %>
</div>
<div class="field">
<%= f.label :street %><br>
<%= f.text_field :street %>
</div>
<div class="field">
<%= f.label :country_id %><br>
<%= f.number_field :country_id %>
</div>
<div class="field">
<%= f.label :city %><br>
<%= f.text_field :city %>
</div>
<div class="field">
<%= f.label :telephone %><br>
<%= f.text_field :telephone %>
</div>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :date_of_birth %><br>
<%= f.date_select :date_of_birth %>
</div>
<div class="field">
<%= f.label :lang_id %><br>
<%= f.text_field :lang_id %>
</div>
<div class="field">
<%= f.label :added %><br>
<%= f.date_select :added %>
</div>
<div class="field">
<%= f.label :salut %><br>
<%= f.text_field :salut %>
</div>
<div class="field">
<%= f.label :zip %><br>
<%= f.text_field :zip %>
</div>
<div class="field">
<%= f.label :newsletter %><br>
<%= f.check_box :newsletter %>
</div>
<div class="field">
<%= f.label :company %><br>
<%= f.text_field :company %>
</div>
The form now submits to event controller PATCH
class EventsController < ApplicationController
before_action :set_event, only: [:show, :edit, :update, :destroy]
...
# PATCH/PUT /events/1
# --> HOW DO I SAVE THE SUBMITTED ENTRANT HERE??? <--
def update
respond_to do |format|
if #event.update(event_params)
format.html { redirect_to #event, notice: 'Event was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
...
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = Event.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def event_params
params.require(:event).permit(:id, :lottery_id, :events_dates_id, :event_date, :event_location, :tickets_for_winner, :prize, :tickets_internally,
:entrants_attributes => [:id, :lastname, :firstname, :street, :country_id, :city, :telephone, :email, :date_of_birth, :lang_id, :added, :salut, :zip, :newsletter, :company])
end
end
How do I register an Entrant with an Event, adding data only to the intermediate model EventMap since the Event will always exist?
Do I need to include accepts_nested_attributes_for in my models to propagate changes accross tables (I could not quite figure out what this does from the documentation)? Do I need to send additional params via the Entrant form to update the EventMap?
Main GOAL: I want a form where Entrants can register to an existing event!
Hard to judge about Your forms, as we don't see any ;)
But You are right to be able to create nested attributes, from nested attributes from, You need to set accepts_nested_attributes_for :some_model, :some_other_model
If You find docs confusing, consult Railscasts:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
You are requiring custom logic and that custom logic must be defined, Rails will not automatically update everything, it must be defined in the update controller as you suggest.
I might do something along the lines of this:
def update
entrant = Entrant.find(params[:entrant_id])
event = Event.find(params[:event_id])
EventMap.create!(event: event, entrant: entrant)
#.... go on with usual stuff
# Alternatively you could use build
event_map = EventMap.new
event_map.build(event: event, entrant: entrant)
end