I have an Active panel with a dependent select i.e. the choice on the first dropdown select impacts what appears in the second drop-down.
All was working perfectly well a few months ago but i just realized yesterday it is not working any more.
I managed to find what cause the error: if I remove the eager loading ("include"), then it works again.
NOT WORKING: (current version):
@deal_subsectors = DealSector.find(params[:deal_sector_id],
include: :deal_subsectors).dealsubsectors
I get this error (form chrome dev tools's Console)
GET http://localhost:3000/admin/deals/deal_subsectors_by_deal_sector?deal_sector_id=2 404 (Not Found)
send @ jquery.js?body=1:9660
jQuery.extend.ajax @ jquery.js?body=1:9211
jQuery.(anonymous function) @ jquery.js?body=1:9357
jQuery.extend.getJSON @ jquery.js?body=1:9340
update_deal_subsector @ active_admin.js?body=1:19
(anonymous function) @ active_admin.js?body=1:12
jQuery.event.dispatch @ jquery.js?body=1:4666
elemData.handle @ jquery.js?body=1:4334
ListPicker._handleMouseUp @ about:blank:632
WORKING, when I remove "include" / eager loading :
@deal_subsectors = DealSector.find(params[:deal_sector_id]).deal_subsectors
It works perfecty in that case.
But I really want to eager load deal subsectors so I wonder what is causing this error, what has changed since it was working. I have a few assumptions but can't find the culprit.
Did Rails 4 change the way I should use find(params[:id]..) or the way i should use eager loading
did active Admin change the way it handles eager loading: maybe it only works on index and not on edit pages...
did turbolinks now on Rails 4 change the way i must eager load?
Here's the code:
- on Active Admin
ActiveAdmin.register Deal do
# controller for the multi-select sector/subsector in the form
# does 2 things at same time: creates method and automatically defines the route of the method defined in controller
if params[:deal_sector_id] # pass the id
@deal_subsectors = DealSector.find(params[:deal_sector_id], include: :deal_subsectors).dealsubsectors
else
@deal_subsectors = []
end
render json: @deal_subsectors
end
end
- the form with the 2 dependent selects
form do |f|
f.inputs "Client" do
f.input :deal_sector_id,
:label => "Select industry:",
:as => :select,
:prompt => true,
:collection => DealSector.order("name").all.to_a
f.input :deal_subsector_id,
:label => "Select subindustry:",
:as => :select,
:prompt => true,
:collection => DealSubsector.order("name").all.to_a
end
end
- the javascript powering it:
// for edit page
var deal_subsector = { };
$(document).ready(function() {
$('#deal_deal_sector_id').change(function() {
update_deal_subsector();
});
});
function update_deal_subsector() {
deal_sector_id = $('#deal_deal_sector_id').val(); //get the value of sector id
url = '/admin/deals/deal_subsectors_by_deal_sector?deal_sector_id=' + deal_sector_id; //make a query to the url passing the deal sector id as a parameter
$.getJSON(url, function(deal_subsectors) {
console.log(deal_subsectors);
$('#deal_deal_subsector_id').html("") //just blanks the id, blank it before populating it again if sector changes
for( i = 0; i < deal_subsectors.length; i++) {
console.log(deal_subsectors[i]);
$('#deal_deal_subsector_id').append("<option value=" + deal_subsectors[i].id + ">" + deal_subsectors[i].name + "</option>")
};
}); //pass the url and function to get subsector ids and all we get is assigned to the variable subsector_id
};
// for index page (filters)
$(document).ready(function() {
$('#q_deal_sector_id').change(function() {
update_deal_subsector_filter();
});
});
function update_deal_subsector_filter() {
deal_sector_id = $('#q_deal_sector_id').val(); //get the value of sector id
url = '/admin/deals/deal_subsectors_by_deal_sector?deal_sector_id=' + deal_sector_id; //make a query to the url passing the deal sector id as a parameter
$.getJSON(url, function(deal_subsectors) {
console.log(deal_subsectors);
$('#q_deal_subsector_id').html("") //just blanks the id, blank it before populating it again if sector changes
for( i = 0; i < deal_subsectors.length; i++) {
console.log(deal_subsectors[i]);
$('#q_deal_subsector_id').append("<option value=" + deal_subsectors[i].id + ">" + deal_subsectors[i].name + "</option>")
};
}); //pass the url and function to get subsector ids and all we get is assigned to the variable subsector_id
};
ADDED file
class DealSector < ActiveRecord::Base
has_many :deal_subsectors
end
class DealSubsector < ActiveRecord::Base
belongs_to :deal_sector, :foreign_key => 'deal_sector_id'
end
When you call ActiveRecord::find
– it means you are expecting to get a one, single model from the DB.
Then, you referring to this model and call dealsubsectors
– I assume it's has_many
relation to your model. It will produce 2 queries: first to fetch original DealSelector
, second – all related DealSubsectors
.
There's nothing you can optimise (unless you dealsubsectors
is a custom method in your model, not the relation).
If you see that something hits your DB with queries – you have to look in another place. Say, your form – do you display only one Client per form? If not, it will iterate and fetch all DealSector and DealSubsector again for every new client. Try to provide more code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With