Sending POST request in Rails - ruby-on-rails

How would I go about sending an HTTP POST request in the following format in a Rails setup:
curl https://api.venmo.com/v1/payments -d access_token=4e4sw1111111111t8an8dektggtcbb45 -d email="someemail#gmail.com" -d amount=5 -d note="Delivery."
I'd like to have users input the email/amount/note parameters into a form on a webpage, then pass that data (when the user clicks the submit button) into a Controller where the access_token parameter is stored to then fire off the POST request.
So far I've tried setting up the Controller with this method (and calling it from the view html.erb):
def make_payment
if !params[:access_token].nil?
form_data = {
"email" => #email_to,
"amount" => #amount_to,
"note" => #note_to,
"access_token" => :access_token
}
url = "https://api.venmo.com/v1/payments"
request = Net::HTTP::Post.new(url, form_data)
response = http.request(request)
end
end
Here's my current view setup:
<div class="box box-warning">
<div class="box-header">
<h3 class="box-title">Pay Bill using Venmo Account</h3>
<div id="payment_note_input">
<input id="payment_note" type="text" class="form-control" required placeholder="add a note to your payment">
</div>
<div id="payment_target_input" >
<input id="payment_target" type="text" class="form-control" required placeholder="pay an email address">
</div>
<div id="payment_amount_input">
<input id="payment_amount" type="text" class="form-control" required placeholder="enter the payment amount! ">
</div>
</br>
<button class="btn btn-danger" type="button" onClick= <%=make_payment%> > Make payment</button>
</div>
I feel like I'm close to a solution here...

You can use httpparty gem to achieve that, its easy to use in only 1 line:
response = HTTParty.post("https://example.com?param1=value1",
:body => {:text => data}.to_json,
:headers => {'Content-Type' => 'application/json'}
)
You can remove Body and Header if you don't have specific Body or Header,
and if you want to achieve Get request its even easier:
responce = HTTParty.get('http://example.com.json')
json=JSON.parse(responce.body) # in case you expect json responce

You need to use a form in order to generate a POST request from the web page. Rails provides you with Form helpers that would help you achieve this.
<div class="box box-warning">
<div class="box-header">
<%= form_tag make_payment_path do %>
<%= hidden_field_tag "access_token", #access_token %>
<h3 class="box-title">Pay Bill using Venmo Account</h3>
<div id="payment_note_input">
<%= text_field_tag "payment_note", nil, class: "form-control", placeholder: "add a note to your payment" %>
</div>
<div id="payment_target_input" >
<%= text_field_tag "payment_target", nil, class: "form-control", placeholder: "pay an email address" %>
</div>
<div id="payment_amount_input">
<%= text_field_tag "payment_amount",nil, class:"form-control", placeholder: "enter the payment amount! ">
</div>
</br>
<%= sumbit_tag "Make payment", class:"btn btn-danger" %>
<% end %>
</div>
And then you can access the form variables in your controller by...
def make_payment
access_token = params[:access_token]
note = params[:payment_note]
target = params[:payment_target]
...
end

Related

how to use form to set the values of params (for Scope) in Ruby on Rails?

