Ruby on Rails: Multiple Same Input Fields in Same Form - ruby-on-rails

Have a page where there are multiple input fields of the same thing, Posts. Right now, when a user enters in a question for, let's say 3 fields, the only one that saves to the database is the last one. Whereas, it should save all three and give them each it's own post_id. Also; if the user doesn't enter anything in for the other fields, it should not save in the database either.
<%= form_for(#post) do |f| %>
<%= f.text_field :content %>
<%= f.text_field :content %>
<%= f.text_field :content %>
<% end %>

It's failing because what you've got above evaluates to thee html field with the same name/id and the browser will only post the value for one of them. If they are different fields, then you need to give them unique names/ids or you need to create them as an array eg:
<%= f.text_field_tag 'content_array[]' %>
or, if you want these to be a set of posts - you'll need to add multiple sub-forms (one for each post) using a custom form.

What you can do is convert to html and as an array
in your form:
<input`type="text" name="post[content][]" id="content_id">
Then, in your controller:
content_details = params[:post][:content]
content_details.each do|cont|
#post = Post.new(content: cont)
#post.save
This will loop through all of the content created and save each.

Related

Storing user input value in controller

I have a controller named Welcome with view called index.
In my index view i have created a small form as such.
<%= form_for :location do |f| %>
<%= f.label :Longitude %><br>
<%= f.text_field :integer %>
<br>
<br>
<%= f.label :Latitude %><br>
<%= f.text_field :integer %>
<p>
<%= f.submit %>
</p>
<% end %>
In this form the user can enter some integer value for longitude and latitude. Once the user enters value for longitude and latitude. They click submit. Upon submit i would like to store these values in my controller. So i am using the following method where i have two instance variables taking values from the form.
def index
#long = params[:longitude]
#lat = params[:latitude]
end
In my routes.rb I have
get 'welcome/index'
post 'welcome/index'
Please tell me where i went wrong. Also if someone can suggest a better way of doing this also i would appreciate it i am new to rails and i want to learn the correct way of doing things so i don't create bad habits early on.
The reason it's not working is because your fields are both named :integer, and since they share the same name, the browser will only send one value.
So, with your code, if you filled in the first field with 'a' and the second with 'b', your params would contain something like this:
{ location: { integer: "aaa" } }
Which obviously isn't what you want! If your HTML looked more like this (I've stripped the layout stuff to make things clearer):
<%= form_for :location do |f| %>
<%= f.label :longitude %>
<%= f.text_field :longitude %>
<%= f.label :latitude %>
<%= f.text_field :latitude %>
<%= f.submit %>
<% end %>
Then you could access the params in your controller params[:location][:longitude] and params[:location][:latitude]
A good idea to see the difference between the effect of your form vs this form would be to inspect the html. Take a look at the input name attributes, and label for attributes and see how they match up with the params Rails receives. Also, when you post the form, be sure to look in your server log to see the params! :)
After reading your question, I think you want to see how controllers, views and models work. For learning purpose you can generate scaffold and study the generated code.
For example, generate a model GeoLocation, related controller and views by this:
rails g scaffold GeoLocation longitude:string latitude:string
Now fire up rails server and browse http://localhost:3000/geo_locations/new and save your long, lat. I wrote this answer to give you some guidance.
You can follow these excellent books:
The book of Ruby
The Rails 4 Way

Rails - Multiple forms, different Models (Objects), one submit button

I have a view with 3 forms, Schedules, Workouts and Exercises, all behaving like an edit form, each. And one submit(save) button in the all the view.
When I click on the save button. Every data changed on those forms should be updated after click.
What is the best solution for this ? Javascript updating each data separated ? How to do that ? Is there a more Rails way to do this easily ?
My difficulty is how to integrated all those models in one view, while all this is happening in the show(view) from the Student model.
If you're implementing something like a profile / edit page (where you can save all the records at once), the two ways I would look at would either be to save the forms via Ajax, or use a single submit method to handle them
Ajax
The ajax method would be the most conventional:
Every form you submit will go to the form's own update method in the backend
Each form could be handled by a single button, but it's best to split them up
#app/controllers/profile_controller.rb
def edit
#schedules = Schedule.all #-> not sure how many records you're using
#workouts = Workout.all
#exercises = Exercise.all
end
#app/views/profile/edit.html.erb
<%= form_for #schedule do |f| %>
<%= f.text_field :test %>
<% end %>
# -> other forms
<%= button_to "Save", "#", id: "save" %>
#app/assets/javascripts/application.js
$("#save").on("click", function() {
$("form").submit(); // we'll have to define the form to submit
});
Single
If you submit all the forms as one, you'll have to encase them all in a single form, as sending different errors. This could be achieved by using _, and handled in the backend by looping through the different params, saving each one individually.
I'd do this:
#app/controllers/application_controller.rb
def submit
types = %w(schedules exercises workouts)
for type in types do
type.constantize.update_attributes()
end
end
This allows you to create a form with the different data types submitted in the same action:
#app/views/profile/edit.html.erb
<%= form_tag profile_submit_path do %>
<%= fields_for #schedules do |f| %>
<%= f.text_field :title %>
<% end %>
# -> fields_for for the other objects
<% end %>
This will allow you to send the updated objects to your controller, allowing them to submit
If all of your models (Schedules, Workouts and Exercises) are associated, using fields_for should be a good option.
From the above link:
<%= form_for #person do |person_form| %>
First name: <%= person_form.text_field :first_name %>
Last name : <%= person_form.text_field :last_name %>
<%= fields_for :permission, #person.permission do |permission_fields| %>
Admin? : <%= permission_fields.check_box :admin %>
<% end %>
<%= f.submit %>
<% end %>
Read the guides.
You could have some simple javascript that iterates over all form tags and submits each of them.
Alternatively, if you are going to use javascript anyways, you could follow an AJAXish auto-save approach upon changing any field.
But I think it might be cleaner if you just had one form for multiple models, using fields_for.

Mentioning user username in comments (#mention) - Rails

In my rails app, if a user mentions another username in a comment by using the # character, such as #max i'm trying to add autocomplete to suggest a list of users and then automatically create a link_to (username, user_path(user)
This is what I have in my comment partial:
<%= form_for [commentable, Comment.new] do |f| %>
<%= hidden_field_tag :commentable_type, commentable.class.to_s %>
<%= hidden_field_tag :commentable_id, commentable.id %>
<p>
<%= f.text_area :body %>
</p>
<p><%= f.submit "Submit" %></p>
<% end %>
I'm trying to use this gem: https://github.com/ichord/jquery-atwho-rails
It says to bind the text area with
data = ['tom','john'];
$('textarea').atwho({at:"#", 'data':data});
Where do I actually put this? Can I do something like data = User.all? Should I just be using a regular expression to do this?
I think the reason that data = User.all isn't working is because User.all will return an array of User objects. What you want to do is retrieve those User object usernames (or whatever you want the autocomplete to use, and store that in data instead.
You might try something like
#usernames = User.pluck(:username)
to get all the usernames. Then, in your partial:
data = <% #usernames &>
$('textarea').atwho({at:"#", 'data':data});
This is assuming of course that your partial is an .erb file where you can embed ruby code.
You can do something like this:
<script>
data = <%= raw User.pluck(:username).compact.to_json %>;
$('textarea').atwho({at:"#", 'data':data});
</script>
You might want to move the loading of the usernames into the controller or a helper method. The whole sniplet might belong into an view partial to keep things organized. And it might not be the best idea to load all usernames into the view when there are too many users in the database.

Ruby on Rails 3.2.13 - How Do I Reference Fields in fields_for?

I have a Modality model with a related model ModalityItem. Modality has many :modality_items and ModalityItem belongs to :modality. One of the fields I want to display is a name field from MediaLibrary where the id matches media_library_id in ModalityItem.
I plan to allow up to 15 ModalityItem rows for each Modality. The Rails application will display either blank rows for ModalityItem when new records need to be added or ModalityItem row data when records exist.
Here is the code I have in the edit method of the modalities_controller where I can also rename the Modality. I have created array #items (Array.new(15)) and load each array element with either a row from ModalityItem or ModalityItem.new. If no ModalityItem rows exist for the selected Modality, the entire array will have 15 elements of ModalityItem.new. If ModalityItem rows exist I want to join the row to the corresponding MediaLibrary row and display its name on the edit view.
#modality = Modality.find(params[:id])
#modality_items = ModalityItem.joins('JOIN media_libraries ON media_libraries.id = modality_items.media_library_id').where("modality_id = ?", #modality.id).all
#items = Array.new(15)
count = 0
while count < #items.size
if #modality_items && count < #modality_items.size
#items[count] = #modality_items[count]
else
#items[count] = ModalityItem.new
end
count += 1
end
Here is my code in the edit view.
<%= form_for(#modality) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<p style="font-weight: bold; font-size: 114%;"><%= link_to "Return to Manage Modalities", modalities_path %></p><br>
<%= f.label :name, "Modality Name:" %> <%= f.text_field :name %><br><br>
<%= f.fields_for :modality_items, #items do |item| %>
<div class="modality-class">
<%= item.label :media_library_id, "Media Library" %><%= item.text_field :media_library_id %>
<div class="short-label"><%= item.label :rank, "Rank" %></div><%= item.text_field :rank %>
</div><br><br>
<div class="modality-instruct">
<%= item.label :instructions, "Instructions" %><%= item.text_field :instructions %>
</div><br><br>
<% end %>
<%= f.submit "Save changes to Modality", class: "btn btn-medium btn-custom" %><br><br>
<p style="font-size: 114%; font-weight: bold;"><%= link_to "Delete this modality?", #modality, method: :delete, data: { confirm: "You sure you want to Delete this modality?" } %></p>
<% end %>
I have only used fields_for with a collection_select statement where I captured the id numbers of multiple items in my drop down list in an array. I used those ids to create another table related to the main table I was updating.
In this scenario I want to gather the information entered on the screen, loop through it and create my records. I plan to delete all existing ModalityItem rows for a Modality and recreate them each time. When I used fields_for with a collection_select I set an instance variable #whatevername equal to params[:whatevername] then looped through the ids. With the code I have included I would set #modality_items = params[:modality_items] then do something with it I guess. I have the following questions about what happens when someone enters data and clicks the button to update:
What does params[:modality_items] contain? Is it an array with all the text fields from the view?
Will #items be updated with the data from the form or will I have to save params[:modality_items]?
I'm sure this is basic information but this is my first time doing this and have been unsuccessful in finding the answer after doing many online searches about fields_for off and on for months now.
Note: I currently do not reference the name from MediaLibrary in my view because I need more information about how to access fields in fields_for before proceeding. I also have the issue of :name being in both the Modality and MediaLibrary models. The name in Modality is updatable but name of MediaLibrary will be display only in the fields_for statement.
Any help would be appreciated.
What does params[:modality_items] contain? Is it an array with all the
text fields from the view?
Nothing. You really SHOULD look at your log files to see what is inside the params hash.
The :modality_items is an array nested inside params[:modality] so you get
params[:modality][:modality_items]
So form_for(#modality)gets you params[:modality] and then the f.fields_for (note the f piped in from the form_for) arranges for the fields_for params to be nested inside the modality hash as an array
Will #items be updated with the data from the form or will I have to
save params[:modality_items]?
If you are using accepts_nested_attributes_for :modality_items inside your Modality model for the modality_items_attributes and those attributes are accessible (not protected from mass assignment then your rows will automatically be updated or inserted as appropriate.
Basically accepts_nested_attributes_for accepts attriobutes nested inside the params hash that correspond to the same name.
This link from the official documentation explains clearly how the params hash is organised
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
And read here for more details on fields_for http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for

passing dynamic params field

Im working with Rails 3.0.3
I want to create bills in my App. Each Bill has many entries (Material, how much of that and the Price)
The Problem i have, is that i want to write the bill and the entries and then save both at the same time. So when you click on save Bill, the Bill + each Entry should be created (saved in the db).
I can write the bill + each entry (with javascript), but i dont know how i could save both of them. Right now i can only save the bill it selft. Is it possible to pass a dynamic field via params so i can handle that in the bills controller to save? How would you implement this?
What you are looking for is called nested form, you have a main form for your bill and multiple forms that are dynamically generated as children of this general form using fields_for like this:
<% form_for #bill do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<% f.fields_for :entry do |builder| %>
<%= render "entry", :f => builder %>
<% end %>
<p><%= f.submit "Submit" %></p>
<% end %>
Of course you will need some js for the dynamic creation of the different entries, here you have a couple of railscasts that will be helpfull.
Nested model form Part 1
Nested model form Part 2

Resources