I'm passing an array with form params to process. It contains several rows with each multiple values. How can I retrieve the individual values?
This is the controller code:
params[:line].each do |line|
...
end
Each "line" gives me these values and I want to retrieve each value, like "home_score_id":
["1", {":home_club_id"=>"11", ":home_score"=>"2", ":away_score"=>"4", ":away_club_id"=>"10"}]
Update:
This is the form, it has 12 lines where you enter match results:
= form_tag store_all_results_path, class: 'form-horizontal' do
.control-group
.controls
= select_tag :gameround_id, options_for_select(#gamerounds.map{ |g| ["#{markup_gameround(g)}", g.id] })
- 1.upto(12) do |counter|
.control-group
.controls
= select_tag "line[#{counter}][:home_club_id]", options_for_select(#clubs.map{ |c| [c.club_name, c.id] }), include_blank: true
= text_field_tag "line[#{counter}][:home_score]", nil, class: "small_text_field"
= text_field_tag "line[#{counter}][:away_score]", nil, class: "small_text_field"
= select_tag "line[#{counter}][:away_club_id]", options_for_select(#clubs.map{ |c| [c.club_name, c.id] }), include_blank: true
.form-actions
= submit_tag :submit, value: I18n.t('.general.save'), class: "btn"
= link_to t('.cancel', default: t("helpers.links.cancel")), results_path, class: 'btn'
When submitted, it gives these POST parameters:
Started POST "/results/store_all" for 127.0.0.1 at 2013-04-03 10:47:34 +0200
Processing by ResultsController#store_all as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "gameround_id"=>"3", "line"=>{"1"=>{":home_club_id"=>"8", ":home_score"=>"3", ":away_score"=>"2", ":away_club_id"=>"10"}, "2"=>{":home_club_id"=>"7", ":home_score"=>"4", ":away_score"=>"2", ":away_club_id"=>"12"}, "3"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}, "4"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}, "5"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}, "6"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}, "7"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}, "8"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}, "9"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}, "10"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}, "11"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}, "12"=>{":home_club_id"=>"", ":home_score"=>"", ":away_score"=>"", ":away_club_id"=>""}}, "commit"=>"Opslaan"}
In the controller, I want to go through each of the 12 lines and create a result record (when line is not empty):
def store_all
params[:line].each do |line|
unless line[:home_club_id].blank?
Result.create(home_club_id: line[:home_club_id], away_club_id: line[:away_club_id], home_score: line[:home_score], away_score: line[:away_score], gameround_id: params[:gameround_id])
end
end
end
Although your keys look like symbols (:home_club_id), they are in fact strings prefixed with a colon (":home_club_id"). Removing the colons from your view should fix the problem.
So instead of:
= text_field_tag "line[#{counter}][:away_score]"
Just write:
= text_field_tag "line[#{counter}][away_score]"
Since params is a HashWithIndifferentAccess you can use either line["away_score"] or line[:away_score] in your controller.
def store_all
params[:line].each do |counter, line|
unless line[:home_club_id].blank?
Result.create(line.merge(gameround_id: params[:gameround_id])
end
end
end
The second value in "line" is a Hash, thus access is possible with
line[1][:home_club_id]
Related
I have a Rails 3.2.16 legacy app where I record call information and times on each call en_route_time on_scene_time, etc all are datetime fields.
In my Call show view I have an edit times path which redirects to an edit_times view via a get request. This allows you to edit times in case errors were made.
edit_times in calls_controller.rb
def edit_times
#call = Call.find(params[:id])
end
edit_times.html.erb
<%= form_for(#call) do |f| %>
<%= f.label :En_Route_Time %>
<%= f.date_select :en_route_time %>
<%= f.time_select :en_route_time,
:combined => true,
:default => Time.zone.now,
:include_blank => true,
:minute_interval => 1,
:time_separator => "",
:start_hour => 00,
:end_hour => 23 %>
<%= f.label :On_Scene_Time %>
<%= f.date_select :on_scene_time %>
<%= f.time_select :on_scene_time,
:combined => true,
:default => Time.zone.now,
:include_blank => true,
:minute_interval => 1,
:time_separator => "",
:start_hour => 00,
:end_hour => 23 %>
<%= f.label :To_Hospital_Time %>
<%= f.date_select :to_hospital_time %>
<%= f.time_select :to_hospital_time,
:combined => true,
:default => Time.zone.now,
:include_blank => true,
:minute_interval => 1,
:time_separator => "",
:start_hour => 00,
:end_hour => 23 %>
<%= f.label :At_Hospital_Time %>
<%= f.date_select :at_hospital_time %>
<%= f.time_select :at_hospital_time,
:combined => true,
:default => Time.zone.now,
:include_blank => true,
:minute_interval => 1,
:time_separator => "",
:start_hour => 00,
:end_hour => 23 %>
<%= f.label :In_Service_Time %>
<%= f.date_select :in_service_time %>
<%= f.time_select :in_service_time,
:combined => true,
:default => Time.zone.now,
:include_blank => true,
:minute_interval => 1,
:time_separator => "",
:start_hour => 00,
:end_hour => 23 %>
<%= f.button :Submit %>
<% end %>
This works fine, however when editing times if a time is not populated it will update_attributes with a default time when blank is selected 0:00.
So I wrote the following private method in calls_controller' to allow blank times if the5iparams is blank on the update action and use abefore_filter` to trigger it.
calls_controller.rb
before_filter :filter_blank_call_times, only: [:update]
def filter_blank_call_times
if params[:call]['en_route_time(5i)'].blank?
params[:call]['en_route_time(1i)'] = ""
params[:call]['en_route_time(2i)'] = ""
params[:call]['en_route_time(3i)'] = ""
params[:call]['en_route_time(4i)'] = ""
params[:call]['en_route_time(5i)'] = ""
end
if params[:call]['on_scene_time(5i)'].blank?
params[:call]['on_scene_time(1i)'] = ""
params[:call]['on_scene_time(2i)'] = ""
params[:call]['on_scene_time(3i)'] = ""
params[:call]['on_scene_time(4i)'] = ""
params[:call]['on_scene_time(5i)'] = ""
end
if params[:call]['to_hospital_time(5i)'].blank?
params[:call]['to_hospital_time(1i)'] = ""
params[:call]['to_hospital_time(2i)'] = ""
params[:call]['to_hospital_time(3i)'] = ""
params[:call]['to_hospital_time(4i)'] = ""
params[:call]['to_hospital_time(5i)'] = ""
end
if params[:call]['at_hospital_time(5i)'].blank?
params[:call]['at_hospital_time(1i)'] = ""
params[:call]['at_hospital_time(2i)'] = ""
params[:call]['at_hospital_time(3i)'] = ""
params[:call]['at_hospital_time(4i)'] = ""
params[:call]['at_hospital_time(5i)'] = ""
end
if params[:call]['in_service_time(5i)'].blank?
params[:call]['in_service_time(1i)'] = ""
params[:call]['in_service_time(2i)'] = ""
params[:call]['in_service_time(3i)'] = ""
params[:call]['in_service_time(4i)'] = ""
params[:call]['in_service_time(5i)'] = ""
end
end
routes.rb except
resources :calls do
member do
post 'close'
post 'cancel'
post 'note'
get 'opencall'
get 'new_return'
get 'duplicate_call'
get 'edit_times'
put 'update_billing'
post 'dispatch_call'
put 'en_route'
put 'on_scene'
put 'to_hospital'
put 'at_hospital'
put 'in_service'
end
collection do
get "scheduled"
get "call_search"
end
end
This works fine when editing times and allows for a blank time to be entered if the 5i datetime field is blank.
The problem I'm having is when editing/updating a call through the normal edit/update convention, whenever I do edit the call it wipes out whatever times are there.
I'm looking for a way to either write a conditional in the update method in calls_controller.rb where filter_blank_call_times is only called if any of the 5i keys are blank. The way it's working right now is that when you edit times it calls the update action on the calls_controller and sets all of the times to nil. I need to figure out a way to only perform the filter_blank_call_times method when editing times, not when editing/updating a call to prevent call times from being wiped out.
If there is a better way of doing this, such as building another controller for edit_times and nesting that resource under calls or somehow doing a post request instead of utilizing the update action action on the calls_controller I'd love to hear about it.
So in summary, editing times is no problem, but calling this on the update action wipes out the time calls and I need to figure out a way around this.
If my question is not clear or you need more information/code, please let me know.
Here's an except of the params that are passed when calling the update action in calls_controller
Started PUT "/calls/125" for 127.0.0.1 at 2014-10-08 06:59:05 -0500
Processing by CallsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"uH+XDJpZQDH4PNAuOOi7dfLVolfRzziMKWc/rSR6UMg=", "call"=>{"caller_name"=>"James Jelinek", "caller_phone"=>"281-444-2222", "caller_address"=>"", "patient_name"=>"Doe, John", "billing_address"=>"", "patient_dob"=>"2001-10-17", "patient_age"=>"12", "patient_sex_id"=>"1", "insurance_id"=>"4", "nature_id"=>"2", "region_id"=>"2", "transfer_from_id"=>"3", "transfer_from_other"=>"", "facility_from_location"=>"", "transfer_to_id"=>"", "transfer_to_other"=>"123 w 8th st Houston, TX 77088", "facility_to_location"=>"ER Room 2", "service_level_id"=>"1", "special_equipment_ids"=>["", "2"], "transfer_date(2i)"=>"10", "transfer_date(3i)"=>"2", "transfer_date(1i)"=>"2014", "transfer_date(5i)"=>"00:00:00", "wait_return"=>"yes", "parent_call_id"=>"124", "traffic_type"=>"Non-Emergency", "unit_ids"=>["", "1"], "call_status"=>"open"}, "button"=>"", "id"=>"125"}
To check the time against all zeros, nil, or empty this regex should work.
"00:00:00"::=~(/[1-9]/).nil?
=> true
And instead of manually writing everything out you can write code to grab the text before "(5i)" and change all the other values to empty. The code would look something like this:
params["call"].keys.each {|item|
post_text = "(5i)" # Set the target text we're looking for
if !!item[post_text] # If target text matches
if params["call"][item]::=~(/[1-9]/).nil? # Time is all zeros, nil, or empty
pre_text = item[0...item.index(post_text)] # get the text from before target
params["call"].keys.select {|i|
!!i[pre_text] and !i[post_text] #select the OTHER values that match the pre_text
}.each {|like_item|
params["call"][like_item] = "" # set all the OTHER values that match the same pre_text to ""
}
end
end
}
Note if you want to change the (5i) field to blank as well you'd change it to this:
params["call"].keys.each {|item|
post_text = "(5i)" # Set the target text we're looking for
if !!item[post_text] # If target text matches
if params["call"][item]::=~(/[1-9]/).nil? # Time is all zeros, nil, or empty
pre_text = item[0...item.index(post_text)] # get the text from before target
params["call"].keys.select {|i|
!!i[pre_text] #select the values that match the pre_text (including post_text)
}.each {|like_item|
params["call"][like_item] = "" # set all the values that match the same pre_text to ""
}
end
end
}
Either of these get placed inside
def filter_blank_call_times
# CODE HERE
end
I'm using this code in my view to create a selection grouped_collection_select(:query, :city_id, #states, :cities, :name, :id, :name, {:selected => "Chicago"}) that looks like this:
I want to have "Chicago" selected by default. How can I get this to work?
Hi on your sample above you can select "Chicago" by defining the selected key index of chicago.
Here's an example:
#city_group =
[
["Wisoncin", [["Lake Geneva", "1"],
["Elkhart Lake", "2"]]],
["Michigan", [["Harbor Country", "3"], ["Traverse City", "4"]]],
["Indiana", [["Bloomington", "5"], ["Valparaiso", "6"]]],
["Minnesota", [["Twin Cities",
"7"], ["Bloomington", "8"], ["Stillwater",
"9"]]],
["Florida", [["Sanibel & Captiva", "10"]]],
["Illinois", [["Chicago", "11"],
["Galena", "12"]]],
]
and in your views add this:
<%= select_tag(:brand_id, grouped_options_for_select(#city_group, selected_key = "11", prompt = nil)) %>
Hope it helps! Enjoy!
Solution: 1
city = City.find_by_name("Chicago")
select(:query, :city_id, option_groups_from_collection_for_select(#states,
:cities, :name, :id, :name, city.id))
Solution: 2
city_obj = City.find_by_name("Chicago")
grouped_collection_select(:query, :id, #states, :cities, :name, :id, :name,
{:object => city_obj})
Solution: 3
#city = City.find_by_name("Chicago")
grouped_collection_select(:city, :id, #states, :cities, :name, :id, :name)
It is possible to pre-select an option, but it's not very clear in the documentation. The first parameter (here :city) has to be the name of an instance variable defined on self. The object stored in that instance variable has to have a method named after the second parameter (here: :id). Now #city.id should return the id of the city you want to have selected.
#city = City.find_by_name("Chicago")
grouped_collection_select(:city, :id, #states, :cities, :name, :id, :name)
I made you a gist with a slightly different example for better understanding. Note: the gist should be executed in a rails console, so that the include works
I am using Meta-search Gem to search from table by below controller action. I am Using The Rails version 3.2.9.
class FeedEntriesController < ApplicationController
def index
#search = FeedEntry.search(params[:is_star])
#feed_entries = #search.page(params[:page])
#app_keys = AppKey.all
end
end
feed_entries table contain is_star:boolean attribute. So, I just want to pass the hash parameter is_star == true into the params[:is_star] from view using form_for or link_to . I tried using the below way.
In Views/feed_entries/index.html.erb
<%= link_to "Stared", {:controller => "feed_entries", :action => "index", :is_star => true }%>
but the above way is now worked, So I decided to make use of form_for in the below way,
<%= form_for(#is_star) do |f|%>
<%= f.hidden_field :is_star_is_true %>
<%= f.submit "Search" %>
<% end %>
But, nothing is worked, please someone help me resolve this problem.
true and false when passed as a string is parsed as their truthy value when used in a boolean column. This is also true for 0, 1, '0' and '1'
>> m = Model.new
>> m.active = 'false'
>> m.active? # false
>> m.active = 'true'
>> m.active? # true
Knowing this, you can pass 'true' as the value of the hidden_field
<%= f.hidden_field :is_start, value: 'true' %>
You can pass in the value of the parent in the view where the form is being rendere ultimately with something like <%=params[:is_start] = 1 %> . I am not sure how the layout of the app is setup. Also make sure to attr_accessible :is_start
Update: I may have understood your problem wrong. So try this as well
<%= f.hidden_field :is_star, value: 'true' %>
Or you could have a radio button ?
<%= f.radio_button :is_star, value: 'true' %>
I want to see my room_requests which have duration included in my date range from form. Here's what I've done:
controller for this view:
def not_confirmed_slots
if params[:search]
#slots = RoomRequest.find(:all, :conditions => ['date >= ? and date =< ?', params[:start_date].strftime("%Y-%m-%d"), params[:end_date].strftime("%Y-%m-%d")])
if #projects.size.zero?
flash[:notice] = "No result found"
#slots = RoomRequest.find(:all)
end
else
#slots = RoomRequest.all
end
end
and my form from view:
%h1= t('headers.reports.notConfirmedSlots')
= form_tag not_confirmed_slots_reports_path, method: 'get' do
%p
= text_field_tag :start_date, nil, :class => "datepicker", :placeholder => t('placeholders.reports.startDate')
%p
= text_field_tag :end_date, nil, :class=>"datepicker", :placeholder => t('placeholders.reports.endDate')
.clear
.action_bar
= submit_tag t('buttons.reports.generate'), {class: "button blue"}
But every time I submit form with dates it lists me all room_requests from db - any tips?
Oh, and here is the partial (it's on the same view where is search form):
%table
- #slots.each do |s|
%tr
%td
= s.bookers_name
%td
= s.request_type
I'm having trouble getting fields_for to work on an Array attribute of a non-ActiveRecord model.
Distilled down, I have to following:
models/parent.rb
class Parent
extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations
extend ActiveModel::Translation
attr_accessor :bars
end
controllers/parent_controller.rb
def new_parent
#parent = Parent.new
#parent.bars = ["hello", "world"]
render 'new_parent'
end
views/new_parent.html.haml
= form_for #parent, :url => new_parent_path do |f|
= f.fields_for :bars, #parent.bars do |r|
= r.object.inspect
With the code as above, my page contains ["hello", "world"] - that is, the result of inspect called on the Array assigned to bars. (With #parent.bars omitted from the fields_for line, I just get nil displayed).
How can I make fields_for behave as for an AR association - that is, perform the code in the block once for each member of my bars array?
I think the correct technique is:
= form_for #parent, :url => new_parent_path do |f|
- #parent.bars.each do |bar|
= f.fields_for "bars[]", bar do |r|
= r.object.inspect
Quite why it can't be made to Just Work I'm not sure, but this seems to do the trick.
I think that it can be done without the need of each:
= form_for #parent, :url => new_parent_path do |f|
= f.fields_for :bars do |r|
= r.object.inspect
You need to set some methods that are expected in the parent class to identify the collection.
class Parent
def bars_attributes= attributes
end
end
And you also will need to make sure that the objects in the array respond to persisted (so you cannot use strings) :(
I ditched the fields_for and added multiple: true
= form_for #parent, :url => new_parent_path do |f|
- #parent.bars.each_with_index do |bar, i|
= f.text_field :bars, value: bar, multiple: true, id: "bar#{i}"