I have the following scenario:
class Product < ActiveRecord::Base
belongs_to :categories
end
class Category < ActiveRecord::Base
has_many :products
end
Categories table has 2 level nesting, for example. Main category is 'Men', sub-category is 'Accessories' and sub-sub-category is 'Watches'.
Now when user creates new product he must choose category(only main category is required, but he can also chose sub and sub-sub category optional).
My idea is this: I created 3 different select boxes with same name "product[category_id]", so only the last selected value will be sent to the server through params[:product][:category_id].
<div class="col-md-2 main-category">
<small> Main category? required </small>
<%= f.select :category_id,
Category.where('category_id IS ?', nil).collect {|c| [c.name, c.id]},
{ include_blank: "Select category..." },
id: 'main-category', class: 'form-control' %>
</div>
<div class="col-md-2 category-level-1">
<small> What type? optional </small>
<%= f.select :category_id, {}, {}, class: 'form-control' %>
</div>
<div class="col-md-2 category-level-2">
<small> What type? optional </small>
<%= f.select :category_id, {}, {}, class: 'form-control' %>
</div>
2nd(sub-categories) and 3rd(sub-sub-categories) are initial empty ({}, {}) and hidden through CSS(display: none) and will be populated through Ajax call.
$('#main-category, .category-level-1 > select').change(function() {
var selectBox = this.id;
var selectedValue = $(this).val();
var url = '/categories/' + selectedValue + '/subcategories';
$.get(url, function(data) { createSelect(data, selectBox); });
});
function createSelect(data, selectBox) {
var $currentSelect = null;
if (selectBox == 'main-category') {
$('.category-level-1').show();
$('.category-level-2').hide();
$('.category-level-1 > select').find('option').remove();
$currentSelect = $('.category-level-1 > select');
}
else {
$('.category-level-2').show();
$('.category-level-2 > select').find('option').remove();
$currentSelect = $('.category-level-2 > select');
}
$currentSelect.append('<option selected disabled>Select Category...</option>');
for(var i=0; i<data.length; i++) {
$currentSelect.append('<option value="' + data[i].id + '">' + data[i].name +
'</option>');
}
}
Where Ajax call is sent to following route (categories controller)
def subcategories
id = params[:id]
@subcategories = Category.where('category_id = ?', id)
render json: @subcategories
end
So for final result i have following:
First of all, is it normal to have different inputs in one form with same names created manually like I did in this example? For some reason, it seem like 'code-smell' to me. I'm relatively new to Rails, so I wanted to ask if I am violating some good practices with this code. Can you suggest better ways of achieving the same results?