How to use ActiveAdmin on models using has_many through association?

44,729

Solution 1

For 1)

show do
  panel "Patients" do
    table_for physician.appointments do
      column "name" do |appointment|
        appointment.patient.name
      end
      column :appointment_date
    end
  end
end

For 2)

form do |f|
  f.inputs "Details" do # physician's fields
    f.input :name
  end

  f.has_many :appointments do |app_f|
    app_f.inputs "Appointments" do
      if !app_f.object.nil?
        # show the destroy checkbox only if it is an existing appointment
        # else, there's already dynamic JS to add / remove new appointments
        app_f.input :_destroy, :as => :boolean, :label => "Destroy?"
      end

      app_f.input :patient # it should automatically generate a drop-down select to choose from your existing patients
      app_f.input :appointment_date
    end
  end
end

Solution 2

In answer tomblomfield follow up question in comments:

Try the following in your AA ActiveAdmin.register Model do block:

  controller do
    def scoped_collection
      YourModel.includes(:add_your_includes_here)
    end
  end

This should lazy load all your associations for each index page in a separate query

HTH

Solution 3

It should solve the N+1 query problem.

show do
  panel "Patients" do
    patients = physician.patients.includes(:appointments)
    table_for patients do
      column :name
      column :appointment_date { |patient|    patient.appointments.first.appointment_date }
    end
  end
end

Solution 4

It's work for me (with chosen)

permit_params category_ids: []

form do |f|
   inputs 'Shop' do
     input :category_ids, collection: Category.all.collect {|x| [x.name, x.id]}, as: :select, multiple: true, input_html: { class: "chosen-input",  style: "width: 700px;"}
    end
   f.actions
end
Share:
44,729
Victor Lam
Author by

Victor Lam

Updated on March 20, 2021

Comments

  • Victor Lam
    Victor Lam about 3 years

    I am using ActiveAdmin gem in my project.

    I have 2 models using has_many through association. The database schema looks exactly the same as the example in RailsGuide. http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association has_many through association
    (source: rubyonrails.org)

    How can I use ActiveAdmin to ...

    1. show appointment date of each patient in physicians page?
    2. edit appointment date of each patient in physicians page?

    Thanks all. :)

  • tomblomfield
    tomblomfield over 12 years
    I'm doing a similar thing, but it ends up with a SQL nightmare. Each call to appointment.patient generates another SQL query.. standard n+1 query problem. Has anyone found a way of doing the equivalent of ActiveRecord's eager loading? Eg .includes(:patient)
  • Awea
    Awea about 12 years
    I have some trouble with your solution. The _destroy input won't work in my case
  • PeterWong
    PeterWong about 12 years
    there could be many reasons and "won't work" isn't enough for me to know what exactly goes wrong. I am sorry about that.
  • Greg
    Greg almost 12 years
    Quick Tip: Make sure to include accepts_nested_attributes_for in the Patients model accepts_nested_attributes_for :appointments
  • Robin Pyon
    Robin Pyon over 11 years
    To anyone having similar issues to @Awea and being unable to destroy added items, ensure that :allow_destroy is enabled for nested attributes, see related answer
  • chech
    chech almost 11 years
    in case anyone is interested in the index page: eileenbuildswithrails.com/posts/…
  • monfresh
    monfresh almost 11 years
    scoped_collection is not called on the show view, so this won't solve tomblomfield's issue, since he was talking about N+1 queries on the show view. I'm running into this too, and haven't found a solution.
  • Mohd Anas
    Mohd Anas over 10 years
    Can we use the same with HABTM associations?
  • Малъ Скрылевъ
    Малъ Скрылевъ almost 10 years
    Will the approach allow update each appointment's data separately without a whole page reload?
  • PeterWong
    PeterWong almost 10 years
    @МалъСкрылевъ no, that code generates form fields for appointments, just a part of the whole form. So have to submit altogether.
  • Tashows
    Tashows over 6 years
    I think what you are looking for is def find_resource, where you could run Foo.includes(:bars).find(params[:id])
  • A moskal escaping from Russia
    A moskal escaping from Russia over 5 years
    Replace Category.all.collect {|x| [x.name, x.id]} with Category.pluck(:name, :id) whenever you can.
  • obenda
    obenda about 3 years
    Correction for 2) - it should be : if !app_f.object.id.nil?
  • obenda
    obenda about 3 years
    In the case of using strong parameters, you should define the above in the active admin file.