I want to build a filter with the help of scope in ruby on rails.
In my controller, I have the lines:
def index
#carpools = Carpool.paginate(page: params[:page], per_page: 5)
#carpools = #carpools.filter_by_locationFrom(params[:carpool_from]) if params[:carpool_from].present?
end
And in my model, I have the lines:
scope :filter_by_locationFrom, -> (locationFrom) { where locationFrom: locationFrom }
And in my view (index.html.erb), I want to have a form to type the value of locationFrom, so that the controller will know the params: locationFrom exists and only select the specified data (with the locationFrom value)from the database.
I have tried several form format but they all got some issues. How can I make such form?
Here is the form I tried:
<%= form_with(model: #carpool, method: "POST") do |f| %>
<div class="form-group row">
<%= f.label :locationFrom, class: "col-2 col-form-label text-light" %>
<div class="col-10">
<%= f.text_field :carpool_from, class: "form-control shadow rounded", placeholder: "From" %>
</div>
</div>
<div class="form-group row justify-content-center">
<%= f.submit("filter", class: "btn btn-outline-light btn-lg") %>
</div>
<% end %>
This gives 400 bad request, saying that:
ActionController::ParameterMissing (param is missing or the value is empty: carpool):
app/controllers/carpools_controller.rb:20:in `create'
But my form is inside 'index' page, I don't know why it refers to 'create'
Thanks in advance!

Wrong controller action invoked?

Rails 3.2
This is my second attempt at solving this problem.
I inherited an application for processing customer tickets. The main ticket view, is large and complicated, so it's split up into multiple sections.
I am trying to add a new section to enter customers information.
I have a scaffolding for CustomerInfo, with a controller and a model, in the normal locations:
controllers/customer_infos_controller.rb and models/customer_info.rb.
I put the views under views/tickets/sections
In my views/tickets/show.html.slim, I have:
- #customer_info = customer_info #ticket
h4.form-header Customer Information
.form-section.attachments
- if #customer_info.nil?
= render partial: 'tickets/sections/customer_info', locals: {ticket: #ticket }
In my , views/tickets/sections/_customer_info.html.slim, I have:
= form_for(CustomerInfo.new, url: customer_info_path) do |f|
- f.hidden_field :ticket_id, :value => ticket.id
.form-horizontal-column.customer-info
.form-group
= f.label :first
= f.text_field :first, maxlength: 50
.form-group
= f.label :last
= f.text_field :last, maxlength: 50
.actions = f.submit 'Save'
.clear
In my routes.rb, I have:
post '/customer_infos' => 'customer_infos#create', as: 'customer_info'
When I run the application, the form displays properly. But, when I enter the first name, and last name, the ticket gets updated.
Looking at the log file, I see that when the Save button in the Customer Information section, I see:
Processing by TicketsController#update as HTML
In the log, I also saw the params:
{
"ticket":
{
.......................
},
"customer_info":
{
"first":"John",
"last":"Doe"
},
"commit":"Save"
}
rake routes gives me:
customer_info POST /customer_infos(.:format) customer_infos#create
This is the HTML:
<div class="form-horizontal-column customer-info">
<div class="form-group">
<label for="customer_info_first">First *</label>
<input id="customer_info_first" type="text" size="50" name="customer_info[first]" maxlength="50">
</div>
<div class="form-group">
<label for="customer_info_last">Post tax total *</label>
<input id="customer_info_last" type="text" size="50" name="customer_info[last]" maxlength="50">
</div>
<div class="actions">
<input type="submit" value="Save" name="commit">
</div>
</div>
This is the portion:
<form accept-charset="UTF-8" action="http://xxx.xxxx.xxxx.com/admin/tickets/159384" class="form form-horizontal tickets-form context-form" data-admin="true" enctype="multipart/form-data" id="edit_ticket_159384" method="post">
So, there is no customer_info portion, with the proper action and method.
Why is the tickets controller update method is invoked, instead of the CustomerInfo create method? I also don't see the ticket_id param in the params.

Integrating Stripe in Rails app

I am trying to create a custom form with stripe, and while it all appears to be submitting, when I check my dashboard in Stripe, although I do see a record of the transaction - I do not see the amount or any reference to the cc coming through. With that said, I am not quite sure what I SHOULD be seeing in the dashboard. But I am pretty sure I am doing something wrong. Here is the code to my form:
<div class="container">
<div class="row Row one">
<div class="col-sm-12 col-md-10">
<%= form_for #project, url: project_charges_path, :html => {:id => "payment-form"}, method: 'post' do |f| %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.hidden_field :#project_id, :value => #project.id %>
<div class= "field">
<%= label_tag :card_number, "Credit Card Number" %><br>
<%= text_field_tag :card_number, nil, name: nil %><br>
</div>
<div class= "field">
<%= label_tag :card_code, "Security Code (cvc)" %><br>
<%= text_field_tag :card_code, nil, name: nil %><br>
</div>
<div class= "field">
<%= label_tag :card_month, "Expiration" %>
<%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month"} %>
<%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year+15}, {name: nil, id: "card_year"}%>
</div>
<div class= "actions">
<%= f.submit("Submit") %>
</div>
<div id="stipe-error">
<%= flash[:error] %>
</div>
<% end %>
</div>
</div>
<!-- <div class="row"></div> -->
and here is my charges controller:
class ChargesController < ApplicationController
def new
#project = Project.find(params[:project_id])
end
def create
#project = Project.find(params[:project_id])
binding.pry
# Amount in cents, this is being read and recorded in stripe dashboard
#amount = 500
customer = Stripe::Customer.create(
:email => 'helloWorld#stripe.com',
:card => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => 'Rails Stripe customer',
:currency => 'usd'
)
#payment = Payment.create({
user_id: current_user.id,
project_id: #project,
amount: #amount
})
#payment.save
rescue Stripe::CardError => e
flash[:error] = e.message
end
# private
# def charges_params
# params.require(:payment).permit(:comments, :user_id, :project_id)
# end
end
Per a tutorial I have also included some javascript in my application.js:
$('#payment-form').submit(function(event) {
var $form = $(this);
alert('you clicked submit');
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
function stripeResponseHandler(status, response) {
var $form = $('#payment-form');
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('button').prop('disabled', false);
} else {
// response contains id and card, which contains additional card details
var token = response.id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// and submit
$form.get(0).submit();
}
}
Inside the striped dashboard I see:
the email comes through, but nothing concerning the amount or card. I don't expect to see the card number persay, but some reference to it, maybe just the type, or last four digits? Also in the front page of the dashboard (the area what gives a graph, I think I should be seeing the sum of the payments, even test payments, and the sum is still $0 despite having made over a dozen test payments of $5 each.
What am I missing here?
Also most of the tutorials I have come across are either really old, or PHP, which I am not familiar with. If anybody can recommend a great resource, that would really be helpful as well. I plan to use stripe for multiple projects, and would really like to UNDERSTAND it...
I might be very late in replying and you must have already done this but just in case this might help some else. I have just integrated stripe in my app. I am not sure what you are asking but i think a working example might help. This is very similar to what you have done and i can't find what's going wrong.
What i'm doing is saving customer_id returned by stripe in my user table. When the user saves the credit card, a certain amount according to the subscription plan is deducted. You will see the customer_id in your plan details under the subscribers in the dashboard. Also, in the customers, When you refer that customer_id, you'll see what plan he's subscribed to.
View: (creditcard.html.erb)
<div class="row">
<% if flash[:error].present? %>
<div class="col-lg-12 alert alert-danger">
<%= flash[:error] %>
</div>
<% else %>
<div class="col-lg-12" id = "payment-errors">
<span class="payment-errors"></span>
</div>
<% end %>
</div>
<div>
<%= form_tag plans_billings_chargecreditcard_path, id: "payment-form" do%>
<div class="row">
<div class="col-lg-3">
<div class="form-group">
<label>Card Number</label>
<%= text_field_tag nil, nil, size: 20, "data-stripe": "number", class: "form-control" %>
</div>
</div>
<div class="col-lg-2">
<div class="form-group">
<label>CVC</label>
<%= text_field_tag nil, nil, size: 4, "data-stripe": "cvc", class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label>Expiration Date(MM/YY)</label>
<select class="selectpicker set-width" data-live-search="true" data-stripe = "exp_month">
<option>- Month -</option>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
<option>6</option>
<option>7</option>
<option>8</option>
<option>9</option>
<option>10</option>
<option>11</option>
<option>12</option>
</select>
<select class="selectpicker set-width" data-live-search="true" data-stripe = "exp_year"> <!-- form-control input-lg -->
<option>- Year -</option>
<option>16</option>
<option>17</option>
<option>18</option>
<option>19</option>
<option>20</option>
<option>21</option>
<option>22</option>
<option>23</option>
<option>24</option>
<option>25</option>
<option>26</option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<%= submit_tag "Save Card", class: "btn btn-primary" %>
</div>
</div>
</div>
<% end %>
</div>
CofeeScript: (plan_billings.coffee)
stripeResponseHandler = (status, response) ->
# Grab the form:
$form = $('#payment-form')
if response.error
# Problem!
# Show the errors on the form:
$('#payment-errors').addClass 'alert'
$('#payment-errors').addClass 'alert-danger'
$('.payment-errors').text response.error.message
$('.submit').prop 'disabled', false
# Re-enable submission
else
# Token was created!
# Get the token ID:
token = response.id
# Insert the token ID into the form so it gets submitted to the server:
$form.append $('<input type="hidden" name="stripeToken">').val(token)
# Submit the form:
$form.get(0).submit()
return
$ ->
$form = $('#payment-form')
$form.submit (event) ->
# Disable the submit button to prevent repeated clicks:
$form.find('.submit').prop 'disabled', true
# Request a token from Stripe:
Stripe.card.createToken $form, stripeResponseHandler
# Prevent the form from being submitted:
false
return
Controller: (in PlanBilling controller, chargecreditcard action)
#plan_and_billing = current_user.plan_billing
#current_plan = DataPlan.find_by(id: #plan_and_billing.data_plan_id)
token = params[:stripeToken]
if current_user.customer_id.present?
customer = Stripe::Customer.retrieve(current_user.customer_id)
customer.sources.create(source: token)
redirect_to plans_billings_planbilling_path
else
customer = Stripe::Customer.create( :source => token, plan: YOUR_PLAN_ID_YOU_HAVE_INYOUR__DASHBOARD )
#credit_card = current_user.update(customer_id: customer.id)
redirect_to plans_billings_planbilling_path
end
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to plans_billings_creditcard_path
What's happening in controller is that when a user has no card and he saves the card details, the card is saved and the Price of the plan you have mentioned is deducted. And if he already has a credit card saved, and saving another one, the card will only be saved as you'll see in his details in the dashboard. The new card will not be charged. Its just for saving new credit card to that customer.
I still have a long way to go in this, and of course this might not be a very good code, but this is just very basic thing you might find helpful. In case someone tries it out and faces some prob, i'll be glad to help. Also, I'll be grateful if someone can guide me to make this code better. Cheers :)

Rails search URI with unwanted parameters?

Background
I am creating a search field in my header. This code in my view:
<% if signed_in? %>
<%=f orm_tag( "/search", method: "get", :class=>"navbar-form navbar-left", :role => "search") do %>
<div class="form-group">
<%=t ext_field_tag :q, nil, :class=>"form-control", :placeholder => 'Domain/IP Search' %>
</div>
<%=b utton_tag "Search", :type=>'submit', :class=> "btn btn-primary" do %>
<span class="glyphicon glyphicon-search"></span>
<% end %>
<% end %>
creates this output:
<form accept-charset="UTF-8" action="/search" class="navbar-form navbar-left" method="get" role="search">
<div style="display:none">
<input name="utf8" type="hidden" value="✓">
</div>
<div class="form-group">
<input class="form-control" id="q" name="q" placeholder="Domain/IP Search" type="text">
</div>
<button class="btn btn-primary" name="button" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</form>
Here is a picture:
The issue
The problem is when I search, I get this in my url:
/search?utf8=✓&q=test&button=
Ideally, I'd like it to be more like:
/search?q=test
tl;dr:
How do I get rid of the button parameter (and hopefully the utf one as well).
Extra info:
routes.rb
resources :search
search_controller.rb
class SearchController < ApplicationController
def index
#results = params[:q]
puts #results.to_s
end
end
search\index.html.erb
<%=#results.to_s %>
EDIT, answer
Adding this because while the accepted answer helped me get to the solution; it didn't have the exact code for my circumstance. I made these changes:
1) routes:
match '/search', to: 'search#index', via: 'post'
2) form in my header:
<%= form_tag search_path, method: "post", :class => "navbar-form navbar-left", :id=> "SearchForm", :role => "search" do %>
<div class="form-group">
<%= text_field_tag :q, nil, :class => "form-control", :placeholder => 'Domain/IP Search' %>
</div>
<%= button_tag "Search", :type=> 'submit', :class=> "btn btn-primary" do %>
<span class="glyphicon glyphicon-search"></span>
<% end %>
<% end %>
GET
The bottom line, as I wrote in another answer, is that you're using GET:
Essentially, when you submit a GET form, it appends the parameters to your URL, whilst a POST form will append the data to the request body (or somewhere hidden).
The difference is just that the GET request expects a response to be returned immediately, and so you have to pass the parameters in the URL to ensure the server knows how to construct it. The best example being if you use a GET request to load a page.
The POST method is used primarily used for forms, where a response is not expected immediately; thus allowing you to keep the params hidden in the request.
Fix
We've actually created a basic search feature here (the actual search doesn't work for some reason, but the live search does)
The way we did it was as follows:
match 'search(/:search)', :to => 'products#search', :as => :search, via: [:get, :post]
This will firstly allow you to access the search action by typing domain.com/search/your-query-here
In terms of submitting via a form, you'll be able to use JQuery to amend the URL with the input from the text field:
#app/views/elements/_nav.html.erb
<%= form_tag search_path, :method => :post, :id => "SearchForm" do %>
<%= text_field_tag :search, params[:search], placeholder: 'Search your favourite products or brands', :autocomplete => :off, :id => 'SearchSearch' %>
<%= image_submit_tag('nav_bar/search.png', title: 'Search', class: 'search_submit', data: { "placement" => "bottom" }) %>
<% end %>
#app/assets/javascripts/application.js
//Search Submit
$(document).ready(function() {
$('#SearchForm').submit(function(e) {
e.preventDefault();
if( $('#SearchSearch').val().length > 0 ) {
var search_params = '/' + $('#SearchSearch').val().toLowerCase();
}else{
var search_params = ''
}
window.location.href = $(this).attr('action') + search_params
});
});
If you are not doing with the Utf8 parameter but, Rails is & but its needed. It's to correct some issues in IE's parameter encoding, This parameter was added to forms in order to force Internet Explorer 5, 6, 7 and 8 to encode its parameters as unicode.Its fixes encodeing issue of IE.
Please refer following link:
What is the _snowman param in Ruby on Rails 3 forms for?
This parameter is a feature of rails.
It was previously the snowman.
It helps IE to really use utf-8.
Avoid using form_tag and it works:
<form action="<%= search_path %>" method="get" >
<%= text_field_tag 'query' %>
<%= submit_tag "Search", :name => nil%>
</form>
Now style your form as you want

Defining field label in a block - on error, field_with_errors div tag not in right place

I am using validates_acceptance_of :terms, :message => "must be accepted" in my user.rb model, and am using bootstrap-sass.
My check box code looks like this in the view:
<div class="control-group">
<%= f.label :terms, :class => "control-label" do %>
Accept <%= link_to('Terms of Use *', "#myTOUModal", :"data-toggle" => "modal") %>
<% end %>
<div class="controls">
<%= f.check_box :terms %>
</div>
</div>
For some reason, when the terms check box isn't selected on form submission, the appropriate error message shows up at the top of the form, but there is a problem with the field_with_errors div class wrapping around the check box label.
The HTML for the rendered page looks like this:
<div class="control-group">
<label class="control-label" for="user_terms">
Accept Terms of Use *
</label>
<div class="controls">
<input name="user[terms]" type="hidden" value="0" />
<div class="field_with_errors">
<input id="user_terms" name="user[terms]" type="checkbox" value="1" />
</div>
</div>
</div>
The result is that the check box field label isn't highlighted on error. Is there a way to force the div tag placement for the field_with_errors class to show up just after the <div class="control-group"> tag? Why does using a block to define a field label throw off the field_with_errors tag placement? Does anyone have experience with this?
Thank you
This is a bug i think. The problem is in block. Define your label without block and everything works.
Try something like:
<% modal_html = capture do >
Accept <%= link_to('Terms of Use *', "#myTOUModal", :"data-toggle" => "modal") %>
<% end %>
<%= f.label :terms, modal_html, :class => "control-label" %>
Or helper:
def modal_html
#Q{Accept #{link_to('Terms of Use *', "#myTOUModal", :"data-toggle" => "modal")} }.html_safe
end

Resources