Rails generic form for with Braintree form builder - ruby-on-rails

I have a similar form like this:
<%= form_for :customer,
:params => #result && #result.params[:customer],
:errors => #result && #result.errors.for(:customer),
:builder => BraintreeHelper::BraintreeFormBuilder,
:url => Braintree::TransparentRedirect.url,
:html => { :autocomplete => "off"} do |f| -%>
First name: <%= f.text_field :first_name , :value => "John"%><br />
<%= f.submit %>
<% end %>
When I try to add the value to that text field is not letting me. However, if I take the builder from the form_for tag, I am able to do so. Anyone has had experience with Braintree form builder?

Siwei Shen is on the right track...
Form builders in Rails help you tie your forms to models in your application and generate values, names, and IDs for your form elements that correspond to model attributes. They're tremendously helpful, but sometimes it's necessary to override what they give you.
The example form builder you found in the Braintree Rails example app provides some things that are helpful since TR forms post directly to our gateway rather than your app and gives your form fields attribute names and default values that Braintree's gateway will expect as well as helps to populate validation errors which are returned to your app.
In this particular case, the form builder is ultimately merging the values for the inputs (including :first_name) with either the existing value (if any) or nil (over-writing what you've passed in.
https://github.com/braintree/braintree_ruby_examples/blob/master/rails_tr_checkout/app/helpers/braintree_form_builder.rb#L22
Feel free to modify the form builder to suit your needs!

when using "form_for", the default value is the form-object's value. e.g.
#person = Person.new(:first_name => "Jack")
<%= form_for :person do |f| %>
<%= f.text_field :first_name %>
<% end %>
and you will get a text input with the default value "Jack" :
<input type="text" value="Jack"/>
so, when using f.text_field, you are not able to set the default value, unless you change the form-object ( here is the #person).
If you want to set the default value, I suggest you either use "form_tag", which does not have "form object", or use jQuery to implement the default value stuff.

Related

Adding a confirmation checkbox to a form in Rails not tied to some attribute?

Noob question! :)
I have a form, that has basically no point other than call some_action. The reason I use a form for this, is because we have a specific styling for this in our large website.
<%= styled_form_for(#user, :url => some_action_user_path #user)) do |f| %>
<%= f.save_button %>
<% end %>
I thought, since it's a form, I should be able to put a checkbox in there. It should have no other goal than confirming the user wants to do this action indeed. E.g. "Yes, I want to do some_action to the user model".
How would I make a checkbox that does not really change any attribute or affect anything - Other than that it should be checked for the form to submit?
This is probably dead simple, but according to the documentation and various error messages I should provide arguments such an attribute (which I don't want...)
form_for is meant to work on attributes of a model, which is what all the documentation you are reading is telling you. So if your model had a boolean column you could easily attach a check box to it.
If you ever want a form (or specific tag) that does not follow this, you can use the _tag version of these methods. For example, form_tag or, in your particular case, check_box_tag.
Example:
<%= styled_form_for(#user, :url => some_action_user_path #user)) do |f| %>
<%= check_box_tag "do_some_method" %>
<%= f.save_button %>
<% end %>
NOTE: You will only get a param entry for :do_some_method if it is checked off. If you want to get a param regardless, you have to add a hidden_field_tag before it.
<%= hidden_field_tag "do_some_method", "no_dont_do_it" %>
<%= check_box_tag "do_some_method", "yes_do_it" %>
Now if the checkbox is selected you'll get params[:do_some_method] set to "yes_do_it"; if it's not checked off, instead of getting no entry, you'll get params[:do_some_method] set to "no_dont_do_it".

Using Rails' form helpers without a model

For various reasons I need to avoid traditional nested forms (nested in the sense of treating the fields like a sub-group of the primary model for the page), but still want to keep fields grouped together with an index-style naming, so I have this:
<%= simple_fields_for :crate_request do |ff| %>
<%= ff.input :_create, :label => "crate needed", :as => :boolean %>
<%= ff.input :details, :as => :text %>
<% end %>
The rendered fields are named as expected (with names like params[:crate_request][:details]) and all looks well until I submit a form with validation errors and it has to come back to re-render. The fields don't prefill with the submitted values stored in the params hash. Although I'm using simple_form, it doesn't seem to just be a simple_form issue. The native Rails helpers appear to do the same.
So the question: is there any way to have the fields automatically pre filled from the params hash again without having to manually set the value of each field from params?
You would just need to pass some object as an extra argument to simple_fields_for.
As the form builder expects the object to have field accessors as methods, but you've only got a hash (params[:create_request]), you can use OpenStruct to create an object which would translate missing method calls to hash lookup.
The final solution then would look something like this:
<%= simple_fields_for :create_request, OpenStruct.new(params[:create_request]) do |ff| %>
...
<% end %>
Replace
<%= ff.input :details, :as => :text %>
by
<%= input :details, :as => :text %>

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

Using the textarea helper in Rails forms

Why does this code show an error in text area?
<%= form_for(:ad, :url => {:action => 'create'}) do |f| %>
<%= f.text_field(:name) %>
<%= f.text_area_tag(:text, "", :size => "50x10") %>
<%= submit_tag("Submit") %>
<% end %>
The FormHelper method is text_area, not text_area_tag.
Use either of the following:
<%= f.text_area(:text, size: '50x10') %>
or:
<%= text_area_tag(:ad, :text, size: '50x10') %>
The f variable that you are creating in the first line is a reference to your FormBuilder. By default it references ActionView::Helpers::FormBuilder or you can create your own.
The FormBuilder helper for textareas is called text_area. FormBuilder helpers are smarter than regular HTML helpers. Rails models can be nested logically, and your forms can be written to reflect this; one of the primary things FormBuilder helpers do is keep track of how each particular field relates to your data model.
When you call f.text_area, since f is associated with a form named :ad and the field is named :text it will generate a field named ad[text]. This is a parameter convention that will be automatically parsed into a Hash on the server: { :ad => { :text => "value" } } instead of a flat list of parameters. This is a huge convenience because if you have a Model named Ad, you can simply call Ad.create(params[:ad]) and all the fields will be filled in correctly.
text_area_tag is the generic helper that isn't connected to a form automatically. You can still make it do the same things as FormBuilder#text_area, but you have to do it manually. This can be useful in situations that a FormBuilder helper isn't intended to cover.

Best way to reload parts of a form

I want to reload a part of a form generated with the form_for-helper via AJAX.
After reloading the part I still want to have access to the form object.
How can I do this?
Best regards
I am not sure if your are using different terminology than I've heard, but what do you mean "still want to have access to the form object"?
Do you mean access to it in JavaScript? That should still work as long as you don't overwrite the form tags.
Do you mean in the html.erb code generating the partial? That doesn't really make sense, because that form_for object has already generated its html tags and gone out of scope. You need to use to the regular form of the helpers that takes the name of the object as the first parameter. There is no problem with this working with the tags generated by the form_for version of the helpers.
So, in your main page:
<%= form_for :person, #person, :url => { :action => "create" } do |f| %>
<%= f.text_field :name %>
<div id="reloadable">
</div>
<% end %>
And in your partial that fills that div:
<%= text_field :person, :name %>
No step 3.

Resources