Time zone dropdown where select value is index - ruby-on-rails

I'm trying to create a select dropdown for time_zones in my user profile but I need the list and indexes to match up because I'm not using text, I'm using an integer for to store the zones in my database. I did that so I could display it as a dropdown in rails admin instead of a text input.
User:
validates_inclusion_of :time_zone, in: ActiveSupport::TimeZone.us_zones.map { |z| z.name },
message: "is not a valid time zone",
allow_blank: true
# This allows me to display the time_zone as a dropdown in rails admin instead of a text box
TIMEZONES = ActiveSupport::TimeZone.us_zones.map { |z| z.name }
def time_zone_enum
TIMEZONES.each_with_index.to_a
end
View:
<%= f.collection_select :time_zone, ActiveSupport::TimeZone.us_zones.map { |z| z.name }, value, name %>
# I don't know how to get the value to be an index of the map operation and to display the name

Try map.each_with_index as described here: How to map with index in Ruby?
<%= f.collection_select :time_zone, ActiveSupport::TimeZone.us_zones.map.each_with_index { |z, i| i.to_s.concat(" #{z.name}") }, name %>
You may need to modify that code to work in your rails application, but calling each_with_index on your map should give you a second parameter which will contain the index of your hash.

Related

Scope with two parameters rails

I'm following this tutorial to implement a filtering feature in my Rails app. I want admins to be able to filter by age, identifier, and a date interval the users were created. It is the last bit that is causing me some headache.
In my model user.rb, I have defined the following scopes:
scope :created_between, -> (startdate, enddate) {where(created_at: startdate..enddate)}
scope :identified, -> { where.not(identifier: [nil, '']) }
scope :age, -> (age) { where("age > ?", age)}
In my controller users_controller.rb, I use a function to filter the params:
def search
filter = params.slice(:age, :created_between, :identified)
filter.each do |key, value|
if value.present?
#users = #users.public_send(key,value)
else
#users = #users.public_send(key)
end
end
end
I differentiate between a value present or not, since the :identified scope is implemented as a checkbox and therefore passes no value like
Lastly, I have created a form for all the possible filters like so, in my view.html.erb file:
<%= form_tag users_search_path, :method => :get, :enforce_utf8 => false do %>
<%= date_field :created_between, "from" %>
<%= date_field :created_between, "to" %>
<%= check_box_tag :identified, '', false %>
<%= text_field_tag :age, "age" %>
<% end %>
The filter for age and identified works. When I submit the form the query becomes /users/search?identified=&created_between[from]=&created_between[to]= when I only check the checkbox identified (the date_field is also passed although I did not submit any date). And /users/search?age=21&created_between[from]=&created_between[to]= when I only submit an age.
My problem is that whenever I try to submit two dates for the created_between scope I get an wrong number of arguments (1 given, expected 2) error. I'm not sure that I'm submitting the date fiels correctly.
How can I pass the two needed params to the scope? Or should I do it another way instead?
Sometimes just writing out the question seems to make things clearer. However, the solution was to alter my scope function for :created_between to:
scope :created_between, -> (date) {where(created_at: date[:from]..date[:to])}

Dropdown field with user inserted data into another form (ruby on rails)

I was wondering if it was possible to put user inserted data into a dropdown text field for example:
I have the form for let's say what you did in a day, start hour end hour etc and activity, now I want the activity field to be a drop down one and have user data exclusive to the user currently logged in that was inputed into a "configuration" form, so you dont have to remember the activity number,
how can I do this?
Is this even possible?
using RoR
inside your controller
def new
..
prepare_item
end
def edit
..
prepare_item
end
def prepare_item
#item_list = Items.all.map { |c| [c.name, c.id] }
end
inside your view
<%= f.select :item_id, #item_list, { include_blank: false }, { class: 'form-control' } %>
please note class: form-control incase you using bootstrap

Passing HTML name value into rails select field

I have a form that has a select field where the user selects their title. I want to pass a name value into the rails code so the field can be modified with a client-side validation framework. The client-side validations validate each field based on the name of the field.
My current solution isn't passing the name value of 'title' into the final HTML rendered in the browser.
The field
<%= f.select :title, options_for_select([["Title", "0"], ["Mr.", "Mr."], ["Mrs.", "Mrs."], ["Ms.", "Ms."], ["Dr.", "Dr."], ["Prof.", "Prof."]], selected: "0", disabled: ["0"]), :name => "title" %>
The current HTML output
name="user[title]"
<% possible_options = [["Title", "0"], ["Mr.", "Mr."],
["Mrs.", "Mrs."], ["Ms.", "Ms."], ["Dr.", "Dr."], ["Prof.", "Prof."]]
%>
<%= f.select :title, options_for_select(possible_options), {}, {:name => "title"} %>
It's better to prepare this possible_optins list in controller action itself & accessing here just like an instance variable.
Just for a quick fix, let it be in this view/form.

