I've got a hash that I define in my plot controller, under the edit action
#custom_params = { :custom_plot_type => "Line", :x_axis_title => "", :x_low => "", :x_high => "", :y_axis_title => "", :y_low => "", :y_high => "" }
When I visit the edit page, I have a form_with #plot as the model containing the following select box:
= fields_for :custom_params do |c|
= c.label(':custom_plot_type', "Plot Type")
= c.select(:custom_plot_type, options_for_select(['Line', 'Scatter', 'Heat Map', 'Column'], #custom_params[:custom_plot_type]))
Rails gives me the following error
undefined method `custom_plot_type' for #< Hash:0x00007ffff8c4b030>
I have followed the answer on this question and I'm pretty sure my definition of the hash is correct. But no matter which way I format it (for example, using "custom_plot_type" => "Line" and #custom_params["custom_plot_type"] instead) I get the same error in the view.
I can also output the element I want in the console within the controller, using
puts #custom_params
puts #custom_params[:custom_plot_type]
This outputs the correct value, but as soon as I try to access it in the view it crashes
Edit: Adding more information about the form to clarify in response to a comment. My form is structured as follows:
= form_with(model: #plot, local: true, method: "patch") do |f|
= label_tag('plot[name]', "New plot name:")
= text_field_tag('plot[name]', #plot.name)
%br
= label_tag('plot[description]', "Description:")
= text_field_tag('plot[description]', #plot.description)
%br
%br
= fields_for :custom_params do |c|
= c.label(':custom_plot_type', "Plot Type")
= c.select(:custom_plot_type, options_for_select(['Line', 'Scatter', 'Heat Map', 'Column'], #custom_params[:custom_plot_type]))
The thinking behind this was to have the a form that has fields that are associated with the Plot model, and also to have a subform for "custom params" that are not associated with the model itself but will be saved to a file. So the form does have a model instance associated with it, but the select tag in question does not.
I edited the form to use a select_tag instead of a c.select element, as follows:
= fields_for :custom_params do |c|
= label_tag('custom_params[:custom_plot_type]', "Plot Type")
= select_tag('custom_params[:custom_plot_type]', options_for_select(['Line', 'Scatter', 'Heat Map', 'Column'], #custom_params[:custom_plot_type]))
I still use the value of c for other form elements later on, but using _tag elements instead of elements related to the form builder allow me to use the arbitrary hash within the select tag - thanks #tgmerritt for the suggestion
Related
I have cocoon creating association sub-forms, one of these forms has projects and codes
Setup
/ view (in slim format)
.nested-fields.subform.project-subform
= link_to_remove_association "×", f
#project-code-container
.form_group
= f.label :project_id, "Project"
= f.select(:project_id,
#current_projects.map { |project| [project.name, project.id] },
{},
{ onChange: "updateCodes(this)" },
)
.form_group
= f.label :project_code_id, "Code"
= f.select(:project_code_id, #current_project_codes[1])
The second select should show a list of codes based on the index of the selected project. So if project 3 was selected, then the options for codes should be #current_project_codes[3]
Problem
When I hit a validation error on submit, the form is reloaded with the previous data already filled out (like a normal rails form). However, I don't know how to tell the project_code select which options it should load. Since this is a cocoon form, I don't have an object like #project to access the data.
I need to figure out what project was selected, so I can show the right codes.
On validation error/reload, how can I get a cocoon object's data?
p.s. I'm struggling to define this question, if you have ideas on how to make my question clearer, please let me know.
Credit to #arieljuod
f.object gives the form's object with its data
For my specific problem, this was the line that allowed a select to autopopulate with any pre-saved data:
f.select(
:project_code_id,
#current_project_codes[f.object.project_id || #current_projects.first.id]
)
This is what I am trying to do:
= form_tag(path) do
- #items.each do |i|
= fields_for "i[]", i do
%input.content{:name => "content", :type => "hidden"}
= submit_tag "Submit"
As you can see, I try to pass the value of all .content inputs from itemsto a path.
These are the parameters I get:
{"utf8"=>"✓", "content"=>"", "commit"=>"Submit"}
I'd expect something like this:
{"items": [
{
"id":1,
"content":""
},
{
"id":2,
"content":""
},
{
"id":3,
"content":""
},
] }
How do you create those POST requests in rails?
This is simpler than you've been trying to make it. You tend to only need fields_for if you have a set of fields for each of the nested models. here you just have a single hidden column, so I'd choose to just use a single hidden field eg:
= form_tag(path) do |f|
- #items.each do |i|
= f.hidden_field "items[#{i.id}]", value: i.content
= submit_tag "Submit"
Note: not bug-testing left as an exercise to the reader.
This will generate a set of parameters that map the id of the item vs the content eg: "items"=>{"38383285"=>"", "304713261"=>"Some content here", "547539357"=>"Some other content here"}
Which you can just iterate through to change the actual values however you like.
You have not provided any example of the actual structure of your models - so I am guessing how you would use that... you will need to (possibly heavily) modify the example below to meet your actual needs.
For one thing - given it's a hidden field - I have no idea what other model (and column) it is that you are trying to update. So lets pretend you have a second model called OtherItem that also has a content-field and maps to an Item via an item_id column. In that case, you'd do something like this:
def my_action
item_ids = params[:items].keys
items = OtherItem.where(:item_id => item_ids)
items.each do |item|
item.update(content: params[:items][item.item_id])
end
# other stuff here
end
I have simplest rails app, with scaffold Tent
here my controller#index for
def index
#tents = Tent
#tents = #tents.where(:brand => params[:brand]) if params[:brand]
#tents = #tents.where(:season => params[:season]) if params[:season]
end
view also standart, generated by scaffold
and here search witch should filter data
= form_tag tents_path, method: :get do
= label_tag "manufacturer"
= select_tag :brand, options_for_select(...), include_blank: true
= label_tag "seasons"
- Tent.pluck(:season).each do |season|
=check_box_tag 'season', season
=h season
= submit_tag 'Submit'
Problem 1:
When i submit from, and params are unselected(select or checl_boxes) i don't want to send this params but they are sent with empty
GET /tents?utf8=...&brand=&season=&commit=Submit
Problem 2:
When i check multiple checkboxes get request is somthing like
GET /tents?utf8=...&brand=Brand&season=4&season=3&commit=Submit
after this i expect that data will be selected for both values, but controller expected that both values is in the field, and returns zero results
any suggestuions?
UPDATE
probably my question solved in railscasts-111 (advanced search form)
About problem 2:
You need to specify season checkbox like below:
=check_box_tag 'season[]', season
But i didnt test it
Problem 2:
You need to write javascript wrapper for form to serialize and send data on submit
I've just had Submitting multiple forms in Rails answered which led to another problem. In my form I have the following (there's quite a bit more):
= hidden_field_tag :event_id, :value => #event.id
.control-group
= label_tag :title
.controls
= select(:registration, "registrations[][title]", Registration::TITLE)
and the last line returns:
"registrations"=>[{"title"=>{"registration"=>"Mr"},
as opposed to the expected:
"title"=>"Mr"
I've tried:
= select(:registration, "registrations[][title]", Registration::TITLE)
which returns:
undefined method `registrations[][title]' for #
and also tried:
= select("registrations[][title]", Registration::TITLE)
which returns:
wrong number of arguments (2 for 3)
Look at the parameters below, event(_id) is only there once then the :title oddness starts, any idea what the problem may be?
{"utf8"=>"✓",
"authenticity_token"=>"BQXm5fngW27z/3Wxy9qEzu6D8/g9YQIfBL+mFKVplgE=",
"event_id"=>"7",
"registrations"=>[{"title"=>{"registration"=>"Mr"},
"first_name"=>"Name1",
"last_name"=>"Surname1",
"company_name"=>"Company1",
"designation"=>"Designation1",
"landline"=>"Landline1",
"cell"=>"Cell1",
"email"=>"address1#example.com",
"member"=>{"registration"=>"No"},
"dietary"=>{"registration"=>"None"},
"specify"=>"None"},
{"first_name"=>"Name2",
"last_name"=>"Surname2",
"company_name"=>"Company2",
"designation"=>"Designation2",
"landline"=>"Landline2",
"cell"=>"Cell2",
"email"=>"address2#example.com",
"member"=>{"registration"=>"No"},
"dietary"=>{"registration"=>"None"},
"specify"=>"None",
"title"=>{"registration"=>"Mr"}},
{"first_name"=>"Name3",
"last_name"=>"Surname3",
"company_name"=>"Company3",
"designation"=>"Designation3",
"landline"=>"Landline3",
"cell"=>"Cell3",
"email"=>"address3#example.com",
"member"=>{"registration"=>"No"},
"dietary"=>{"registration"=>"None"},
"specify"=>"None"}],
"commit"=>"Submit registrations"}
Please not that :dietary and :member are formated in the same way as :title. Thanks in advance for your assistance!
EDIT
So submitting to the hash via a text_field_tag is a simple is:
= text_field_tag "registrations[][first_name]"
But the problem comes in with my hidden_field_tag and select_tag.
It's adding bad values, for example:
"title"=>{"registrations"=>"Mr"}
and basically it seems I need to find a better way to add those values into the hash. I'll continue trying to find a solution and will post it here unless someone beats me to it.
Unless i'm reading it wrong, your first two select calls are the same. Have you tried = select(:registrations, "title", Registration::TITLE)? If you look at the documentation of the method in api.rubyonrails.org, it will state that the first value is the object, second is the property. That would be registrations => { :title => "Value" }, in the parameters. If you just want :title => "Value", then you need the select_tag method.
While I wouldn't normally create a page like this, please know this is a current constraint I can't change.
The page has a checkbox form as well as a table with links for THs that sort the table. I need to construct the TH link in a way that it retains the checkbox items already checked.
Checkbox constructed in View with Haml as:
= form_tag movies_path, :method => :get do
Include:
- #all_ratings.each do |rating|
= rating
= check_box_tag "ratings[#{rating}]", "1", (#ratingsarray.include?(rating) ? true : false)
= hidden_field_tag 'sort', #sort
= submit_tag 'Refresh'
Then for the table it has this for the TH
%th{:class => #classrelease_date}
%a#release_date_header= link_to "Release Date", movies_path(:sort=>'release_date', :params[:ratings]=>params[:ratings])
Ultimately I want the URL like "/moves/?sort=release_date&Ratings[PG]=1&Ratings[G]=1" where I am spitting out the ratings params back to the page as part of the URL. Or how to I pass the ratings params in any part of page where the existing controller code will read it.
Existing controller code access ratings from checkbox:
params[:ratings]
Since movies_path accepts hash as parameter, you can tailor params and then generate the URL with movies_path(params). Generally, you may need to remove "controller" and "action" from params.