I want to use form_for to create a form and update multiple users.
Let's say each user has :id and :name. I would like the POST parameters to be:
{
"users": [
{
"id": 1,
"name": "Bob"
},
{
"id": 2,
"name": "Leo"
}
......
]
}
The form looks like([] means input fields):
Users
1 [ Bob ]
2 [ Leo ]
3 [ ]
How does the form_for code looks like?
form_tag your_url, method: :post do |f|
#users.each do |user|
label_tag user.id
hidden_field_tag "users[][id]", user.id
text_field_tag "users[][first_name]", user.first_name
end
end
I think it will pass parameters as you want, but the hard thing is how to show detail error messages for each user
Related
How do I specify the selected option if two of these options have the same id? I have this form input
<%= f.input :receiver_id,
label: "Client",
collection: receivers_keys_and_values,
as: :grouped_select,
group_method: :last %>
and this method to create the select options
def receivers_keys_and_values
[
["Client", Client.all.map { |c| [c.name, c.id] }],
["Program", Program.all.map { |p| [p.name, p.id] }]
]
end
The issue I have is that a client ID could be the same as a Program ID. Therefore when two ID are the same the selected one is always the Program one.
How could I specify something like?
selected: ["Client"][id]
or
selected: ["Program"][id]
This way ids of the selected elements will be different for programs and clients:
def receivers_keys_and_values
[
["Client", Client.all.map { |c| [c.name, "client_#{c.id}"] }],
["Program", Program.all.map { |p| [p.name, "program_#{p.id}"] }]
]
end
You'll also have to update form handling code in order to be able to parse input like "program_123".
You can also go fancy and refactor the code a bit:
def receivers_keys_and_values
[Client, Program].map do |type|
type.all.map { |entity| [entity.name, dom_id(entity) }
end
end
but I'm not sure if it's clearer (should produce the same result though). Up to you.
I have a simple table which displays all the users and its attributes id,name,age,status,location. I want to filter on age and status.
Id name age status location
1 xz 22 single ca
2 yy 23 married ma
I am using filterrific plugin and able to display the list and the filter dropdown.
My user.rb
filterrific(
available_filters: [
:with_status,
:with_age
]
)
scope :with_age, lambda { |age|
where(age: [*age])
}
scope :with_status, lambda { |status|
where(status: [*status])
}
def self.options_for_select
order('LOWER(status)').map { |e| [e.status] }.uniq
end
def self.options_for_select2
order('LOWER(age)').map { |e| [e.age] }.uniq
end
The controller index looks like
def index
#filterrific = initialize_filterrific(
User,
params[:filterrific],
select_options: {
with_status: User.options_for_select,
with_clearance_batch_id: User.options_for_select2
},
default_filter_params: {},
available_filters: [],
) or return
#users = #filterrific.find
respond_to do |format|
format.html
format.js
end
end
the index.html.erb looks like
<%= form_for_filterrific #filterrific do |f| %>
<div>
age
<%= f.select(
:with_age,
#filterrific.select_options[:with_age],
{ include_blank: '- Any -' },
{class: 'form-control' }
) %>
</div>
<div>
status
<%= f.select(
:with_status,
#filterrific.select_options[:with_status],
{ include_blank: '- Any -' },
) %>
</div>
<% end %>
<%= render(
partial: 'browse_users/list',
locals: { users: #users }
) %>
When I go to the page I am able to see all the users. Now when I filter nothing happens. I still see all the users. Not sure what is happening. I have feeling that my scope filter is not getting applied.
To me this did the trick:
In app/assets/javascripts/application.js, I've put the line "//= require turbolinks" after "//= require filterrific/filterrific-jquery" (earlier it was before it)
After doing the above, filtering or sorting happened still only when I hit refresh in the browser, and I didn't find a solution to that, so I rather added a form submit button as mentioned in "Disable AJAX auto form submits" in the documentation (http://filterrific.clearcove.ca/pages/action_view_api.html). This way you should still click a button or hit Enter, but at least filtering / sorting works.
One more thing: I had also a problem when wanting to sort according to a field in another table (following a belongs_to foreign key relationship). If I did it as mentioned in the source of the sample app in github (https://github.com/jhund/filterrific_demo/blob/master/app/models/student.rb):
"order("LOWER(countries.name) #{ direction }").includes(:country)"
I got an SQL error. When I have changed it to something like
"joins(:country).order("LOWER(countries.name) #{ direction }")"
it solved the problem.
I'm trying to make an app in Rails 4. I use simple form for forms.
I have an attribute called 'self_governance' in my model.
I've written a helper method so that I can define 5 levels which can be stored for this attribute, but which are displayed to the user as options (rather than numbers 1 .. 5).
In my helper, I have:
module PreferencesHelper
def self_gov_selector
[
[ 'tier 1','1'],
[ 'tier 2','2'],
[ 'tier 3','3'],
[ 'tier 4','4'],
[ 'tier 5','5'],
]
end
In my form, I then have:
<%= f.input :self_governance, :label => "Select your tier", collection: self_gov_selector %>
Then in my show, I'm trying to figure out how to display 'tier 1' instead of '1'.
I have tried:
<%= #preference.self_governance %>
<%= #preference.self_gov_selector %>
I can't find anything that works. They all display 1 instead of Tier 1 in the views.
How can I make this work?
The params posted by the form will only include the second value in the array, so you're likely storing your value as an integer in your database table.
A simple solution is to use an enum to map the integers you're storing to the values they represent:
In your Preference model:
enum self_governance: {
tier_1: 1,
tier_2: 2,
tier_3: 3,
tier_4: 4,
tier_5: 5
}
Then update your view accordingly:
<%= #preference.self_governance.try(:humanize) %>
EDIT:
An additional bonus of this approach is that you can replace your helper method with calling the enum directly:
f.input :self_governance, as: :select, label: "your label", collection: Preference.self_governances.map { |key, val| [key.humanize, val] }
If I create a child node in RABL using the node() method, how can I control the attributes that are presented?
The JSON output is this:
[
{
"location": {
"latitude": 33333,
"longitude": 44444,
"address": "xxxxxxx",
"title": "yyyy",
"url": "http://www.google.com",
"rate": {
"created_at": "2012-09-02T11:13:13Z",
"id": 1,
"location_id": 1,
"pair": "zzzzzz",
"updated_at": "2012-09-02T12:55:28Z",
"value": 1.5643
}
}
}
]
I want to get rid of the created_at, updated_at and location_id attributes.
I have this in my view file:
collection #locations
attributes :latitude, :longitude, :address, :title, :url
node (:rate) do
|location| location.rates.where(:pair => #pair).first
end
I tried using a partial and the 'extend' method, but it totally screwed things up. Also, I tried adding attributes to the block but it didn't work (the output was as specified in the attributes but it didn't show the values for each attribute).
Thanks!
Your code: location.rates.where(:pair => #pair).first returns the whole Rate object. If you want specific fields (for example: all, except for create_at, updated_at, etc.) then you have two options:
Manually describe the hash in node():
node (:rate) do |location|
loc = location.rates.where(:pair => #pair).first
{ :pair => loc.pair, :value => loc.value, etc... }
end
Or you can do this:
node (:rate) do |location|
location.rates.where(:pair => #pair).select('pair, value, etc...').first
end
...and as a side note, I should say that placing logic (rates.where) in your view is not a best practice. see if your controller can do that for the view using the Rate model.
You wouldn't be able to use attributes within the node block, since "self" in there is still the root object or collection, so in your case #locations. See also RABL wiki: Tips and tricks (When to use Child and Node)
In the node block you could simply create your custom response by only listing the attributes that your interested in:
node :rate do |location|
rate = location.rates.where(:pair => #pair).first
{:id => rate.id, :location_id => rate.location_id, :value => rate.value}
end
You can also try the approach using a partial:
In app/views/rates/show.json.rabl
object #rate
attributes :id, :location_id, :value
Then in your #locations rabl view:
node :rate do |location|
rate = location.rates.where(:pair => #pair).first
partial("rates/show", :object => rate)
end
Update: To clear up confusion: by multiple records I mean multiple individuals at once. Each voter would have their own select__tag, this is the reason I want to pass the ID as a hash.
I'm attempting to display multiple records, with each record displaying its own selection box. I would like to submit this form and pass a hash, having the Add.id function as the key of the hash, and the selection box option pass as the information in the hash. How could I fix my code? is this even possible with the select_tag method?
<%= form_tag yardsign_adds_path, :method => :post do %>
<%= select_tag "support_code[]",
options_for_select([[ "1 - Strong Supporter", add.id ],
[ "2 - Likely Voter" ],
[ "3 - Undecided" ],
[ "4 - Likely Opposed" ],
[ "5 - Strongly Opposed" ]]) %>
<%= submit_tag "Update" %>
<% end %>
Current terminal output:
Started POST "/adds/yardsign" for 127.0.0.1 at 2010-04-17 01:36:03
Processing by AddsController#yardsign as HTML
Parameters: {"commit"=>"Update", "authenticity_token"=>"VQ2jVfzHI7pB+87lQa9NWqvUK3zwJWiJE7CwAnIewiw=", "support_code"=>["1", "3 - Undecided", "3 - Undecided"]}
From the little i get ur question i assuming u want user will able to select more than one option from the select list refer following code (please ignore if you want something else )
<%= select_tag "support_code[]", :multiple=>true
options_for_select([[ "1 - Strong Supporter", add.id ],
[ "2 - Likely Voter" ],
[ "3 - Undecided" ],
[ "4 - Likely Opposed" ],
[ "5 - Strongly Opposed" ]]) %>