I'm trying to create an ultra simple paypal custom integration with rails. I'm following Ryan Bates Railscast #141 on this subject and I've simplified it even further. If you have experience with super simple paypal integration, any advice would be appreciated!
I'm attempting to pass everything through my account model. A proof-of-concept.
def paypal_url(return_url)
values = {
:business => 'jwade_1268181180_biz#gmail.com',
:cmd => '_cart',
:upload => 1,
:return => return_url,
:invoice => 2,
:amount => 7,
:item_name => 'Membership',
:item_number => 1,
:quantity => 1
}
"https://www.sandbox.paypal.com/cgi-bin/webscr?" + values.to_query
end
and of course I create a link:
<%= link_to "Checkout", #account.paypal_url(accounts_path) %>
The Paypal detects an error: "Your shopping cart is empty", which is strange because I can see everything my model passes in the URL:
https://www.sandbox.paypal.com/cgi-bin/webscr?amount=7&business=jwade_1268181180_biz#gmail.com&cmd=_cart&invoice=&item_name=Barcoden+Membership&item_number=1&quantity=1&return=/accounts&upload=1
I've found that following the railscast results in that empty cart error message.
Try creating a form to replace the link like:
<div>
<%= form_tag 'https://www.sandbox.paypal.com/cgi-bin/webscr' do %>
<input type="hidden" name="cmd" value="_cart">
<input type="hidden" name="upload" value="1">
<input type="hidden" name="business" value="Your sandbox biz Account">
<input type="hidden" name="item_name_1" value="Some Name">
<input type="hidden" name="amount_1" value="100">
<input type="submit" value="PayPal">
<% end %>
</div>
That will work. Looks that the cart is not created unless you use a post request.
Using :method => :post in the link_to helper will not work.
You can use the button_to helper to create a mini form and replace the link_to in the railcast.
To answer we need to have a closer look at your code.
But perhaps this can help you: A Testable PayPal IPN with Rails 2.3
Related
I have a working twitter bootstrap install and simple form generates the following:
<form accept-charset="UTF-8" action="/find_map" class="simple_form form-inline" id="new_location" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="p5CSoidWaoGMfHY0/3ElWi0XJVg6Cqi9GqWRNlJLBQg=" /></div>
<div class="control-group string required"><div class="controls"><input class="string required" id="location_address" name="location[address]" placeholder="Address" size="50" type="text" /></div></div><input class="btn" name="commit" type="submit" value="Find!" />
</form>
Somehow the "Find!" button won't appear on the same line as the search box. Any ideas?
Thanks!
UPDATE:
Sorry I should have mentioned that all the markup is generated by simple_form based on the following:
<%= simple_form_for #location, :url => find_map_path, :html => { :class => 'form-inline' } do |f| %>
<%= f.input :address, :label => false, :placeholder => "Address" %>
<%= f.submit "Find!", :class => 'btn' %>
<% end %>
So, really, there seems to be an issue with the generated markup, even though I have run the bootstrap install for simple_form, etc.
The above image shows a straight html form
<form class="form-inline">
<input type="text" class="input-small" placeholder="Email">
<button type="submit" class="btn">Sign in</button>
</form>
...above the one generated by simple_form.
I think there are a couple issues here. One is the formatting, and the way simple_form adds a <div> around the input field. #Ron's suggestion of using input_field works for me with simple_form 2.0.1. My example is searching for name in a Contacts table. The following makes the text box and button appear side by side:
<%= simple_form_for :contact, :method => 'get',
:html => { :class => 'form-search' } do |f| %>
<%= f.input_field :search, :placeholder => "Name",
:class => "input-medium search-query" %>
<%= f.submit "Find!", :class => "btn" %>
<% end %>
The other issue is that it seems simple_form usually assumes you want to work with model and field names. The example above uses a :symbol instead of a #model as the first argument as suggested here. But that still generates an input field named contact[search] so you'd have to tell your controller how to deal with that.
I think in this case it may be simpler to not use simple_form and instead use something like the form near the beginning of Ryan Bates' Railscast #240, Search, Sort, Paginate with AJAX:
<%= form_tag contacts_path, :method => 'get', :class => "form-search" do %>
<%= text_field_tag :search, nil, :placeholder => "Name",
:class => "input-medium search-query" %>
<%= submit_tag "Find!", :name => nil, :class => "btn" %>
<% end %>
Now the field is just named "search" and I can consume it in my controller's #index method something like this:
#contacts = #contacts.search(params[:search])
assuming I have this in my model:
def self.search(search)
if search
where('lower(name) LIKE ?', "%#{search.downcase}%")
else
scoped
end
end
It's creating subforms because you're passing input to simple_form. Use input_field instead. (BTW, this also works with simple_fields_for).
You need to customize the control-group and controls div classes to display as inline-block when they are under a form-inline form:
form.form-inline div.control-group { display: inline-block; }
form.form-inline div.control-group div.controls { display: inline-block; }
Adding to Mark's reply:
So, input_field exists to create the input component only, it won't give you any sort of label/error/wrapper. That means you won't get any or tag wrapping the field, you should do that manually in case you want to.
Now about using the form with an object, SimpleForm is a FormBuilder, which means it was created to work with a namespace, either an object or a symbol. SimpleForm's simple_form_for == Rails' form_for, you always need an object namespace to work with.
For such a simple case as a search form, you're better off with simple form helpers such as form_tag, as you've pointed out. There's no need to rely on simple_form_for or form_for for that, I agree and I usually go down that path.
I hope that helps, let me know if you still have doubts.
Change the :html => { :class => 'form-inline' } to :html => { :class => 'form-horizontal' }
can't you move the input button next to input address? I think it will solve the problem
<form accept-charset="UTF-8" action="/find_map" class="simple_form form-inline" id="new_location" method="post" novalidate="novalidate">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="p5CSoidWaoGMfHY0/3ElWi0XJVg6Cqi9GqWRNlJLBQg=" />
</div>
<div class="control-group string required">
<div class="controls">
<input class="string required" id="location_address" name="location[address]" placeholder="Address" size="50" type="text" />
<!-- move the button to here -->
<input class="btn" name="commit" type="submit" value="Find!" />
</div>
</div>
</form>
Please, all people with this problem, don't use fluid layout and be sure you are specifying the HTML5 doctype to the documents.
While registering for openstreetmap, on the terms page, I noticed that clicking the labels didn't check the radio buttons associated with them. Here is the html:
<!-- legale is GB -->
<form action="/user/terms" method="post">
<p>
Please select your country of residence:
<input id="legale_fr" name="legale"
onchange="Element.update("contributorTerms", "<img alt=\"Searching\" src=\"/images/searching.gif?1313181320\" />");; new Ajax.Request('/user/terms?legale=FR', {asynchronous:true, evalScripts:true})"
type="radio" value="FR" />
<label for="legale_FR">France</label>
<input id="legale_it" name="legale" ... type="radio" value="IT" />
<label for="legale_IT">Italy</label>
<input checked="checked"
id="legale_gb" name="legale" ... type="radio" value="GB" />
<label for="legale_GB">Rest of the world</label>
</p>
</form>
As you can see the checkbox id="legale_gb" doesn't match the label for="legale_GB".
Now openstreetmap's website is actually open source so we can read the terms.html.erb:
<!-- legale is <%= #legale %> -->
<% form_tag :action => 'terms' do %>
<p>
<%= t 'user.terms.legale_select' %>
<% [['france', 'FR'], ['italy', 'IT'], ['rest_of_world', 'GB']].each do |name,legale| %>
<%=
radio_button_tag 'legale', legale, #legale == legale,
:onchange => remote_function(
:before => update_page do |page|
page.replace_html 'contributorTerms', image_tag('searching.gif')
end,
:url => {:legale => legale}
)
%>
<%= label_tag "legale_#{legale}", t('user.terms.legale_names.' + name) %>
<% end %>
</p>
<% end %>
I'm a rails newbie, but I can't see anything there that lowercases the id of the radio button tag. What's more, even when I look at the source of radio_button_tag, sanitize_to_id I can't see where this is coming from.
Anyone got any idea what's causing this?
Edit Swapped out label for radio in my description according to answer from
2 things:
Wrong tag, the offender is radio_button_tag (it's capped as expected in the label).
Seems like you're linking to the wrong Rails. According to this project's environment.rb, it's using Rails 2.3.14. If you look at radio_button_tag for that release, you'll see the culprit.
# our pretty tag value is downcased on line 318
pretty_tag_value = value.to_s.gsub(/\s/, "_").gsub(/(?!-)\W/, "").downcase
# although the pretty name is not, oddly
pretty_name = name.to_s.gsub(/\[/, "_").gsub(/\]/, "")
# then the two are combined into the HTML id
html_options = { ..., "id" => "#{pretty_name}_#{pretty_tag_value}", ... }
I would like to use the form_for helper multiple times for the same model in the same page. But the input fields use the same ID attribute (in the HTML), so clicking on the label of a field in another form will select the same input in the first form.
Is there a solution besides settings all attributes manually via :for => "title_#{item.id}" and :id => "title_#{item.id}"?
Using Rails 3.0.9
You can use :namespace => 'some_unique_prefix' option. In contrast to :index, this will not change the value used in the name attribute.
It's also possible to use an array, e.g. when you have nested forms or different forms that happen to have some fields in common: :namespace => [#product.id, tag.id] or :namespace => [:product, #product.id]
I found the answer myself, one can pass a :index option to form_for. That string will be used in the id and for attributes:
<%= form_for #person, :index => #person.id do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
will parse
<form accept-charset="UTF-8" action="/person/11" class="edit_person" id="edit_person_11" method="post">
<!-- Hidden div for csrf removed -->
<label for="person_11_name">Name</label>
<input id="person_11_name" name="person[11][name]" size="30" type="text" />
<input name="commit" type="submit" value="Update Person" />
</form>
Notice it'll change the name of the inputs as well.
I believe you can add this param:
:html => { :id => 'id_i_want' }
I have a form_for I'm making in my view helper that is going to let one user promote another user from a group.
def promote_button_for(group, user)
membership = group.get_membership( user )
form_for membership, :url => group_membership_path( group, membership ) do |f|
f.hidden_field :group_creator
hidden_field_tag 'test', '1'
f.submit( "Promote", :onclick => "return confirm(\"Are you sure you want to promote #{user.email} to an officer?\")" )
end
end
When I submit the form via the button, I don't seem to get any of the hidden field parameters sending to the controller.
Started POST "/groups/1/memberships/6" for 127.0.0.1 at 2011-02-01 01:45:32 -0600
Processing by MembershipsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"VQl/rVX8OVOETv2HE7KtopUc3B19ShoMkUhjJwNlaZs=", "commit"=>"Promote", "group_id"=>"1", "id"=>"6"}
The generated Html looks like:
<form accept-charset="UTF-8" action="/groups/1/memberships/6" class="edit_membership" id="edit_membership_6" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="_method" type="hidden" value="put" />
<input name="authenticity_token" type="hidden" value="VQl/rVX8OVOETv2HE7KtopUc3B19ShoMkUhjJwNlaZs=" />
</div>
<input id="membership_submit" name="commit" onclick="return confirm("Are you sure you want to promote kquiring#gmail.com to an officer?")" type="submit" value="Promote" />
</form>
Any help would be greatly appreciated,
Thanks!
Can you try
f.hidden_field :group_creator, {:value => ''}
You are having this problem because the form_for object is only seeing the string that is generated by the last f.submit tag, while everything else between the form_for and the f.submit is lost.
In this case, the form_for tag does not manipulate the view directly, as it is basically just a string that is returned from the promote_button_for method.
The answer is that you just need to chain the generated tags together, like this:
def promote_button_for(group, user)
membership = group.get_membership( user )
form_for membership, :url => group_membership_path( group, membership ) do |f|
f.hidden_field(:group_creator) << \
hidden_field_tag('test', '1') << \
f.submit( "Promote", :onclick => "return confirm(\"Are you sure you want to promote #{user.email} to an officer?\")" )
end
end
Notice the << \, which concatenates all the generated strings together and returns them to form_for.
I'm using fields_for in my form like so
<%= form_for #user %>
...
<%= f.fields_for :photos do |f2| %>
<%= f2.radio_button :public, 'true' %>
<% end %>
...
<% end %>
Here are the radio buttons it generates:
<input id="user_photos_attributes_0_public_true" name="user[photos_attributes][0][public]" type="radio" value="true" />
<input id="user_photos_attributes_0_id" name="user[photos_attributes][0][id]" type="hidden" value="1" />
<input id="user_photos_attributes_1_public_true" name="user[photos_attributes][1][public]" type="radio" value="true" />
<input id="user_photos_attributes_1_id" name="user[photos_attributes][1][id]" type="hidden" value="4" />
<input id="user_photos_attributes_2_public_true" name="user[photos_attributes][2][public]" type="radio" value="true" />
<input id="user_photos_attributes_2_id" name="user[photos_attributes][2][id]" type="hidden" value="5" />
...
I have this in user.rb
has_many :photos
accepts_nested_attributes_for :photos
When form is submitted I get this error:
Error during failsafe response: ActionView::Template::Error
TypeError (expected Hash (got Array) for param `photos_attributes'):
Does anyone know why this is happening?
Btw, I'm using Rails 3.0.0.rc2
How are you saving your model?
If you inspect the params hash, you will get something like:
{ :user => {:photo_attributes => [{:id => 1, :public => true}, {:id => 4, :public => false}] }, :your_other_params => ... }}
So a User.new(params[:user]).save should work. Unless you are passing each hash of attributes instead of the array. See this article if you need a more in-depth detail.
What is in your params hash? That'd help you to trace the problem.
BTW, if you want a "true/false" behavior (I assume that because of the is_public property), rather than "present/non-present", a checkbox should be used. Radio buttons are for mutually exclusive options.
I recently had the same problem. Instead of trying to get the params through the controller, we used the Chrome tools to see what was being passed in the params and found that we were passing an empty hash/array e.g. params[] versus params[:something]