Rails multiple select puts extra blank parameter - ruby-on-rails

I'm trying to create an HTML multiple select using collection_select, to be able to update an entity (a Student) which has a collection of another entity (a SubscriptionList) as a nested attribute. This is backed up by a HABTM ActiveRecord's relation.
I have created the following form for the Student via scaffolding:
<div class="field">
<%= f.label :first_name %><br>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name %><br>
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :file_number %><br>
<%= f.text_field :file_number %>
</div>
<div class="field">
<%= f.label :subscription_list %><br>
<%= f.collection_select(:subscription_lists, SubscriptionList.all, :id, :name, {}, {:multiple => true}) %>
</div>
<div class="actions">
<%= f.submit %>
</div>
and it draws the multiple select properly.
However, if I fill the form and try to PUT the entity, I'm getting this as the params:
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"vXYMRYI1UtX7WJRZM0OPIhHQSSEyNOPyUxkUvScdu45PTL7qVhvlJfQYNvaKG5rw+mvHAAAbf6ViTQ6tE4lV1Q==", "student"=>{"first_name"=>" Mariana", "last_name"=>"González", "file_number"=>"12345678", "subscription_lists"=>["", "3"]}, "commit"=>"Update Student", "controller"=>"students", "action"=>"update", "id"=>"14"}
So, my Student is
"first_name"=>" Mariana", "last_name"=>"González", "file_number"=>"12345678", "subscription_lists"=>["", "3"]}
I find it very strange to be receiving ["", "3"] as the values. Why I'm receiving this first "" value?
I'm also posting here my Controller (actions other that update have been deleted for brevity)
class StudentsController < ApplicationController
before_action :set_student, only: [:show, :edit, :update, :destroy, :enrollments]
# PATCH/PUT /students/1
# PATCH/PUT /students/1.json
def update
puts "\n\n\n\n\n\n\n\n\nThese are the params: #{params.inspect}"
puts "\n\n\n\n\nThis is student_params object: #{student_params.inspect}\n\n\nand its class #{student_params.class}"
#puts "\n\n\n\n\n\n\n\n\nWill look for SL with ID: #{params[:subscription_lists_id]}"
all_ids = student_params.subscription_lists.collect {|sl| sl.id }
#student.subscription_lists = SubscriptionList.find(all_ids)
##student.subscription_lists = SubscriptionList.where(id: all_ids)
respond_to do |format|
if #student.update(student_params)
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { render :show, status: :ok, location: #student }
else
format.html { render :edit }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_student
#student = Student.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def student_params
#params[:student]
#params.require(:foo).permit(:bar, {:baz => [:x, :y]})
#params.require(:student).permit(:first_name, :last_name, :file_number, :subscription_lists)
params.require(:student).permit! # No strong parameters...
end
end
In fact, I'd rather receive a Student with a nested collection of SubscriptionList instead of just receving an array of ids, but I'm not sure if this is even possible.
Any help would be really appreciated.
Best regards

About your question has been answered in collection select always adding blank value.
You will get [""] when you did not select anything or you select your options select as default. To avoid this you have to add hidden_field before the collection select.
<div class="field">
<%= f.label :subscription_lists %><br>
<%= f.hidden_field :subscription_lists %>
<%= f.collection_select(:subscription_lists, SubscriptionList.all, :id, :name, {}, {:multiple => true}) %>
</div>
The hidden_field helps you when it's nothing selected. How about when you choose it? Please try this.
def update
if student_params["subscription_lists"].any?
student_params["subscription_lists"].reject!(&:empty?)
end
respond_to do |format|
if #student.update(student_params)
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { render :show, status: :ok, location: #student }
else
format.html { render :edit }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
I hope this help you.

This is what I ended up doing, mostly following this tutorial.
For the Controller:
class StudentsController < ApplicationController
before_action :set_student, only: [:show, :edit, :update, :destroy, :enrollments]
# PATCH/PUT /students/1
# PATCH/PUT /students/1.json
def update
puts "\n\n\n\n\n\n\n\n\nThese are the params: #{params.inspect}"
puts "\n\n\n\n\nThis is student_params object: #{student_params.inspect}\n\n\nand its class #{student_params.class}"
#subscription_lists = SubscriptionList.where(:id => params[:subscriptions])
#student.subscription_lists.destroy_all # disassociate the already added
#student.subscription_lists << #subscription_lists
respond_to do |format|
if #student.update(student_params)
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { render :show, status: :ok, location: #student }
else
format.html { render :edit }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_student
#student = Student.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def student_params
params.require(:student).permit(:first_name, :last_name, :file_number, subscription_lists: [:id])
end
end
And the form:
<div class="field">
<%= f.label :subscription_list %><br>
<%= select_tag "subscriptions", options_from_collection_for_select(SubscriptionList.all, 'id', 'name',#student.subscription_lists.map { |j| j.id }), :multiple => true %>
</div>
Hope it's useful

Related

Difficulties with Nested Forms in Rails 6.1.3.2

I’m working on a project that will utilize nested forms that incorporates Rails 6.1.3 and Bootstrap 5.1.2.
I’m having difficulty getting the nested form feature to work.
Project GitHub: cjmccormick88/testapp-nested
There are two models: client and shipping address.
Client accepts nested attributes for the shipping address model. A client can have many shipping addresses.
Authentication is being handled by Devise. Bootstrap is used for styling. Audited is used for audit trail.
Clients Controller
class ClientsController < ApplicationController
before_action :set_client, only: %i[ show edit update destroy ]
# GET /clients or /clients.json
def index
#clients = Client.all
end
# GET /clients/1 or /clients/1.json
def show
end
# GET /clients/new
def new
#client = Client.new
#client.shipping_addresses.build
end
# GET /clients/1/edit
def edit
end
# POST /clients or /clients.json
def create
#client = Client.new(client_params)
#client.shipping_addresses.build(client_params[:shipping_addresses_attributes])
#client.save
respond_to do |format|
if #client.save
format.html { redirect_to #client, notice: "Client was successfully created." }
format.json { render :show, status: :created, location: #client }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /clients/1 or /clients/1.json
def update
respond_to do |format|
if #client.update(client_params)
format.html { redirect_to #client, notice: "Client was successfully updated." }
format.json { render :show, status: :ok, location: #client }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
# DELETE /clients/1 or /clients/1.json
def destroy
#client.destroy
respond_to do |format|
format.html { redirect_to clients_url, notice: "Client was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_client
#client = Client.find(params[:id])
end
# Only allow a list of trusted parameters through.
def client_params
params.require(:client).permit(:client_name, shipping_addresses_attributes: [:id, :address_line1, :address_line2, :city, :state, :country])
end
end
Client Model
class Client < ApplicationRecord
audited
has_many :shipping_addresses, :inverse_of => :client, autosave: true
accepts_nested_attributes_for :shipping_addresses
end
Shipping Address Model
class ShippingAddress < ApplicationRecord
audited
belongs_to :client
validates :client, :presence => true
end
Client View Form Partial
<%= form_with(model: client) do |form| %>
<% if client.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(client.errors.count, "error") %> prohibited this client from being saved:</h2>
<ul>
<% client.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :client_name %>
<%= form.text_field :client_name %>
</div>
<%= form.fields_for #client.shipping_addresses.build do |s| %>
<div class="field">
<%= s.label :address_line1, 'Address Line 1' %>
<%= s.text_field :address_line1 %>
</div>
<div class="field">
<%= s.label :address_line2, 'Address Line 2' %>
<%= s.text_field :address_line2 %>
</div>
<div class="field">
<%= s.label :city, 'City' %>
<%= s.text_field :city %>
</div>
<div class="field">
<%= s.label :state, 'State' %>
<%= s.text_field :state %>
</div>
<div class="field">
<%= s.label :country, 'Country' %>
<%= s.text_field :country %>
</div>
<% end %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
In addition, there is a controller for shipping addresses if someone chooses to view those pages on their own.
Shipping Addresses Controller
class ShippingAddressesController < ApplicationController
before_action :set_shipping_address, only: %i[ show edit update destroy ]
# GET /shipping_addresses or /shipping_addresses.json
def index
#shipping_addresses = ShippingAddress.all
end
# GET /shipping_addresses/1 or /shipping_addresses/1.json
def show
end
# GET /shipping_addresses/new
def new
#shipping_address = ShippingAddress.new
end
# GET /shipping_addresses/1/edit
def edit
end
# POST /shipping_addresses or /shipping_addresses.json
def create
#shipping_address = ShippingAddress.new(shipping_address_params)
respond_to do |format|
if #shipping_address.save
format.html { redirect_to #shipping_address, notice: "Shipping address was successfully created." }
format.json { render :show, status: :created, location: #shipping_address }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #shipping_address.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /shipping_addresses/1 or /shipping_addresses/1.json
def update
respond_to do |format|
if #shipping_address.update(shipping_address_params)
format.html { redirect_to #shipping_address, notice: "Shipping address was successfully updated." }
format.json { render :show, status: :ok, location: #shipping_address }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #shipping_address.errors, status: :unprocessable_entity }
end
end
end
# DELETE /shipping_addresses/1 or /shipping_addresses/1.json
def destroy
#shipping_address.destroy
respond_to do |format|
format.html { redirect_to shipping_addresses_url, notice: "Shipping address was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_shipping_address
#shipping_address = ShippingAddress.find(params[:id])
end
# Only allow a list of trusted parameters through.
def shipping_address_params
params.require(:shipping_address).permit(:address_line1, :address_line2, :city, :state, :country, :client_id)
end
end
Behavior of the Application
The application accepts the entry of the client form and it manipulates the model for the shipping address; however, the only entry in the table on each row is the client_id value for the client foreign key. It is not committing the other components of the hash into the table.
Screen Display
Things Tried
I've tried the application posted on GitHub at stevepolitodesign/rails-nested-form-app.
I've tried a suggestion made from a similar post on rails forum: difficulties-with-nested-form-implementation-rails-6-1-3/78776/3.
I've gone through as much documentation as I can track down on the standard rails guides for nested forms.
Results from all of these did not yield good results. Item # 1 was a decent app in terms of the pathway it takes; however, when you are using bootstrap it does not seem to work. It could be that the code there has to be modified some to allow that functionality. So far, any posts made for a request regarding bootstrap with that design have not yielded fruit.
Scope
I'm looking to understand the problem that is happening and/or find a better way to accomplish this function that cooperates well with Bootstrap use.

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

HABTM Association Build

I need propagate this values in :departaments_products table: , but I received the error:
I'm using Rails 4
NoMethodError in Products#new
undefined method `departament_id' for #<Product:0x007f916d35d648>
view.html.erb:
<%= form_for(#product) do |f| %>
<% if #product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% #product.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>
<div class="field">
<%= f.label :price %><br>
<%= f.text_field :price %>
</div>
<%= f.collection_select(:departament_id, Departament.all, :id, :name, {:include_blank => true}) %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Products_controller:
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
#product = Product.find( params[:id] )
end
# GET /products/new
def new
#product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Produto criado com sucesso' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: #product }
else
format.html { render :edit }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:name, :price)
end
end
Models:
class Departament < ActiveRecord::Base
has_and_belongs_to_many :products
end
class Product < ActiveRecord::Base
has_and_belongs_to_many :departaments
end
Migration:
class AddProductsAndDepartaments < ActiveRecord::Migration
def change
create_table :departaments_products do |t|
t.references :product, :departament
end
end
end
As its a HABTM association, logically you should be selecting multiple departament_ids for a single product. That said, you should include multiple: true option in the collection_select for departament_ids (Notice departament_ids in plural) in your view code:
<%= f.collection_select(:departament_ids, Departament.all, :id, :name, {include_blank: true}, {multiple: true}) %>
Currently, you are accessing it as departament_id (Notice singular) BUT as per HABTM association you get a method named departament_ids (Notice plural) and NOT departament_id which is why you receive error as NoMethodError in Products#new undefined method 'departament_id'
Once you are done with this change, you need to permit the departament_ids field in ProductsController as below:
def product_params
params.require(:product).permit(:name, :price, :departament_ids => [])
end
:departament_ids => [] is used because multiple selection is allowed for departament_ids and so you would receive it as an Array in params hash upon form submission.
Try departament_ids
For has_many => departament_ids
For has_one => departament_id

acts_as_taggable issue - Everything looks almost fine

I have just followed step by step this other question, but my app is still giving me some errors regarding tagging (rails 4)
Error that Im experiencing is: Desktop/hack/app/controllers/jacks_controller.rb:85: syntax error, unexpected end-of-input, expecting keyword_end end ^
I have already re-intended as suggested in the chat, but nothing changed.
Code for reference
I have no associations between my models, (in the link that I have referred, there are associations)
jack form
<%= form_for(#jack) do |f| %>
<% if #jack.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#jack.errors.count, "error") %> prohibited this jack from being saved: </h2>
<ul>
<% #jack.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :tag_list, "Tags (separated by comma)" %><br>
<%= f.text_field :tag_list %>
</div>
<div class="field">
<%= f.label :picture %><br>
<%= f.text_field :picture %>
</div>
<div class="actions">
<%= f.submit %>
jack.rb
class Jack < ActiveRecord::Base
acts_as_taggable_on :tags
end
Routes
Rails.application.routes.draw do
get 'tagged/index'
root :to => redirect('/jacks')
get 'about' => "about#info"
get 'submit' => "jacks#create"
resources :jacks
match 'tagged', to: 'jacks#tagged', :as => 'tagged', via: 'get'
resources :users
jack active helper
module JacksHelper
include ActsAsTaggableOn::TagsHelper
end
And controller
class JacksController < ApplicationController
before_action :set_jack, only: [:show, :edit, :update, :destroy]
# GET /jacks
# GET /jacks.json
def index
if params [:tag]
#jacks = Jack.tagged_with(params[:tag])
else
#jacks = Jack.all
end
# GET /jacks/1
# GET /jacks/1.json
def show
end
# GET /jacks/new
def new
#jack = Jack.new
end
# GET /jacks/1/edit
def edit
end
# POST /jacks
# POST /jacks.json
def create
#jack = Jack.new(jack_params)
respond_to do |format|
if #jack.save
format.html { redirect_to #jack, notice: 'Jack was successfully created.' }
format.json { render :show, status: :created, location: #jack }
else
format.html { render :new }
format.json { render json: #jack.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /jacks/1
# PATCH/PUT /jacks/1.json
def update
respond_to do |format|
if #jack.update(jack_params)
format.html { redirect_to #jack, notice: 'Jack was successfully updated.' }
format.json { render :show, status: :ok, location: #jack }
else
format.html { render :edit }
format.json { render json: #jack.errors, status: :unprocessable_entity }
end
end
end
# DELETE /jacks/1
# DELETE /jacks/1.json
def destroy
#jack.destroy
respond_to do |format|
format.html { redirect_to jacks_url, notice: 'Jack was successfully destroyed.' }
format.json { head :no_content }
end
end
def tagged
if params[:tag].present?
#jacks = Jack.tagged_with(params[:tag])
else
#jacks = Jack.postall
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_jack
#jack = Jack.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def jack_params
params.require(:jack).permit(:title, :description, :picture, :tag_list)
end
end
index method is missing an 'end'
def index
if params[:tag]
#jacks = Jack.tagged_with(params[:tag])
else
#jacks = Jack.all
end
end

Updating an existing entry in my database isn't working

I'm trying to use a list of clients that have been created from my client model in my new model called Jobs.
Basically. A user should be able to view a list of jobs that are currently assigned to any one client and then drill down into further information.
I have inserted a new column into my jobs database called client_id and have inserted the following code in my _form view to be able to see a drop down list of all the clients
<%= f.label :client_id %><br />
<%= f.collection_select :client_id, #clients, :id, :name, :prompt =>
"Select" %>
However. When I hit submit it tries to POST it to jobs/new which according to my resource route. Doesn't exist.
I have also inserted some dummy data into the database and though that is showing up fine when I try to edit it. Pressing save will not do anything to the record.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"0ZVYpM9vTgY+BI55Y9yJDwCJwrwSgGL9xjHq8dz5OBE=", "job"=>{"name"=>"Sample Monthly", "client_id"=>"2", "frequency"=>"Monthly", "owner"=>"Me"}, "commit"=>"Save Job", "id"=>"1"}
Job Load (0.3ms) SELECT "jobs".* FROM "jobs" WHERE "jobs"."id" = ? LIMIT 1 [["id", "1"]]
(0.1ms) begin transaction
(0.5ms) UPDATE "jobs" SET "name" = 'Sample Monthly', "frequency" = 'Monthly', "updated_at" = '2012-05-12 17:04:23.818967' WHERE "jobs"."id" = 1
(108.3ms) commit transaction
Redirected to http://localhost:3000/jobs/1
Here's my controller..
class JobsController < ApplicationController
before_filter :load_clients, :only => [ :new, :create, :edit ]
def index
#job = Job.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #job }
end
end
def new
#job = Job.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #Job }
end
end
def create
#job = Job.new(params[:job])
respond_to do |format|
if #job.save
format.html { redirect_to #job, notice: 'Job was successfully created.' }
format.json { render json: #job, status: :created, location: #job }
else
format.html { render action: "new" }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
def show
#job = Job.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #job }
end
end
def update
#job = Job.find(params[:id])
respond_to do |format|
if #job.update_attributes(params[:job])
format.html { redirect_to #job, notice: 'Job was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #job.errors, status: :unprocessable_entity }
end
end
end
private
def load_clients
#client = Client.find(:all)
end
end
I suppose to get this working is a relatively easy fix but this is my forst Rails app and i'm not sure where to start.
Edit:
As requested. Here is my jobs form:
<%= form_for(:job) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :client_id %><br />
<%= f.collection_select :client_id, #client, :id, :name, :prompt =>
"Select" %>
</div>
<div class="field">
<%= f.label :frequency %><br />
<%= f.text_field :frequency %>
</div>
<div class="field">
<%= f.label :owner %><br />
<%= f.text_field :owner %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Edit2: Here's my Job model.
class Job < ActiveRecord::Base
belongs_to :clients
end
Try replace :job with #job in your form.
And also looks like you are missing edit action in your controller.

Resources