f.collection_select with name - ruby-on-rails

I hope someone can help me.
I have a table with the name "location_location_relationships". If you create a new entry you can select two locations (predecessor and successor) which are from a "locaions" table. In addition you can select a tour. These are coming from table "tours". The locations selection is working. But the tours makes some problems. First I had nothing in the models everything worked but the selection wrote not the names but the ids in the "location_location_relationships" table. But I want the names in there. So I completed the models of "tours" and "location_location_relationships". In the selection there are the names of the tours now but if I press the Button "create" I get an error massage:
Tour(#96769428) expected, got String(#1848192)
and it shows me the error in the location_location_relationship_controller.rb in:
'def create
#location_location_relationship = LocationLocationRelationship.new(location_location_relationship_params)'
Has anyone an idea what I did wrong?
Thank you very much for your help in advance!
This is my location_location_relationships_form.html.erb where the collection_select is in:
<%= form_for(#location_location_relationship) do |f| %>
<% if #location_location_relationship.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#location_location_relationship.errors.count, "error") %> prohibited this location_location_relationship from being saved:</h2>
<ul>
<% #location_location_relationship.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label 'Von Ort' %><br />
<%= f.collection_select :predecessor_id, Location.all, :id, :name %>
</div>
<div class="field">
<%= f.label 'Zu Ort' %><br />
<%= f.collection_select :successor_id, Location.all, :id, :name %>
</div>
<div class="field">
<%= f.label 'Tour' %><br>
<%= f.collection_select :tour, Tour.all, :id, :name_of_tour, prompt: true %>
</div>
<div class="field">
<%= f.label 'Distanz' %><br>
<%= f.text_field :distance, type: "number", min:0 %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My model of the location_location_relationships:
class LocationLocationRelationship < ActiveRecord::Base
belongs_to :successor, class_name: "Location"
belongs_to :predecessor, class_name: "Location"
validates :successor_id, presence: true
validates :predecessor_id, presence: true
belongs_to :tour
validates :tour, presence: true
validates :distance, :numericality => true
# validates :sequence, :numericality => {:only_integer => true}
# validates :binary_variable, :numericality => {:only_integer => true}
end
And my tours model:
class Tour < ActiveRecord::Base
#validates :tour, presence: true
has_many :location_location_relationships
def name_of_tour
name
end
end
And the location_location_relationships controller:
class LocationLocationRelationshipsController < ApplicationController
before_action :set_location_location_relationship, only: [:show, :edit, :update, :destroy]
# GET /location_location_relationships
# GET /location_location_relationships.json
def index
#location_location_relationships = LocationLocationRelationship.all
end
# GET /location_location_relationships/1
# GET /location_location_relationships/1.json
def show
end
# GET /location_location_relationships/new
def new
#location_location_relationship = LocationLocationRelationship.new
end
# GET /location_location_relationships/1/edit
def edit
end
# POST /location_location_relationships
# POST /location_location_relationships.json
def create
#location_location_relationship = LocationLocationRelationship.new(location_location_relationship_params)
respond_to do |format|
if #location_location_relationship.save
format.html { redirect_to #location_location_relationship, notice: 'Die Distanz wurde angelegt.' }
format.json { render :show, status: :created, location: #location_location_relationship }
else
format.html { render :new }
format.json { render json: #location_location_relationship.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /location_location_relationships/1
# PATCH/PUT /location_location_relationships/1.json
def update
respond_to do |format|
if #location_location_relationship.update(location_location_relationship_params)
format.html { redirect_to #location_location_relationship, notice: 'Die Distanz wurde aktualisiert.' }
format.json { render :show, status: :ok, location: #location_location_relationship }
else
format.html { render :edit }
format.json { render json: #location_location_relationship.errors, status: :unprocessable_entity }
end
end
end
# DELETE /location_location_relationships/1
# DELETE /location_location_relationships/1.json
def destroy
#location_location_relationship.destroy
respond_to do |format|
format.html { redirect_to location_location_relationships_url, notice: 'Die Distanz wurde gelöscht.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_location_location_relationship
#location_location_relationship = LocationLocationRelationship.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def location_location_relationship_params
params.require(:location_location_relationship).permit(:predecessor_id, :successor_id, :tour, :distance, :sequence, :binary_variable)
end
end

Tour(#96769428) expected, got String(#1848192)
You should change tour to tour_id
<div class="field">
<%= f.label 'Tour' %><br>
<%= f.collection_select :tour_id, Tour.all, :id, :name_of_tour, prompt: true %>
</div>
And also in location_location_relationship_params
def location_location_relationship_params
params.require(:location_location_relationship).permit(:predecessor_id, :successor_id, :tour_id, :distance, :sequence, :binary_variable)
end

Related

ID changed to NULL on update - Rails 4

I have a landlord and landlord_address model. When a new landlord_address is created, the landlord_id is saved to the table. For some reason, when I edit a landlord_address the landlord_id is changed to NULL.
Models:
class Landlord < ActiveRecord::Base
has_many :landlord_addresses, dependent: :destroy
belongs_to :listing_agent, class_name: 'Agent'
end
class LandlordAddress < ActiveRecord::Base
belongs_to :landlord
has_many :landlord_companies, dependent: :destroy
end
Landlord Addresses Controller:
module Matrix
class LandlordAddressesController < ApplicationController
before_action :set_landlord_address, only: [:show, :edit, :update, :destroy]
# GET /landlord_addresses
# GET /landlord_addresses.json
def index
#landlord = Landlord.find(params[:landlord_id])
#landlord_addresses = #landlord.landlord_addresses.order(address_line_one: :asc)
end
# GET /landlord_addresses/1
# GET /landlord_addresses/1.json
def show
end
# GET /landlord_addresses/new
def new
#landlord_address = LandlordAddress.new
#landlord = Landlord.find(params[:landlord_id])
end
# GET /landlord_addresses/1/edit
def edit
end
# POST /landlord_addresses
# POST /landlord_addresses.json
def create
#landlord_address = LandlordAddress.new(landlord_address_params)
respond_to do |format|
if #landlord_address.save
format.html { redirect_to matrix_landlord_landlord_addresses_path, notice: 'Landlord address was successfully created.' }
format.json { render :show, status: :created, location: #landlord_address }
else
format.html { render :new }
format.json { render json: #landlord_address.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /landlord_addresses/1
# PATCH/PUT /landlord_addresses/1.json
def update
respond_to do |format|
if #landlord_address.update(landlord_address_params)
format.html { redirect_to matrix_landlord_landlord_addresses_path, notice: 'Landlord address was successfully updated.' }
format.json { render :show, status: :ok, location: #landlord_address }
else
format.html { render :edit }
format.json { render json: #landlord_address.errors, status: :unprocessable_entity }
end
end
end
# DELETE /landlord_addresses/1
# DELETE /landlord_addresses/1.json
def destroy
#landlord_address.destroy
respond_to do |format|
format.html { redirect_to landlord_addresses_url, notice: 'Landlord address was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_landlord_address
#landlord_address = LandlordAddress.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def landlord_address_params
params.require(:landlord_address).permit(:address_line_one, :address_line_two, :city, :state, :zip, :super_name, :super_number, :landlord_id, :latitude, :longitude)
end
end
end
Landlord Addresses _form:
<div class="feedback-container">
<%= form_for [:matrix, #landlord_address] do |f| %>
<% if #landlord_address.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#landlord_address.errors.count, "error") %> prohibited this landlord_address from being saved:</h2>
<ul>
<% #landlord_address.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
/ul>
</div>
<% end %>
<div id="form-map"></div>
<input id="pac-input" class="controls" type="text"
placeholder="Enter a location">
<div id="type-selector" class="controls">
<input type="radio" name="type" id="changetype-all" checked="checked">
<label for="changetype-all">All</label>
</div>
<div class="field">
<%= f.label :address, class: "general-text-label" %>
<%= f.text_field :address_line_one, class: "general-text-field map-autocomplete-address" %>
<%= f.hidden_field :latitude, class: "map-autocomplete-latitude" %>
<%= f.hidden_field :longitude, class: "map-autocomplete-longitude" %>
</div>
<div class="field">
<%= f.label :super_name, class: "general-text-label" %><br>
<%= f.text_field :super_name, class: "general-text-field" %>
</div>
<div class="field">
<%= f.label :super_number, class: "general-text-label" %><br>
<%= f.text_field :super_number, class: "general-text-field" %>
</div>
<div class="field">
<%= f.hidden_field :landlord_id, :value => params[:landlord_id] %>
</div><br>
<div class="actions">
<%= f.submit "Submit", class: "btn btn-black btn-4x" %>
</div>
<% end %>
</div>
Routes:
namespace :matrix do
resources :landlords, shallow: true do
resources :landlord_addresses do
resources :landlord_companies
end
end
end
New Error:
This part
<%= f.hidden_field :landlord_id, :value => params[:landlord_id] %>
will be your issue. When params[:landlord_id] is nil your record will be updated to null.
You should change it to
<%= f.hidden_field :landlord_id, :value => #landlord_address.landlord_id || #landlord.id %>
or some thing else.
Your route is nested, You dnt need to assign in hidden field. You can do it in the controller, passing params.
Form:
Remove hidden field, we are assigning it in the controller!
<div class="field">
<%= f.hidden_field :landlord_id, :value => params[:landlord_id] %>
</div><br>
Controller:
# POST /landlord_addresses
# POST /landlord_addresses.json
def create
#landlord_address = LandlordAddress.new(landlord_address_params)
# add this line here!
#landlord_address.landlord_id = params[:landlord_id]
respond_to do |format|
if #landlord_address.save
format.html { redirect_to matrix_landlord_landlord_addresses_path, notice: 'Landlord address was successfully created.' }
format.json { render :show, status: :created, location: #landlord_address }
else
format.html { render :new }
format.json { render json: #landlord_address.errors, status: :unprocessable_entity }
end
end
end
private
#ALSO REMOVE `:landlord_id` from
def landlord_address_params
params.require(:landlord_address).permit(:address_line_one, :address_line_two, :city, :state, :zip, :super_name, :super_number, :latitude, :longitude)
end

Show nested_fields in Rails 4

I have a weird problem with "nested_form" in Rails. I made a model "evaluate" associated to other model "proyect", but when I try to show theres fields, on "proyects" form, just show fields from "proyects".
Here is my code:
Models:
proyect.erb
class Proyect < ActiveRecord::Base
belongs_to :user
has_many :vercions #I know is versions
has_many :evaluates #I know is evaluators
accepts_nested_attributes_for :evaluates, allow_destroy: true
validates :titulo,:presence => true,
:length => { :minimum => 3 }
validates :descripcion,:presence => true,
:length => { :minimum => 3 }
end
evaluate.erb
class Evaluate < ActiveRecord::Base
belongs_to :proyect
has_and_belongs_to_many :users
end
Controller
proyects_controller.erb
class ProyectsController < ApplicationController
before_action :set_proyect, only: [:show, :edit, :update, :destroy]
# GET /proyects
# GET /proyects.json
def index
if current_user.tipo == 'i'
#proyects = Proyect.where(:user_id => current_user.id)
else
#proyects = #Proyect.where(:id_user => current_user.id)
Proyect.all
end
end
# GET /proyects/1
# GET /proyects/1.json
def show
#vercion = Vercion.new
end
# GET /proyects/new
def new
#proyect = Proyect.new
#proyect.evaluates.build
end
# GET /proyects/1/edit
def edit
end
# POST /proyects
# POST /proyects.json
def create
#proyect = current_user.proyects.new(proyect_params)
respond_to do |format|
if #proyect.save
format.html { redirect_to #proyect, notice: 'Proyecto creado!.' }
format.json { render :show, status: :created, location: #proyect }
else
format.html { render :new }
format.json { render json: #proyect.errors, status: :unprocessable_entity }
end
# Llamamos al ActionMailer que creamos
Usermailer.bienvenido_email(current_user,#proyect).deliver
end
end
# PATCH/PUT /proyects/1
# PATCH/PUT /proyects/1.json
def update
respond_to do |format|
if #proyect.update(proyect_params)
format.html { redirect_to #proyect, notice: 'Proyect was successfully updated.' }
format.json { render :show, status: :ok, location: #proyect }
else
format.html { render :edit }
format.json { render json: #proyect.errors, status: :unprocessable_entity }
end
end
end
# DELETE /proyects/1
# DELETE /proyects/1.json
def destroy
#proyect.destroy
respond_to do |format|
format.html { redirect_to proyects_url, notice: 'Proyect was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_proyect
#proyect = Proyect.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def proyect_params
params.require(:proyect).permit(
:titulo, :descripcion,:evaluador, :id_user, :codigo, :user_assign,evaluates_attributes: [:id,:nombre, :prioridad, :_destroy, user_ids: [] ])
end
end
Views
_form.html.erb (Proyects)
<%= nested_form_for(#proyect) do |f| %>
<% if #proyect.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#proyect.errors.count, "error") %> prohibited this proyect from being saved:</h2>
<ul>
<% #proyect.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :titulo %><br>
<%= f.text_field :titulo %>
</div>
<div class="field">
<%= f.label :descripcion %><br>
<%= f.text_area :descripcion %>
</div>
<div class="field">
<%= f.hidden_field :id_user, :value => current_user.id %>
</div>
<!--Aqui añadi algo-->
<fieldset id="evaluates">
<%= f.fields_for :evaluates do |evaluates_form| %>
<div class="field">
<%= evaluates_form.label :status %><br>
<%= evaluates_form.text_field :status %>
</div>
<%= evaluates_form.link_to_remove "Eliminar esta tarea" %>
<% end %>
<p><%= f.link_to_add "Agregar una tarea", :evaluates %></p>
</fieldset>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
_evaluate_fields.html.erb
<div class="field">
<%= f.label :status, 'Nombre de la tarea' %><br>
<%= f.text_field :status %>
</div>
<div class="field">
<%= f.collection_check_boxes :user_ids, User.where(:tipo => 'e'), :id, :cedula %>
</div>
<%= f.link_to_remove "Eliminar Evaluador" %>

Nested forms not storing data into database in rails 4

I have a vendor model, a product model, and a vendor_product model. In my vendors form, I have used nested form to create vendor_products with attributes as vendor_id, product_id and copies.On creating a new vendor, it also creates a vendor_product. But for some reason, it does not stores the vendor_id and product_id in vendor_products table but only stores the copies
My associations are as follows
A vendor ->
has_many :vendor_products
has_many :products, through: :vendor_products
A product ->
has_many :vendor_products
has_many :vendors, through: :vendor_products
A vendor_product
belongs_to :vendor
belongs_to :product
Vendor.rb
class Vendor < ActiveRecord::Base
has_many :vendor_products
has_many :products, through: :vendor_products
accepts_nested_attributes_for :vendor_products, :products,
:allow_destroy => true
end
My vendors/_form.html.erb
<%= form_for(#vendor) do |f| %>
<% if #vendor.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#vendor.errors.count, "error") %> prohibited this
vendor from being saved:</h2>
<ul>
<% #vendor.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
:
:
:
<%= f.fields_for :vendor_products do |vproducts| %>
<div class="field">
<%= vproducts.label :product %><br>
<%= collection_select(:product, :product_ids, Product.all, :id,
:product_name,
{:prompt => 'Please select', :multiple => true }) %>
</div>
<div class="field">
<%= vproducts.label :copies %><br>
<%= vproducts.number_field :copies %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My vendors_controller.rb
class VendorsController < ApplicationController
before_action :set_vendor, only: [:show, :edit, :update, :destroy]
respond_to :json
def index
#vendors = Vendor.all.limit(20)
end
def show
end
def new
#vendor = Vendor.new
#vendor.products.build
#vendor.vendor_products.build
end
def edit
end
def create
#vendor = Vendor.new(vendor_params)
respond_to do |format|
if #vendor.save
format.html { redirect_to #vendor, notice: 'Vendor was successfully
created.' }
format.json { render :show, status: :created, location: #vendor }
else
format.html { render :new }
format.json { render json: #vendor.errors, status:
:unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #vendor.update(vendor_params)
format.html { redirect_to #vendor, notice: 'Vendor was successfully
updated.' }
format.json { render :show, status: :ok, location: #vendor }
else
format.html { render :edit }
format.json { render json: #vendor.errors, status:
:unprocessable_entity }
end
end
end
private
def set_vendor
#vendor = Vendor.find(params[:id])
end
def vendor_params
params.require(:vendor).permit(:name, :email, :phone_no, :addressline1,
:addressline2, :landmark,
:city, :state, :country, :pincode, :latitude, :longitude, :status,
product_attributes: [:product_id, :product_name, :price ],
vendor_products: [:vendor_product_id, :vendor_id, :product_id,
:copies])
end
end
Now a vendor and VendorProduct is created but my vendor_product looks lik this
{"id":3,
"vendor_id":null,
"product_id":null,
"copies":4,
}
Can any one point out how to fix this. What am I doing wrong. Please bear in mind that I am a rails newbie.
change once vendor_products to vendor_products_attributes and look
In your view
<%= collection_select(:product, :product_ids, Product.all, :id,
:product_name,
{:prompt => 'Please select', :multiple => true }) %>
replace with
<%= vproducts.select :product_id, options_from_collection_for_select(Product.all, "id", "name"), prompt: "Select something" %>
Change this line:
<%= collection_select(:product, :product_ids, Product.all, :id,
:product_name,
{:prompt => 'Please select', :multiple => true }) %>
</div>
to
<%= collection_select(:product, :product_id, Product.all, :id,
:product_name,
{:prompt => 'Please select', :multiple => true }) %>
</div>

Rails - Nest Attributes Issues

I am having issues understanding this.
What am I trying to accomplish?
Selected items in dropdown submitted to inventory.
Change the status of each item in a form in its own model.
Problem
I submit a form and the status of each item in the dropdown doesn't get submitted.
Any help would be appreciated.
Thanks in advance!
Form Code
<%= form_for(#inventory, html: {class: "form-horizontal"}) do |f| %>
<% if #inventory.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#inventory.errors.count, "error") %> prohibited this inventory from being saved:</h2>
<ul>
<% #inventory.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :tablet_id, "Tablet #", class: "col-md-2 control-label" %>
<div class="col-md-4">
<%= select("inventory", "tablet_id", Tablet.where("status = '1'").all.collect{ |t| [t.alias, t.id] }, {}, { class: "form-control"} ) %>
</div>
</div>
<%= f.fields_for :tablet do |t| %>
<%= t.hidden_field :status, value: 2 %>
<% end %>
<div class="form-group">
<%= f.label :chauffeur_id, "Chauffeur #", class: "col-md-2 control-label" %>
<div class="col-md-4">
<%= select("inventory", "chauffeur_id", Chauffeur.where("status = '1'").all.collect{ |t| [t.chaufNum, t.id] }, {}, { class: "form-control"} ) %>
</div>
</div>
<%= f.fields_for :chauffeur do |t| %>
<%= t.hidden_field :status, value: 2 %>
<% end %>
<div class="form-group">
<%= f.label :vehicle_id, "Vehicle #", class: "col-md-2 control-label" %>
<div class="col-md-4">
<%= select("inventory", "vehicle_id", Vehicle.where("status = '1'").all.collect{ |t| [t.vehNum, t.id] }, {}, { class: "form-control"} ) %>
</div>
</div>
<%= f.fields_for :vehicle do |t| %>
<%= t.hidden_field :status, value: 2 %>
<% end %>
<div class="form-group">
<div class="col-md-2 col-md-offset-2">
<%= f.submit class: "btn btn-sm btn-success" %>
</div>
</div>
<% end %>
Model (Inventory)
class Inventory < ActiveRecord::Base
belongs_to :tablet
belongs_to :chauffeur
belongs_to :vehicle
accepts_nested_attributes_for :tablet
accepts_nested_attributes_for :chauffeur
accepts_nested_attributes_for :vehicle
has_paper_trail
validates :tablet_id, :chauffeur_id, :vehicle_id, presence: true
validates :tablet_id, :chauffeur_id, :vehicle_id, uniqueness: { message: " is already checked out." }
end
Inventory Controller
class InventoriesController < ApplicationController
before_action :authenticate_user!
before_filter :set_paper_trail_whodunnit
before_action :set_inventory, only: [:show, :edit, :update, :destroy]
# GET /inventories
# GET /inventories.json
def index
#inventories = Inventory.all.paginate(:page => params[:page], :per_page => 15)
end
# GET /inventories/1
# GET /inventories/1.json
def show
#versions = PaperTrail::Version.order('created_at DESC')
end
# GET /inventories/new
def new
#inventory = Inventory.new
end
# GET /inventories/1/edit
def edit
end
def history
#versions = PaperTrail::Version.order('created_at DESC')
end
# POST /inventories
# POST /inventories.json
def create
# #inventory = Inventory.new(inventory_params)
render plain: params[:inventory].inspect
# respond_to do |format|
# if #inventory.save
# format.html { redirect_to #inventory, notice: 'Inventory was successfully created.' }
# format.json { render :show, status: :created, location: #inventory }
# else
# format.html { render :new }
# format.json { render json: #inventory.errors, status: :unprocessable_entity }
# end
# end
end
# PATCH/PUT /inventories/1
# PATCH/PUT /inventories/1.json
def update
respond_to do |format|
if #inventory.update(inventory_params)
format.html { redirect_to #inventory, notice: 'Inventory was successfully updated.' }
format.json { render :show, status: :ok, location: #inventory }
else
format.html { render :edit }
format.json { render json: #inventory.errors, status: :unprocessable_entity }
end
end
end
# DELETE /inventories/1
# DELETE /inventories/1.json
def destroy
#inventory.destroy
respond_to do |format|
format.html { redirect_to inventories_url, notice: 'Inventory was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_inventory
#inventory = Inventory.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def inventory_params
params.require(:inventory).permit(:tablet_id, :chauffeur_id, :vehicle_id, tablet_attributes: [:status => '2'], chauffeur_attributes: [:status => '2'], vehicle_attributes: [:status => '2'])
end
end
Clean all your nested attribute code. This is not what you want. So model like this:
class Inventory < ActiveRecord::Base
belongs_to :tablet
belongs_to :chauffeur
belongs_to :vehicle
has_paper_trail
validates :tablet_id, :chauffeur_id, :vehicle_id, presence: true
validates :tablet_id, :chauffeur_id, :vehicle_id, uniqueness: { message: " is already checked out." }
end
Now, what you want to use a rails callback so that when you create an inventory then you update the status of other things. This goes on your model too:
class Inventory < ActiveRecord::Base
...
after_create :update_status
protected
def update_status
self.tablet.update_attribute(:status, 2)
self.chauffeur.update_attribute(:status, 2)
self.vehicle.update_attribute(:status, 2)
end
end
Also remember to clean all your fields_for code and your strong parameters on your controller...you don't need the nested ones anymore.

Can't mass-assign protected attributes when using accepts_nested_attributes_for and polymorphic

I've read through lots of posts here and still cant figure this one out.
I have a forum_post model and a links model. I want to nest the links form with the forum_post form but keep getting a Can't mass-assign protected attributes: links.
ForumPost Model
class ForumPost < ActiveRecord::Base
attr_accessible :content, :links_attributes
has_many :links, :as => :linkable, :dependent => :destroy
accepts_nested_attributes_for :links, :allow_destroy => true
end
Links Model
class Link < ActiveRecord::Base
attr_accessible :description, :image_url, :link_url, :linkable_id, :linkable_type, :title
belongs_to :linkable, :polymorphic => true
end
Forum_post View
<%= form_for(#forum_post) do |f| %>
<% if #forum_post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#forum_post.errors.count, "error") %> prohibited this forum_post from being saved:</h2>
<ul>
<% #forum_post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_area :content, :rows => 5 %>
</div>
<%= f.fields_for :link do |link| %>
<%= render :partial => 'links/link', :locals => { :f => link} %>
<% end%>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Link View Partial
<div class="field">
<%= f.label :link_url %><br />
<%= f.text_field :link_url, :id => "url_field" %>
</div>
<div id="link_preview">
</div>
ForumPosts Controller
class ForumPostsController < ApplicationController
def new
#forum_post = ForumPost.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #forum_post }
end
def create
#forum_post = ForumPost.new(params[:forum_post])
respond_to do |format|
if #forum_post.save
format.html { redirect_to #forum_post, notice: 'Forum post was successfully created.' }
format.json { render json: #forum_post, status: :created, location: #forum_post }
else
format.html { render action: "new" }
format.json { render json: #forum_post.errors, status: :unprocessable_entity }
end
end
end
Links Controller
class LinksController < ApplicationController
def find_linkable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
def index
#linkable = find_linkable
#links = #linkable.links
end
def create
#linkable = find_linkable
#link = #linkable.links.build(params[:link])
if #link.save
flash[:notice] = "Successfully saved link."
redirect_to :id => nil
else
render :action => 'new'
end
end
end
Well, according to your question the protected attributes that you can't mass-assign is :links.
Not sure how that happened, but have you tried attr_accessible :links?
As for the security implications, it is the reason github got hacked once https://gist.github.com/1978249, and I would highly discourage setting whitelist_attributes to false.

Resources