Search code examples
ruby-on-railsgrouped-collection-select

RoR nested optgroups


I have successfully implemented the dynamic select menus for city and area models in my app.

now I have the following models:

class Pet < ActiveRecord::Base
  belongs_to :pet_type
  belongs_to :pet_category
  belongs_to :pet_breed
end

class PetType < ActiveRecord::Base
  has_many :pet_categories, through: :pet_type_categories
  has_many :pet_type_categories
end

class PetCategory < ActiveRecord::Base
  has_many :pet_types, through: :pet_type_categories
  has_one :pet_type_category
end

class PetTypeCategory < ActiveRecord::Base
  belongs_to :pet_type
  belongs_to :pet_category
  has_many :pet_breeds
end

class PetBreed < ActiveRecord::Base
  belongs_to :pet_type_category
  belongs_to :pet_Type
  belongs_to :pet_category
end

migrations:

class CreatePetTypes < ActiveRecord::Migration
  def change
    create_table :pet_types do |t|
      t.string :name

      t.timestamps
    end
  end
end

class CreatePetCategories < ActiveRecord::Migration
  def change
    create_table :pet_categories do |t|
      t.string :name

      t.timestamps
    end
  end
end

class CreatePetTypeCategories < ActiveRecord::Migration
  def change
    create_table :pet_type_categories do |t|
      t.references :pet_type, index: true
      t.references :pet_category, index: true

      t.timestamps
    end
  end
end

class CreatePetBreeds < ActiveRecord::Migration
  def change
    create_table :pet_breeds do |t|
      t.string :name
      t.references :pet_type_category, index: true

      t.timestamps
    end
  end
end

The pet_type_category table is a join table for pet_types that share the same pet_categories.

So my question is how do I create 3 dynamic select menus of pet_type, pet_category and pet_breed in the create form?

Thanks

Edit: I managed to get the pet type collection_select and pet category grouped_collection_select done once I updated the relationships, now the 3rd one (pet breed) is what I'm stuck at..


Solution

  • I understand now after a bit of a research that it is not possible to have nested groups though surely It should be possible using some kind of helper, however for a lack of a better solution, I added to the PetTypeCategory model:

      def pet_type_category_names
        "#{self.pet_type.name} #{self.pet_category.name}"   
      end 
    

    and in my view now I have:

    <div class="field">
      <%= f.collection_select :pet_type_id, PetType.all, :id, :name, {prompt: "Choose your pet's type"} %>
    </div>
    
    <div class="field">
      <%= f.grouped_collection_select :pet_category_id, PetType.all, :pet_categories, :name, :id, :name, {prompt: "Choose your pet's category"} %>
    </div>
    
    <div class="field">
      <%= f.grouped_collection_select :pet_breed_id, PetTypeCategory.all, :pet_breeds, :pet_type_category_names, :id, :name, {prompt: "Choose your pet's breed"} %>
    </div>
    

    so for the 3rd select instead of having:

    Dog
      Small
        Breed
    

    I have:

    Dog Small
      Breed