Passing large data sets between forms? - ruby-on-rails

I'm trying to build a step by step form that transforms large sets of data in batches. I want to have the data saved to the database only on the last step. The way I've seen to create forms like this is to save the data in session storage.
session[:stored_data] = large_dataset
But this gives me a CookieOverflow error when trying to save to it.
What are my other options? Am I stuck with saving the data to the database between steps?

You could actually store it in the form itself.
On the first form you might have...
<%= f.text_field :name_of_dog %>
...and on the second form you could store the first form's fields but in a hidden field.
<%= f.hidden_field :name_of_dog %>
This way you carry the data through all the subsequent forms and when the final form is submitted, you have the complete data you need to persist to the database.
I do this for single db records where the amount of information may be overwhelming for the end user or when you're displaying a limited amount of record data per page (say, because you're in an iframe).
I often also have an attr_accessor called something like :page so when the create or edit action is called I know which page has submitted.

Related

How can I update multiple rows in a Model using a form in Rails?

I'm trying to make a small app in rails where investors can see their balances. The balances are updated by an admin.
The investors are all in a Model called User - is there any way to set up one form in one view where User.balance can be updated for all Users?
The fields in the view can be populated using a <% User.each do |u| %> loop, I guess, but how can I handle the data in the controller?
Thanks!
It might be convenient to implement this in an index view, by using an Ajax-capable gem such as best_in_place, which would let the values be edited in place without the form being submitted.

How can I allow users to choose the columns shown in Rails?

I have a model named Employee that has over a dozen fields making it impractical to display all fields at once. I would like to allow users to choose which columns are displayed by using either a multiple select box or a list of checkboxes, the result of which would ideally be stored in memory, not in the model since nothing will be saved long term, and be accessible for a loop to display the appropriate columns.
A sample of the view might be like so:
<% for employee in #employees %>
<tr>
<% for col in col_list %>
<td><%= employee.col %></td>
<% end %>
</tr>
<% end %>
where col_list is the list of columns selected by the user.
A better approach might be to output all the columns server side and do the filtering with javascript in the client. There are several libraries for this such as jQuery Datatables.
You can combine this with a preferences model which is persisted to the session or Redis instead of the main RDBMS if you want to remember the user prefs.
(Yes, you can use models for objects not stored in the DB. It gives you all the rails awesomeness of validations, form and param binding etc.)
As it is described, there is nothing particularly complicated in this feature.
If you have the users logged in somewhere, you can store a serialized list of columns somewhere in a preference for the user. The list of columns should probably be sanitized to avoid showing private columns.
If the user is not logged in, or you want a less persistent approach, simply store the list in a cookie.
If the list is not set (aka the cookie is empty), set it to a default or just render a default list of attributes.

How do I create a fields_for a potentially unlimited number of children objects?

I'm making an application that involves booking appointments for users. I have a User model and an AvailableDate model. The user has_many availble_dates and the AvailableDate belongs_to user.
I want to present a form for the user so that they can mark a couple of dates in a calendar and each of the dates they mark will become an AvailableDate object tied to that user.
At the moment my solution is to do all the work that a form_for helper would normally do manually. This involves a lot of javascript and is generally just getting far too messy.
I can't figure out how I should make a form_for tag work when I need to create potentially infinitely many dates. In theory a user could keep marking off dates in the future as available. If I knew how many dates I needed to create for a user, I could do user.available_dates.build, N times. But this doesn't work here.
Can anyone help? It like this problem should be pretty common. Am I designing my application wrong?
One technique is to render the fields for your association once, outside the form.
When the user performs whatever interaction that should create a new set of inputs you use javascript to clone the initial set of fields and insert them into the form. The one thing you need to do is change the name of these inputs so that they are unique. Usually people use the current time in milliseconds for this unique identifier.
Been there & have found several resources to help: Tutorial & Cocoon
The bottom line is you need to ensure child_index is unique for each field. The tutorial I use has child_index: Time.now.to_i to create a truly unique id, consequently allowing you to add as many fields as you want
The best way to do this:
Render fields_for as a partial (passing your form builder object)
When you want to add new field, create ajax_field action
Make ajax_field view have its own form_builder
Both your original & ajax_field forms will call the partial
On front-end, you can use JS to GET new form action & append field to page
I can give you code if you want

Create objects in form with the same value

I need to build a form that creates 3 records but there is a repeated field in all of these records (the users name).
#competition = Competition.find(params[:competition_id])
#entries = Array.new(3) {#competition.entries.build()}
The entry has the following fields:
Name - String
Description - Text
With this current method the user is required to enter their Name in to 3 different boxes for the three different record entries.
What is the rails approach in stopping the user from having to enter in the same data 3 times?
You need not ask the user for their name three times.
Look into using the nested form_for helper. Something along the lines of
= form_for [#user, #competition] do |f|
…assuming this is what you want to do. Also, when the form is submitted, you can fill in the duplicate fields before saving the object.
Disclaimer: It's been a while since I did Rails. No Rails 4 experience.
Redesign the model so that the repeated attributes are in a has many association with the ones that are always changing. This will give greater flexibility and control in the future.

How to update sum through Ajax in Ruby on Rails 3?

I am building an Invoicing application where an Invoice can have various Items.
In the invoice view I have a row like this for every item:
<%= f.text_field :price %>
<%= f.text_field :quantity %>
A new item can be added to an invoice using Ajax, i.e. without resubmitting the page.
This works pretty well.
It would be nice, though, if the total of all the items would get updated through Ajax as well, without the user having to resubmit the page every time.
Can anybody tell me how this can be done?
Thanks for any help.
You should considering using some kind of front end MVC or MVVM framework to handle this. Take a look at knockoutjs:
Simplify dynamic JavaScript UIs by applying the Model-View-View Model (MVVM) pattern
http://learn.knockoutjs.com/#/?tutorial=collections <-- this tutorial shows almost exactly what you would be after.
Basically, you would setup a viewModel that would represent your view which would have a collection of line entries, this would be "observable" which means in knockout language whenever it is changed (added to or deleted from) your binding to it would be updated. For example it could be a with 's bound to each line item.
Then you can have a calculated observable which would update automatically
It depends on your existing code. Do you submit / receive data in JSON format? Try to use some kind of client-side processing (plain javascript, jQuery or other framework).
Or you use more traditional Rails :remote form with js.erb templates? If so, you can update the invoice total in the create.js.erb . Something like (I assume the invoice total is wrapped with a tag with id="total", item belongs_to invoice, invoice has total field)
... # your current code
$("#total").update("<%= escape_javascript(#item.invoice.total)%>");
Same for delete and update actions.

Resources