Reputation: 258
I have a select tag , which shows some categories in a drop down fashion also using Select2
<%= category.select :parent_id, nested_set_options(Category, @category) {|i| if !(i.depth >= 2)
"#{i.root.name if !i.parent_id.nil? } #{'>' unless !i.parent_id} #{i.name}"
end
} , {include_blank:true} , class: 'select2 form-control'%>
This select is a prompt for when you create a new Category in case you decide to nest it under a parent.
The reason i use this code is because i want to only give the Admin the choice of nesting till depth=3
so only Parent -> Kid -> GrandKid
The code works pretty well but when a value is decided not to be shown , i get a white space (which is a lot smaller) but still the user can choose it.
Is there any way i can exclude those values that fall out of this condition?
The code that solves this question is an interpretation of GoGoCarl's great answer , just because i had a small problem with reject_if
So i just turned the whole thing around and ended up with this:
<%= category.select :parent_id, nested_set_options(Category, @category) {|i|
if !(i.depth >= 2)
"#{i.root.name if !i.parent_id.nil? } #{'>' unless !i.parent_id} #{i.name}"
end
}.select { |i|
!i[0].nil? || !i[0].blank?
} , {include_blank:true , include_hidden:false} , class: 'select2 form-control'%>
Upvotes: 0
Views: 131
Reputation: 2519
Need to get a little fancy but it can be done.
First, the select helper pretty much just expects an Array of Arrays, so something like:
[ ["Apples", 1], ["Oranges", 2], ["Bananas", 3] ]
And that, in the end, if what nested_set_options
is returning. So, ultimately, you can manipulate that Array of Arrays that is returned by nested_set_options
to suit your needs. Example (added whitespace and indentation for clarity):
<%= category.select :parent_id,
nested_set_options(Category, @category) { |i|
if !(i.depth >= 2)
"#{i.root.name if !i.parent_id.nil? } #{'>' unless !i.parent_id} #{i.name}"
end
}.reject_if { |i|
i[0].nil? || i[0].strip.blank?
},
{include_blank:true},
class: 'select2 form-control'%>
The key here is to check the Array of Arrays to see if the display text (the first element of each Array) is blank. Because you are actually returning " "
as your string, this check removes whitespace, then sees if the resulting string is blank. If so, it removes that element. The final Array will only contain those elements whose display contains some non-blank characters.
You could even extend that further to add your administrative user check, and reject certain options in cases where the user is an admin.
Alternatively, you could also look into overriding the move_possible?
method for Category
. However, I think your business logic is too complicated to go that route and may introduce some anti-patterns into your model. But, it an option and would also accomplish the task.
Hope that helps!
Upvotes: 1