Grouped Select in Rails

Grouped Select in Rails

Edit

Correction, since you're using Arrays you'll need grouped_options_for_select

Example:

grouped_options = [
['Group 1',
["Item 1", "Item 2", "Item 3"]],
['Group 2',
["Item 1", "Item 2", "Item 3", "Item 4"]]
]
grouped_options_for_select(grouped_options)

Prints the following:

<optgroup label="Group 1">
<option value="Item 1">Item 1</option>
<option value="Item 2">Item 2</option>
<option value="Item 3">Item 3</option>
</optgroup>
<optgroup label="Group 2">
<option value="Item 1">Item 1</option>
<option value="Item 2">Item 2</option>
<option value="Item 3">Item 3</option>
<option value="Item 4">Item 4</option>
</optgroup>

Note that you have to provide your own select tags to wrap this. There is no select function that will do grouping for you, just this method.

You should get over your reticence. The Rails Way (tm) to do what you ask is to use select_tag with grouped_options_for_select:

<%= select_tag "foo[bar]", 
grouped_options_for_select(@bars) %>

This is what happens when you go off the beaten path with Rails. :)

Here's a reference I just found on google:

http://www.ruby-forum.com/topic/185407

Option Group in select tag using rails

I have added one field called type in template model.Type field has radio button built_in and custom so when I create one template we choose radio button of that type.
Now, my dropdown for option select is look like this:

<%= select_tag :template ,grouped_options_for_select([['Built-In templates',  @built_in.collect {|v| [ v.name, v.id ] }],['Custom',  @custom.collect {|v| [ v.name, v.id ] }]]),{:prompt => t("please_select"),:class=>"form-control m-b-sm required"}%> 

How can I have a multiple grouped select with simple_form?

I figured it out on my own.

This produced the correct output:

<%= f.association :tags, as: :grouped_select, collection: TagGroup.all, group_method: :tags, input_html: { :multiple => true } %>

The key part being:

input_html: { :multiple => true }

Rails 4 JOIN GROUP BY and SELECT

Would the following work for you?

User.joins(:orders)
.select("users.*, max(orders.created_at) as most_recent, count(orders.id) as orders_count")
.group('users.id')

Taking the max of order.created_at should give you the date of the most recent order. I don't think you want to have your select as part of has_many orders, since you're looking for a list of users, not a list of orders. If you'd a method that returns this active record query, assuming you'll use it more than once, you can add the following to your User model.

def self.with_order_info
self.joins(:orders)
.select("users.*, max(orders.created_at) as most_recent, count(orders.id) as orders_count")
.group('users.id')
end

And then, you can call that method anywhere using:

@users = User.with_order_info

As a further note (to be 100% clear), you should keep your association to orders as:

has_many :orders

Setting up grouped options for the f.select form helper

You can do it mapping the collection and then grouping it by a value in the array, for example

<%= f.select(:location_id, grouped_options_for_select(Location.all.map{|l| [l.name, l.category_name, l.id]}.group_by { |c| c[1] }), {include_blank: "Select one..."}, {:class => 'grouped_select',id:"location_grouped"}) %>

This will create the select, grouped by category_name.

Use grouped_collection_select to group a model by enum

The grouped_collection_select method is not the best tool for your needs because it really deals with associated records of a main record, whereas you, if I understand correctly, simply want to add all Conversation records to a select tag, but grouped by its attribute, not association.

You can easily construct the grouped options manually, though. I'd put this code into a helper not to clutter the view template too much:

# app/helpers/conversations_helper.rb
module ConversationsHelper

def grouped_conversations_options_for_select(selected_conversation_id = nil)
options = {}
Conversation.statuses.keys.each do |status|
options[status] = Conversation.with_status(status).pluck(:name, :id)
end
grouped_options_for_select(options, selected_conversation_id)
end

end

# app/view/show.html.erb
<%= select_tag :conversation_id, grouped_conversations_options_for_select(params[:conversation_id]) %>

The helper first constructs a hash with the following structure:

{
active: [[ conversation.id, conversation.name ], [...]],
archived: [[ conversation.id, conversation.name ], [...]],
}

This hash can be then passed to the grouped_options_for_select which converts it to the <OPTIONS> tags including proper <OPTGROUP> tags. The helper also supports setting the currently selected value in the select options. Its output is then passed to the select tag in the view template.

For the helper to work, you also need to add the following scope to the Conversation model:

# app/models/conversation.rb
scope :with_status, ->(status) { where(status: statuses[status]) }

How do I get grouped_collection_select to display within form.select?

For anybody else interested, the below syntax gave me the expected HTML output.

<%= form.grouped_collection_select(:category_id, Category.top_level, :sub_categories, :name, :id, :name,
{ prompt: 'Select a category'},
{ id: :product_category }) %>

Rails - grouped_options_for_select

The grouped_options_for_select method indeed is the correct one.
Since you haven't provided code, this should result in the grouped options you want:

grouped_options_for_select [['Fruits',  @fruits.collect {|v| [ v.name, v.id ] }],
['Veggies', @veggies.collect {|v| [ v.name, v.id ] }],
['Junk', @junk_food.collect {|v| [ v.name, v.id ] }]]

Which can be used to create the dropdown:

select_tag 'Food', grouped_options_for_select(...)

or with form_helper:

f.select :food_attribute, grouped_options_for_select(...)

Rails generate select with both options and option groups

This is hard to answer precisely without knowing what the data looks like, but I'm going to guess that you have something like this:

@grouped_options = [
["Some nil value label"],
["Option one", "1"],
["Option Group 1",
[
["Option one in group 1", "1:1"],
["Option two in group 1", "1:2"],
]
],
["Option Group 2",
[
["Option one in group 2", "2:1"],
["Option two in group 2", "2:2"],
]
],
]

With that, you have a couple options. In plain ERB, you can do it like this:

<%= select "thing", "some_attr" do %>
<% @grouped_options.each do |label, value_or_options| %>
<% if Array === value_or_options %>
<%= tag.optgroup options_for_select(value_or_options), label: label %>
<% else %>
<%= tag.option label, value: value_or_options %>
<% end %>
<% end %>
<% end %>

Personally, though, I would write a helper. The Enumerable#chunk method splits an array into runs of values that return the same thing for the given block, making it easy to separate the grouped from the non-grouped items so we can use grouped_options_for_select and options_for_select, respectively:

def ungrouped_and_grouped_options_for_select(choices, selected_key = nil)
capture do
choices
.chunk {|_, choice_or_group| Array === choice_or_group }
.each do |is_group, choices_or_grouped_choices|
if is_group
concat grouped_options_for_select(choices_or_grouped_choices, selected_key)
else
concat options_for_select(choices_or_grouped_choices, selected_key)
end
end
end
end

You could then use it this:

<%= select "thing", "some_attr" do %>
<%= ungrouped_and_grouped_options_for_select(@grouped_options) %>
<% end %>

You can see both of these approaches in action on repl.it: https://repl.it/@jrunning/UnacceptablePlaintiveServer (see views/tests/index.html.erb, controllers/tests_controller.rb, and helpers/application_helper.rb).



Related Topics



Leave a reply



Submit