Skip to main content

has_many through association with collection_check_boxes question not working at create action (kinda)

Rails • Asked by DC

Testing has_many through association, I want to do that Product has many Category, and Product has many Certificate. Both associations are two-way, and the setups of them, as below, are pretty much identical.

During the new product creation phase, category_ids are passed through and it works fine; however, what I found odd is that if I only select certificates, it fails. I get the following error message saying it's invalid.

#<ActiveModel::Errors:0x007fcb651d32a0 @base=#<Admin::Product id: nil, name: nil, model: "1", country: "1", document: "1", inquiry: nil, permalink: "pro1", feature: nil, specification: nil, dimensions: nil, description: nil, created_at: nil, updated_at: nil>, @messages={ :certificates=>["translation missing: en.activerecord.errors.models.admin/product.attributes.certificates.invalid"]}, @details={ :certificates=>[{:error=>:invalid}]}>

Also, if I skip selecting certificates during creataion and later add that after the new product is created, it works.

I looked through the codes over and over but no luck figuring out why.

Product model

class Product < ApplicationRecord

  validates :name, :model, :country, :permalink, presence: true 
  validates :permalink, uniqueness: true

  has_many :category_product_relations, dependent: :destroy
  has_many :categories, through: :category_product_relations
  has_many :certificate_product_relations, dependent: :destroy
  has_many :certificates, through: :certificate_product_relations

  extend Mobility
  translates :name, type: :string, locale_accessors: [:en, :"zh-TW"]
  translates :feature, :specification, :dimensions, :description, type: :text, locale_accessors: [:en, :"zh-TW"]

end

Category model

class Category < ApplicationRecord

  validates :name_zh_tw, presence: true, uniqueness: true
  validates :permalink, presence: true, uniqueness: true

  has_many :category_product_relations
  has_many :products, through: :category_product_relations

  extend Mobility
  translates :name, type: :string, locale_accessors: [:en, :"zh-TW"]

end

CategoryProductRelation

class CategoryProductRelation < ApplicationRecord
  belongs_to :category
  belongs_to :product
end

Certificate model

class Certificate < ApplicationRecord

  validates :name_zh_tw, :image, presence: true 

  has_many :certificate_product_relations
  has_many :products, through: :certificate_product_relations

  mount_uploader :image, ImageUploader

  extend Mobility
  translates :name, type: :string, locale_accessors: [:en, :"zh-TW"]

end

CertificateProductRelation

class CertificateProductRelation < ApplicationRecord
  belongs_to :certificate
  belongs_to :product
end

Products controller

before_action :find_product, only: [:edit, :update, :destroy]
def new
    @admin_product = Admin::Product.new
    @admin_product.build_image
    @admin_product.build_metum
  end

  def create
    @admin_product = Admin::Product.new(product_params)
    if @admin_product.save
      redirect_to admin_products_path, notice: "New product created"
    else
      flash[:alert] = "Somthing Went Wrong: "
      render :new
    end
  end

  def edit
  end

  def update
    if @admin_product.update(product_params)
      redirect_to admin_products_path, notice: "Product updated"
    else
      flash[:alert] = "Somthing Went Wrong: "
      render :edit
    end
  end

    private
    def find_product
    @admin_product = Admin::Product.find_by(id: params[:id])
  end

  def product_params
    params.require(:admin_product).permit( ...omit...{category_ids: []}, {certificate_ids: []})
  end

form

<%= form_for @admin_product do |f| %>
    ----- omit -----
    <%= f.collection_check_boxes :category_ids, Category.all, :id, :name %>
    <%= f.collection_check_boxes :certificate_ids, Certificate.all, :id, :name %>
    ----- omit -----
<% end %>

Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 22,346+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.