Custom select options html attributes - ruby-on-rails

I have an "add new product page" and I have a field in the database table "jos_stockmovement", "start_week" which contains data for the year and week.
In my "Add New Product" page I have a field dropdown-list named "Start Week" which holds the year and week, for example, "2012/36".
I want to make it so past weeks can be viewed but only the current week can be selected.
Here's my code:
<td colspan="99">
<%= fld.select :start_week, options_for_select(
StockMovement.order("year DESC, week DESC").map { | val |
[ "#{ val.year }/#{ val.week }", val.id ]
},
:selected => #product.start_week
),
:class => "ddl_SW"
%>
</td>

What you want to do is to add the disabled attribute to the past week options, like
<select name="post[stock_movement]">
<option value="1">Present</option>
<option value="2" disabled="disabled">Past</option>
<option value="3" disabled="disabled">Past</option>
</select>
You can do this in Rails3 (I don't think you can in Rails2) by using options_for_select as you were trying to.
stock_movement.rb
# not sure about the scope, maybe need to put in a lambda ?
scope :option_tags, order("year DESC, week DESC").map(&:option_tag)
def before_now?
# your test to know if the thing is before today or not
end
def option_tag
["#{ stock_movement.year }/#{ stock_movement.week }",
val.id,
before_now? ? {:disabled => :disabled} : {}]
end
your_view.rb
<td colspan="99">
<%= fld.select :start_week,
options_for_select(StockMovement.option_tags,
:selected => #product.start_week),
:class => "ddl_SW" -%>
</td>
How about that? I could not test it but should be ok.

Related

Rails generate select with both options and option groups

Is it possible to generate select like:
<select>
<option value>Some nill value label</option>
<option value="1">Option one</option>
<optgroup label="Option Group 1" class="css-class-for-option-group-1">
<option value="1:1">Option one in group 1</option>
<option value="1:2">Option two in group 1</option>
</optgroup>
<optgroup label="Option Group 2" class="css-class-for-option-group-2">
<option value="2:1">Option one in group 2</option>
<option value="2:2">Option two in group 2</option>
</optgroup>
</select>
I tried to use the grouped_options_for_select, but I failed to find I way to pass both option and groups to it. Is there any way to achieve this? I am open to suggestions using SimpleForm as well.
Thanks!
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).
Assuming that the data is formatted as described by Jordan, you could also combine both 'select options' methods (options_for_select and grouped_options_for_select) by summing their return, like so:
<%= f.select :selected_ids, options_for_select([['Option 1', 1]]) + grouped_options_for_select([['Option Group 1', ['group1opt1', 11], ['group1opt2', 12]], ['Option Group 2', ['group2opt1', 21], ['group2opt2', 22]]]), {}, { class: 'class' } %>

Storing array data in jsonb field with Rails and Postgresql

Say I have a Car model in which I want to display different kinds of data. I add a data column to the table:
class AddDataToCars < ActiveRecord::Migration[5.0]
def change
add_column :cars, :data, :jsonb, null: false, default: '{}'
add_index :cars, :data, using: :gin
end
end
Then I add an accessor for a field I want to be present (extra_options):
class Car < ApplicationRecord
store_accessor :data, :wheel_count, :extra_options
validates :extra_options, presence: true
end
I make sure it's a permitted parameter in cars_controller.rb:
def car_params
params.require(:car).permit(:make, :model, :data, :wheel_count, :extra_options)
end
Now I can create a text input in my _form.html.erb partial that puts data in wheel_count like this:
<div class="field">
<%= f.label :wheel_count %>
<%= f.text_field :wheel_count %>
</div>
And it works as expected. What I then would like is a select list (multiple select) or a set of checkboxes where the selected options are stored under extra_options.
I've tried with:
<%= f.select :extra_options, options_for_select(["1", "2", "3", "4", "5"], car.extra_options), { include_blank: true }, { multiple: true } %>
which produced the following markup:
<input name="car[extra_options][]" type="hidden" value="" />
<select multiple="multiple" name="car[extra_options][]" id="car_extra_options">
<option value=""></option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
Obviously the option labels should make more sense than just 1, 2, 3, 4 and 5, but what's worse is that nothing gets stored when I submit the form.
On submission if I select 2 and 3 the parameters look like:
"extra_options"=>["", "2", "3"]
which results in the message Unpermitted parameter: extra_options so it seems like I am not allowed to put arrays in this field.
It may seem stupid to create a jsonb field just for some extra options but it would naturally also hold all sorts of other data.
So how can I create a multiple select list or preferably a set of checkboxes that saves the data correctly in the jsonb field (and of course when editing a submission shows the already selected/checked items)?
Try this, in car_params
params.require(:car).permit(:make, :model, :data, :wheel_count, extra_options: [])
For checkboxes, try this
<%= hidden_field_tag "car[extra_options][]", [] %>
<% ["1", "2", "3", "4", "5"].each do |o| %>
<% default_checked = car.extra_options.include?(o.to_s) rescue false %>
<label class="rightpad">
<%= check_box_tag "car[extra_options][]", o, default_checked %>
</label>
<span>
<%= o %>
</span>
<% end %>

Option Group in select tag using rails

I am getting values of #templates in my controller.
right now I have structure like this:
<%= select_tag :template ,options_from_collection_for_select(#templates,"id", "name"),{:prompt => "--Built In Templates--",:class=>"form-control m-b-sm required"}%>
But now I want to add option group in my select_tag
how can I create structure something like:
<%= select_tag :template ,grouped_options_for_select(['Built-In Templates',#templates.collect{|v| [v.name, v.id ] }],#templates),{:prompt => "please select",:class=>"form-control m-b-sm required"}%>
I want to create array of option group.like
<select>
<optgroup label="Built-In Templates">
<option value="id_default">default</option>
</optgroup>
<optgroup label="Custom Templates">
<option value="id_my template">my template</option>
</optgroup>
</select>
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"}%>

Passing in select menu into nested form's attributes

I have a nested form that has a select dropdown menu.
How can I pass the selected item's ID into the attributes that are submitted when the 'submit' button is hit?
In my situation, this is what my nested form's partial looks like:
=select("dish", "menu_id", Menu.all.collect {|r| [ r.name, r.id ] }, {:include_blank => 'Choose a Menu'})
=f.hidden_field :_destroy
=f.text_field :name, placeholder: "Name"
=f.text_field :price, placeholder: "Price"
=link_to "X", '#', :class => "remove_fields"
When I hit the submit button, the Terminal/Console displays that the following are being submitted to the database but you'll notice that the menu_id from the dropdown menu isn't part of the dishes_attributes since it doesn't share the same input id and name as the other two fields.
... "dishes_attributes"=>{"1342759486320"=>{"_destroy"=>"false", "name"=>"Dish 1", "price"=>"32"} ...
From the HTML source code, the name and price input fields get assigned the following id and name:
<input id="side_dish_dishes_attributes_1342759902918_name" name="side_dish[dishes_attributes][1342759902918][name]" placeholder="Name" size="30" type="text"/>
<input id="side_dish_dishes_attributes_1342759902918_price" name="side_dish[dishes_attributes][1342759902918][price]" placeholder="Price" size="30" type="text"/>
But my select dropdown looks like this:
<select id="dish_menu_id" name="dish[menu_id]">
<option value="">Choose a Menu</option>
<option value="1">Menu 1</option>
<option value="2">Menu 2</option>
</select>
In the parent _form page, here's what the call looks like that then calls this partial:
=link_to_add_fields "Add New Dish", f, :dishes
With the link_to_add_fields looking like this from my helpers/application_helper.rb:
def link_to_add_fields(name, f, association)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
Instead of this line
=select("dish", "menu_id", Menu.all.collect {|r| [ r.name, r.id ] }, {:include_blank => 'Choose a Menu'})
use it with form object
=f.select("menu_id", Menu.all.collect {|r| [ r.name, r.id ] }, {:include_blank => 'Choose a Menu'})
I hope this will sort out your id problem as well as part of dishes attributes

Ruby on Rails - select option helper

can someone please help in select helper, as I am new to Ruby On rails.
I have one json object as follow,
#response = {"status" => "200", "fruit" => [ {
"id" => 1,
"name" => "Apple"
}, {
"id" => 2,
"name" => "Mango"
} ]
}
for which in helper I am returning value "return #response['rateCard']"
Now what I want from this helper to generate such code in view file so it will have selection box like
<select name='fruit'>
<option value="1">apple</option>
<option value="2" selected>mango</option>
</select>
please help
Actually I have one helper "Fruits_helper.rb" which is returning
def selFruit
#resp = Fruit.getFruit # this will return #response object as mentioned above
return #resp['fruit']
end
==================================================================================
So in my fruit.html.erb file I am having small piece of code as follows
<%= form_for(:AdminLogin) do |f| %>
<div>
<%= select_tag "fruit", options_for_select(selFruit.each{|fruit,key| [fruit[key]=>'name',fruit[key]=>'id']}) %>
<div>
<% end %>
============================================================================
the above code gives me o/p as
<select name="fruit" id="fruit">
<option value="id1nameApple">id1nameApple</option>
<option value="id2nameMango">id2nameMango</option>
</select>
where I want result as apple
My Problem has been solved just by following code, hope it will help other RoR freshers too
<%= select_tag "fruit", options_for_select(selFruit.map{|fruit,key| [fruit['name'], fruit['id']]}) %>
If you use (and you should) a form_for builder:
form.select(:fruit, #response["fruit"].map { |f| [f["name"], f["id"]] })

Resources