Rails form_for pass params as Array - ruby-on-rails

I have a page where I may add n number of questions. And my questions partial contains a form as follows:
= form_for :question, :url => questions_path do |f|
= f.text_field :title
What I get in params is "question"=>{"title"=>"Some Name"}. But, if I click Add New Question button the same partial is rendered below. My problem is I still get the first questions params even if I have 2 forms now. Is there a way to get params like
"question"=>{["title"=>"Some Name"], ["title"=>"Some Other Name"]}

try this
= form_for :question, :url => questions_path do |f|
= f.text_field :title, name: "question[title][]"
for more info refer http://guides.rubyonrails.org/action_controller_overview.html#hash-and-array-parameters

Related

Simple form for params

I have 2 models, blogs and posts
resources :blogs do
resources :posts
end
So, also i have an association. One blog can have a lot of posts. So I put the link to new post in the index of blog:
= link_to 'New Post', new_blog_post_path(#blog)
And then it redirects you to new post, which renders a form like this:
= simple_form_for(#post) do |f|
= f.error_notification
.form-inputs
= f.input :title
= f.input :content
.form-actions
= f.button :submit
And I'm getting an error:
undefined method `posts_path'
I think simple form requires the blog_id but I could't find it. I tried to put #blog.id to simple form, but anyway i got an error (id for nil class)
How can I solve my problem?
I've never used simple_form_for, but it looks to me like your resource has association that is assigned. So you'll need to include it in the form definition:
= simple_form_for([#blog, #post]) do |f|
= f.error_notification
.form-inputs
= f.input :title
= f.input :content
.form-actions
= f.button :submit
And obviously you'll need to have #blog available in your controller action.
Link to the form_for docs:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for
EDIT:
Not sure where posts_path is coming from in your code, but obviously that route doesn't exist as all post paths are dependent on blogs.
Is there anywhere where you reference a post_path in your code?

ActiveAdmin Passing Resource from Controller to Render

I am building a rails application using ActiveAdmin, and want to build a form for a custom action in the controller. I am trying to pass #listings from a collective_action to the rendered file, allowing me to edit multiple records at once. The #listings are based on an ActiveRecord query which draws record IDs from the URL.
It seems to be successfully accessing the parameters from the URL, and querying the database. When the form is served to the browser however, it is not able to produce the values of listing.title. Any ideas?
Here is my Listing.rb:
ActiveAdmin.register Listing do
collection_action :batch_upload do
ids = params[:id]
#listings = []
#listings = Listing.find(ids)
render template: 'listings/edit_batch'
end
end
Here is my edit_batch.html.haml:
= semantic_form_for :listing, :url => {:controller => 'listings', :action => 'batch_upload'}, :html=>{:method=>:put} do |f|
-#listings.each do |listing|
=f.hidden_field :id, :value => listing.id
=f.input :title, :value => listing.title
=f.submit "Submit"
If the form is correctly displaying listing.id but not listing.title then I suspect the record does not have title set, or listing does not have a title attribute.
To check, run the Rails console and find the record using the id from the form:
$ Listing.find(1)
Check the returned object to see whether it is missing the title.
I changed the code to the input so that it accesses its html directly and it worked:
=f.input :title, :input_html => { :value => listing.title }
Using Formtastic's inputs block might help simplify the inputs for each listing. Doing so will allow the form to create attribute fields for each Listing object.
# edit_batch.html.haml
= semantic_form_for :listing, :url => {:controller => 'listings', :action => 'batch_upload'}, :html=>{:method=>:put} do |f|
- #listings.each_with_index do |listing, index|
f.inputs for: listing, for_options: { index: index } do |l|
= l.input :id, as: :hidden
= l.input :title
= f.submit "Submit"
The :for and :for_options scope inputs fields to a specific object.

rails simple_form fields not related to the model

I have an existing form which is tied to a model named 'Order', but i want to add new form fields that will capture Credit Card info such as name, cc number, etc to be processed on a 3rd party payment gateway.
But since i don't want to save CC info in our database, there are no corresponding columns of that in my order table. And this gives me an error when submitting the form that those Credit card input fields are not 'part' of the order model.
If I understand your answer correctly, what you want to do is explained in the official wiki page here: Create a fake input that does NOT read attributes. You can use a field not related to any real database column by Edward's suggestion, however you don't need to define an attribute in your model if the form field is nothing to do with the model.
In summary, the trick explained in the page is defining a custom input called 'FakeInput' and use it like this:
<%= simple_form_for #user do |f| %>
<%= f.input :agreement, as: :fake %>
....
Do not forget to restart your rails server after adding/modifying a custom input as Fitter Man commented.
UPDATE: Please note that the official wiki page has updated and the sample code on the wiki page is not working for those which use older versions of SimpleForm. Use code below instead if you encounter an error like undefined method merge_wrapper_options for.... I'm using 3.0.1 and this code works well.
class FakeInput < SimpleForm::Inputs::StringInput
# This method only create a basic input without reading any value from object
def input
template.text_field_tag(attribute_name, input_options.delete(:value), input_html_options)
end
end
You can use attr_accessor
class Order < ActiveRecord::Base
attr_accessor :card_number
end
Now you can do Order.first.card_number = '54421542122' or use it in your form or whatever else you need to do.
See here for ruby docs http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-attr_accessor
and here for a useful stackoverflow question What is attr_accessor in Ruby?
Don't get it mixed up with attr_accessible! Difference between attr_accessor and attr_accessible
The best way to handle this is to use simple_fields_for like so:
<%= simple_form_for #user do |f| %>
<%= f.input :first_name %>
<%= f.input :last_name %>
<%= f.input :email %>
<%= simple_fields_for :other do |o| %>
<%= o.input :change_password, as: :boolean, label: 'I want to change my password' %>
<% end %>
<% end %>
In this example, I have added a new field called change_password which is not part of the underlying user model.
The reason this is a good approach, is that it lets you use any of the simple form inputs / wrappers as fields. I don't care for the answer by #baxang, because it doesn't allow you to use different types of inputs. This seems more flexible.
Notice though for this to work, I had to pass :other to simple_fields_for. You can pass any string/symbol as long as there is not a model with that same name.
I.e. unfortunately I can't pass :user, as simple_form would try to instantiate a User model, and we'd get the same error message again...
Also if you're just trying to add something and get it into the params, but leaving it out of the model's hash, you could just do FormTagHelpers. http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html
Example:
<%= simple_form_for resource, :as => resource_name, :url => invitation_path(resource_name), :html => {:method => :post} do |f| %>
<%= devise_error_messages! %>
<% resource.class.invite_key_fields.each do |field| -%>
<%= f.input field %>
<%= hidden_field_tag :object_name, #object.class.name %>
<%= hidden_field_tag :object_id, #object.id %>
<% end -%>
I found a very simple (and somewhat strange) workaround.
Just add the input_html option with any value key inside. E.g:
= simple_form_for #user do |f|
= f.input :whatever, input_html: {value: ''}
Tested simple_from versions: 3.2.1, 3.5.1

Dynamic content with fields_for

I have a nested form that uses a has_many relationship. In my form view, I use a partial for the field inputs and pass along the FormBuilder object.
form.html.haml:
- form_for #record do |f|
.field
= container do
- f.fields_for :strings do |s|
= render :partial => 'string_fields', :locals => {:s => s}
_string_fields.html.haml:
= s.hidden_field :id
= s.hidden_field :language_id
.field
%h3
= t(:name)
= s.text_field :name, :size => 50
.field
%h3
= t(:description)
= s.text_area :description, :rows => 6
This works as it should; however, I'd like to add functionality in AJAX to dynamically add another set of fields using RJS, and when I try to render the partial through RJS, obviously s isn't defined (I don't know what I'd pass through the :locals hash).
Is there some way to properly add field dynamically to a field set defined by fields_for, or do I have to reimplement my partial without using the helpers?
It's possible to add fields dynamically with your current implementation, look at:
http://railscasts.com/episodes/197-nested-model-form-part-2
for inspiration

Forms blank when rendering a partial when using a collection of objects. Help!

Alright, I know my title is a little obscure but it best describes the problem I am having.
Essentially, I have a list of users, and want to be able to edit their information in-line using AJAX.
Since the users are showing up in rows, I am using a partial to render the data and the forms (which will be hidden initially by the ajax), however, when the rows are rendered currently only the last item has it's form's fields populated.
I suspect this has something to do with the fact that all the form fields have the same id's and it is confusing the DOM. But I don't know how to make sure the id's are unique.
Here is a small example:
In my view:
<%= render :partial => 'shared/user', :collection => #users %>
My partial (broke down to just the form) note that I am using the local variable "user"
<% form_for user, :html => {:multipart => true} do |f| -%>
<%= f.label :name, "Name*" %>
<%= f.text_field :title, :class => "input" %>
<%= f.label :Address, "Address" %>
<%= f.text_field :address, :class => "input" %>
<%= f.label :description, "Description*" %>
<%= f.text_area :description, :class => "input" %>
<% end -%>
When the html is rendered each form has a unique id (for the id of the user) but the elements themselves all have the same id, and only the last user form is actually getting populated with values.
Does anyone have any ideas?? :)
Thanks in advance!
Alright, after having some lunch and regaining some brain cells, (and with a little help from Google) I figured this one out.
When passing a collection to a partial like this:
<%= render :partial => 'shared/user', :collection => #users %>
Rails creates a counter variable that you can use to define an index for the form in the form of "variable_counter":
<% form_for user, :index => user_counter, :html => {:multipart => true} do |f| -%>
This adds the index number to the form id as well as all the field id's and solved my little problem. :)
I hope this helps out someone else with this issue. :)

Resources