0

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
Kirti Thorat
  • 52,578
  • 9
  • 101
  • 108
  • 1
    I guess you need to permit the `department_id` in the `product_params`.Change it to `params.require(:product).permit(:name, :price,:department_id)`. – Pavan Jun 25 '14 at 16:15

2 Answers2

1

Try departament_ids

For has_many => departament_ids

For has_one => departament_id

1

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.

Kirti Thorat
  • 52,578
  • 9
  • 101
  • 108
  • One doubt.By having `t.references :product, :departament` will the OP have `departament_id` or `departament_ids`? – Pavan Jun 25 '14 at 16:49
  • Notice the table name, `:departaments_products` its the join table that is why `department_ids` (M-M association). `products` table doesnt have any reference key `department_id` so that is obviously going to result in error. – Kirti Thorat Jun 25 '14 at 16:52
  • Hmm,It makes sense now.Is my answer is partially correct or totally wrong? – Pavan Jun 25 '14 at 16:56
  • Ok, but my sql table not receive this propagation.. :( – user3251174 Jun 25 '14 at 17:00
  • @Pavan..with OP's current code, with single selection, your answer will only work if you make it `departament_ids` in view and controller code. – Kirti Thorat Jun 25 '14 at 17:03
  • @user3251174 Can you share the server logs generated upon form submission. Add it to the question. – Kirti Thorat Jun 25 '14 at 17:03
  • Forgot, my mistake haha. @KirtiThorat, very thanks! Now it's works.. :) Thanks – user3251174 Jun 25 '14 at 17:17