Using two separate fields for the same parameter in a Rails form handler?

I'm new to Rails and am fixing a Rails 2 site. I have a form that lets the user add information for the starting location (:start) EITHER with an input OR with a dropdown field. However, I have found that when I include both options, only the dropdown (which comes last) submits data, while the input is ignored. What's the right way to include both options?
MY VIEW
<% form_for #newsavedmap, :html=>{:id=>'createaMap'} do |f| %>
<%= f.error_messages %>
<p>Enter a street address, city, and state:
<%= f.text_field :start, {:id=>"startinput", :size=>50}%></p>
<p>Or, select a location from the list:
<%= f.select :start, options_for_select(#itinerary.locations), {:include_blank => true }, {:id=>"startdrop"} %>
<input type="submit" id="savethismap" value="Save Map">
<% end %>
One way to achieve this is by using virtual attributes. Since both fields map to same attribute, you are going to have to pick which one to use.
# app/models/newsavedmap.rb
class Newsavedmap < ActiveRecord::Base
...
attr_accessible :start_text, :start_select
...
def start_text=(value)
#start_text = value if value
prepare_start
end
def start_select=(value)
#start_select = value if value
prepare_start
end
# start_text will fall back to self.start if #start_text is not set
def start_text
#start_text || self.start
end
# start_select will fall back to self.start if #start_select is not set
def start_select
#start_select || self.start
end
private
def prepare_start
# Pick one of the following or use however you see fit.
self.start = start_text if start_text
self.start = start_select if start_select
end
end
Then your form needs to use the virtual attributes:
<%= f.text_field :start_text, {:id=>"startinput", :size=>50}%></p>
<p>Or, select a location from the list:
<%= f.select :start_select, options_for_select(#itinerary.locations), {:include_blank => true }, {:id=>"startdrop"} %>
Other options are:
Use text_field as the primary and update it's value with selected option if user selects an option.
Add a hidden field in your form and use JavaScript to update the hidden field's value when text_field text gets updated or select option changes

Multiple identical collection_select tags in a form in Rails

I have multiple identical collection selects inside a single form. I prefer this over a multiple select list for aesthetic and UX reasons. I have to use a terrible kludge to make everything work right, and I'm wondering if there is a more elegant way to do this:
From the view:
<% 3.times do |i| %>
<%= collection_select("selected_item_" + i.to_s.to_s, :name, #items, :name, :name, { :include_blank => true }, { id: "selected_item_" + i.to_s }) %>
<% end %>
From the controller:
ItemContainer = Struct.new(:name)
3.times do |i|
param = ('selected_item_' + i.to_s).to_sym
instance_variable = '#' + param_name
if params[param] && !params[param].empty?
#selected_items << params[param][:name]
instance_variable_set(instance_variable, ItemContainer.new(params[param][:name]))
end
end
#selected_channels.each.... # do what I need to with these selections
Most of these gymnastics are needed to ensure that the item is still selected if the page is refreshed. If there were some way to force collection select to use arrays, that would be the answer, but I couldn't make that work.
If I understang right you're looking for selegt_tag method (docs: http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-select_tag)
You can write something like this
select_tag "people[]", options_from_collection_for_select(#people, "id", "name")
select_tag "people[]", options_from_collection_for_select(#people, "id", "name")
and it youd output two selects for people, which would be sent as an array on submit.
if you use the [] naming in your collection_select calls then the params will send over the data as an array
I am a bit confused as to the usage of collection_select here as it doesn't seem like you are using a model object? this example using select_tag - might be able to come up with something more appropriate to your issue if the model structures were known
# run this in the loop
# set selected_value to appropriate value if needed to pre-populate the form
<%= select_tag('name[]',
options_from_collection_for_select(#items, 'name', 'name', selected_value),
{ include_blank: true }
)
%>
in controller update/create action
# this works because the select tag 'name' is named with [] suffix
# but you have to ensure it is set to empty array if none are passed, usually only issue with checkboxes
names = params[:name] || []
names.each do |name|
puts name
end
side note: you can use string interpolation with ruby double quotes in places of + for string concatenation
<%= collection_select("selected_item_#{i}",
:name,
#items,
:name,
:name,
{ include_blank: true },
{ id: "selected_item_#{i}" }
)
%>
see also: http://apidock.com/rails/v3.2.13/ActionView/Helpers/FormOptionsHelper/options_from_collection_for_select

Resources