Render form with errors and file inputs - ruby-on-rails

I have a form with nested attributes for attachments.
Everything seems to be working fine till the moment user submits the form with error on a field other than the attachments.
At the first submit of the form I re-render the form displaying the errors but the nested fields for the files he/she attached don't display their values, they are empty. Thus, when user fixes his/her error, the form submits with no attachments.
How should I handle this; I want when rendering the form with errors to have the file inputs with the previously submitted values. If you suggest another approach be my guest.
Sample code:
= simple_nested_form_for foo do |f|
= f.input :name
= f.fields_for :attachments do |af|
= af.input :attached_file
= f.submit 'Create'

if you want to send image of file through ajax then u cant send it directly as ajax is used to send data to server without refreshing the current page it accepts less amount of data.
Other way to send file through ajax is to either hack or else the simple one use remotipart gem remotipart

Related

Different action on submit of form depending on a variable's value

I have a checkout form which includes a field to enter a coupon code. Currently, the form always posts to a payment merchant. However, I want it to take a different action/route if the amount due is 0 because of the coupon code.
The view page contains:
# Form where to enter coupon code
<%= form_for #coupon, method: :post, url: {action: "check_coupon", :controller => 'coupons', format: 'js'}, remote: true do |f| %>
<%= f.submit "Submit Coupon" %>
<%= f.text_field :couponcode, :placeholder => "Enter coupon" %>
...hidden fields...
<% end %>
# Form sent to payment merchant
<form action="https://secure.***.com/order.html" method="post" >
<input type="hidden" name="payment" value="<%=#payment%>" class='js-couponpayment' />
...other hidden fields...
</form>
The controller method check_coupon just validates the coupon and sets some of the variables that exist as hidden fields in the form to be send to the payment merchant. This includes a variable called #payment which specifies the sum to be paid. This sum gets updated based on the coupon entered. Ajax is used to display the updated sum on the screen but to keep it secure check_coupon, and not the script which is only for the number shown on screen, sets the actual sum to be send to the merchant.
If #payment is zero, I would like the second form not to post to the merchant, but instead redirect to root_path with a flash message. How can I do this? How can I make the action for the second form variable depending on the updated value for #payment (preferably using Ruby and not javascript)?
From what I understand, you don't want to update the payment hidden field with Ajax because you think rendering it server-side would be more secure. But, this is not the case AFAIK, because regardless of where you render, if you are still displaying the form and making users submit the form, there is always possibility of end user fiddling with the hidden field values. After all, from wherever you rendered, it will always end up the same HTML. So, security must be coped with other measures such as making an HMAC authenticity hash with a private key.
With the security considered, a pure ruby solutions would be to not use ajax at all. Instead make check_coupon action render a completely new page that checks the sum after coupon code and render the updated payment form again if sum > 0, otherwise redirect to root_url with flash.
But above solution costs a full page reload and reduces interactivity(user has to wait for the page reload). If you don't want that, you can make you ajax response send back a script that both updates the payment form and the sum user sees. Keep in mind that, with rails, you can still use ruby to render the payment form server-side. An eg. js response would be
$('#container-div-of-payment-form').html(<%= j render("payment_form_partial")%>);
//code to update the sum user sees here
Within your payment_form_partial, you can check if the updated sum is zero or not and sets the form url accordingly.
Hope you found this useful.

Display money-rails value in nested form

I have a nested form where a user can add multiple instances of a class. This nested form is part of a larger wizard (multi-step form) where the user can go forwards and backwards through the process.
In my rails application I'm using the money rails gem. When a user goes backwards in the wizard, I'd like to populate the fields so they can see what they've previously entered. Up until now, I've had no issue doing this with other nested objects. However, displaying a money field is stumping me.
# the field
<%= f.text_field :guarantor_net_worth, :value => ( f.object.guarantor_net_worth_cents.nil? ? nil : f.object.guarantor_net_worth_cents ) %>
# In console when I see if there is a value assigned to an object that I'm testing
guarantor_net_worth_cents: 4564600, guarantor_net_worth_currency: "CAD"
The thing I can't seem to figure out is when I set :value => f.object.guarantor_net_worth_currency, the field displays CAD, but won't seem to display the cents. To debug futher, I used puts to see the ID's of the objects I was creating and searching them in console and they are being created properly with the values being passed through params as they should.

Ruby on Rails 3, forms, ajax, nested, in-place editing, one-by-one. Best practice

