Search code examples
ruby-on-railsruby-on-rails-3ruby-on-rails-4ruby-on-rails-3.2ancestry

Dynamic Select with ancestry


My application using ancestry gem.

class Location < ActiveRecord::Base
 has_ancestry :cache_depth => true
 has_many :posts
end

class User < ActiveRecord::Base
 belongs_to :location
end

I created some random Location,

  • Alaska
  • California
    • Los Angeles
    • Fresno
      • Cincotta (Fresno)
      • Hammond (Fresno)
      • Melvin (Fresno)

My question if user sign up form if User select California, display child Los Angles and Fresno, after select Fresno then display it's child.

I got javascript tutorial for Dropdown list http://www.plus2net.com/javascript_tutorial/dropdown-list-demo.php

How is possible work with ancestry gem?


Solution

  • Nested

    Firstly, if you wanted to keep them all in a single dropdown, we created the following helper which achieves it for you:

    enter image description here

    #app/helpers/application_helper.rb
    def nested_dropdown(items)
        result = []
        items.map do |item, sub_items|
            result << [('- ' * item.depth) + item.name, item.id]
            result += nested_dropdown(sub_items) unless sub_items.blank?
        end
        result
    end
    

    This will allow you to call:

    <%= f.select(:category_ids, nested_dropdown(Category.all.arrange), prompt: "Category", selected: @category ) %>
    

    This will give you the ability to call a single dropdown, which has been nested according to your ancestry associations

    --

    Ajax

    If you want to have double dropdown boxes, you'll probably have to implement an ajax function to pull the required data each time the initial dropdown changes:

    #config/routes.rb
    resources :categories do
        get :select_item
    end
    
    #app/assets/javascripts/application.js
    $("#first_dropdown").on("change", function(){
       $.ajax({
           url: "categories/"+ $(this).val() + "/select_item",
           dataType: "json",
           success: function(data) {
              //populate second dropdown
           }
       })
    });
    
    #app/controllers/categories_controller.rb
    Class CategoriesController < ApplicationController
        respond_to :json, only: :select_item
    
        def select_item
           category = @category.find params[:category_id]
           respond_with category.children
        end
    end