Assume, that I have a complex nested form with many fields.
I want to edit its fields one-by-one in ajax way, so that every time I see form - it is in 'show' style (without fields to change information), but with possibility to switch any particular field or group of fields to 'edit' mode with it's own 'save' or 'update' button.
Solving this kind of problem, I ended up with two ways:
Extended use of Ryan Bates' complex-form-examples.
The disadvantage of this way is that every field (or group of fields) requires it's own code (i.e. javascript: 'insert_fields'), which renders corresponding 'edit' style form, so it results in page is overwhelmed by javascripts.
Second - is unified procedure of loading corresponding edit partials through ajax through special controller action (i.e. get_partial), which "render :do updates" given field's area by 'edit' form.
For given field or group of fields i have partials for 'edit' and for 'show'. When i need to switch that field to edit mode i send request (link_to ...,'/.../get_partial?partial=foo',:remote => true) with necessary params by ajax, and some controller#action renders that partial by javascript.
I think that second approach is better one, but I can't figure out how optimize it the best.
Are there any more elegant solutions to this problem?
What if you generated a normal 'edit' form (with all the nested fields, etc), and then had the javascript hide the fields and add the text of the field and an edit link next to it. So for example say your form looks like:
= form_for #foo do |f|
= f.text_field :name
and your javascript would do this to it (1):
= form_for #foo do |f|
= f.text_field :name, :class => "hide"
<the value of the field here>
= link_to "edit", "#"
then make your javascript add a click event to the edit links that, when clicked, does:
= form_for #foo do |f|
= f.text_field :name
= f.submit "Save"
then you'd need more javascript that makes the save button submit the form (ajax), and go back to (1) above

How can I separate error_messages from two forms on one page?

I have two forms in one view updating the User Profile. One Form is to Update my name etc. and one is to change my password.
Profile Form:
- form_for #user, :url => account_path do |f|
= f.error_messages
...form fields here...
Password Form:
- form_for #user, :url => account_path do |pf|
= pf.error_messages
...password fields here...
As you can see they both point to the same update action in the users controller. If I type in a invalid password both error_messages show me the same error message.
How can I output separate error messages per form?
You need to use error_message_on to output the error message for one specific attribute. Keep in mind, that its output is not very meaningful by itself, as it lacks the attribute name and the header message that error_messages/error_messages_for include by default. You can use :prepend_text and :append_text to customize the messages (look at the API docs for more info).
Note that for the password part, all you have to do is call error_message_on :password, but for the rest of the form fields, you have to call error_message_on once for every attribute, apart from :password. You could write your own helper to avoid that.

How to show the content of the form just entered in the ":confirm =>" option on Ruby on Rails

I am trying to have a way of confirming the information entered before actually saving it to the DB
Considered making an individual confirmation page as discussed here
Ruby on Rails: Confirmation Page for ActiveRecord Object Creation
However my form includes an attached file using paperclip which makes it more of a hassle to implement.
I thought of just having a :confirm => pop up that would show the information that the user
had just entered.
The problem is how to show the information that the user had just entered, for example
<% form_for #entry, :html => { :multipart => true } do |f| %>
<%= f.error_messages %>
<%= f.label :name %><br />
<%= f.text_field :name %>
<%= f.label :file %><br />
<%= f.file_field :file %>
<%= f.submit 'Create', :confirm => "????? " %>
<% end %>
Given that your loading attachments it may not be a bad idea to render a staging view including information derived from the attachment allowing the user to confirm. As in display the file if it's an image, or the first paragraph of text if it's a text file, etc.
It's going to take more work than the just adding a confirm pop up, but I feel the enhanced user experience is worth the extra effort.
I'm not familiar with the way that paperclip works. So you're mostly on your own for the intimate details.
You will probably have to create a record before the staging view can be rendered with the sample of the uploaded file. To accomplish that I'd set up an "active" column on the model in question, that defaults to false.
Usage would look something like this:
User complets new form.
Attachment is updated and records are saved, with the active field set to false.
Redirected to confirmation page that is essentially the show page with a confirm link/button and a cancel link/button
a. When the confirm link/button is clicked it sends a request to the controller triggering the update action on this record setting active to true.
b. When the cancel link/button is clicked it sends a request to the controller trigering the destroy action on this record.
All that's left is to set up a recurring task to remove objects that are inactive and were crated long enough ago that it's safe to assume the user has just ended the browser session.
The confirm option for the Rails submit method can only take a text value.
If you want to dynamically generate the confirm text, one way you could do it is to write your own HTML submit tag, and write custom javascript to analyse the fields you want to use in your generated text.
Or you could use the Rails submit method, but use something like JQuery to add an event handler to it.
I'd just throw my js into an onclick handler. That's all Rails does.
<%= f.submit 'Create', :onclick => "confirm('Name is ' + $F('entry_name'));" %>
(note, didn't test that, but it looks close. confirm is a core js function, not part of any lib)

Resources