I am trying to integrate stripe into my rails app. Everything works well until I submit the form in which it looks like this when I do so:
Once I submit the form I am getting the following error:
I cannot figure out why it is doing this. When I check my stripe test dashboard nothing is there.
Here are some of the files:
donation.html.erb
<%= form_tag charges_path do %>
<div id="error_explanation">
<% if flash[:error].present? %>
<p><%= flash[:error] %></p>
<% end %>
</div>
<article>
<%= label_tag(:amount, 'Donation Amount:',class: 'donationHead') %>
<%= text_field_tag(:amount,"", class: 'form-control') %>
</article>
<article>
<%= hidden_field_tag(:stripeToken) %>
</article>
<button id='donateButton' class="btn btn-primary">Donate</button>
<% end %>
<script src="https://checkout.stripe.com/checkout.js"></script>
<script>
var handler = StripeCheckout.configure({
key: '<%= Rails.configuration.stripe[:publishable_key] %>',
locale: 'auto',
name: 'Place4Grace',
image: '<%= asset_url "creative/small_logo.jpg" %>',
description: 'Thank you for your Donation!',
token: function(token) {
$('input#stripeToken').val(token.id);
$('form').submit();
}
});
$('#donateButton').on('click', function(e) {
e.preventDefault();
$('#error_explanation').html('');
var amount = $('input#amount').val();
amount = amount.replace(/\$/g, '').replace(/\,/g, '')
amount = parseFloat(amount);
if (isNaN(amount)) {
$('#error_explanation').html('<p>Please enter a valid amount in USD ($).</p>');
}
else if (amount < 5.00) {
$('#error_explanation').html('<p>Donation amount must be at least $5.</p>');
}
else {
amount = amount * 100; // Needs to be an integer!
handler.open({
amount: Math.round(amount)
})
}
});
$(window).on('popstate', function() {
handler.close();
});
</script>
Here is my stripe.rb
Rails.configuration.stripe = {
:publishable_key => 'pk_test...',
:secret_key => 'sk_test...'
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]
routes.rb
resources :charges, only: [:new, :create]
And lastly here is my controller:
class ChargesController < ApplicationController
def new
end
def create
#amount = params[:amount]
#amount = #amount.gsub('$', '').gsub(',', '')
begin
#amount = Float(#amount).round(2)
rescue
flash[:error] = 'Charge not completed. Please enter a valid amount in USD ($).'
redirect_to root_path
return
end
#amount = (#amount * 100).to_i # Must be an integer!
if #amount < 500
flash[:error] = 'Charge not completed. Donation amount must be at least $5.'
redirect_to root_path
return
end
Stripe::Charge.create(
:amount => #amount,
:currency => 'usd',
:source => params[:stripeToken],
:description => 'Custom donation'
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to root_path
end
end
UPDATE
Here is my route.rb:
Rails.application.routes.draw do
get 'dashboard/index'
get 'dashboard/new'
get 'dashboard/create'
get 'dashboard/show'
get 'dashboard/destroy'
get 'contacts/index'
get 'document/download'
get 'confirmation/confirmation'
get 'document/download'
root 'creatives#index'
get 'access/menu'
get 'access/login'
post 'access/attempt_login'
get 'access/logout'
get 'sessions/index'
get 'sessions/logout'
get 'sessions/profile'
get 'sessions/login'
get 'administrators/index'
get 'administrators/new'
resources :users do
member do
get :delete
end
end
resources :contacts do
member do
get :delete
end
end
resources :charges, only: [:new, :create]
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
Update 2
Update 3
I don't know how to fix this or if this even matters but when you create a controller using rails in the terminal it creates a view automatically. I created a charges controller but the charges form is located in the creatives view not the charges view because it is a partial see image the page is donation.html.erb.
Related
I'm new to Stripe connect, building a marketplace app using stripe connect standalone, and require the user to enter a custom amount to pay the other user. The old form I was using worked fine, but once I changed to the new form, my :source => params[:stripeToken] no longer generates, as well as :stripeEmail. What is causing this?
Invalid source object: must be a dictionary or a non-empty string
my original charges_controller.rb
class ChargesController < ApplicationController
def new
end
def create
# Amount in cents
#amount = 500
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => 'Wage Payment',
:currency => 'cad'
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
then I added the methods from the stripe recipe for custom amounts:
def create
#amount = params[:amount]
#amount = #amount.gsub('$', '').gsub(',', '')
begin
#amount = Float(#amount).round(2)
rescue
flash[:error] = 'Charge not completed. Please enter a valid amount in CAD ($).'
redirect_to new_charge_path
return
end
#amount = (#amount * 100).to_i # Must be an integer!
if #amount < 500
flash[:error] = 'Charge not completed. Payment amount must be at least $5.'
redirect_to new_charge_path
return
end
charge = Stripe::Charge.create(
:amount => #amount,
:customer => customer.id,
:currency => 'cad',
:source => params[:stripeToken],
:description => ‘Payment'
)
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken]
)
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
I also modified the form, and added the javascript in charges/new.html.erb:
old form:
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
Stripe.setPublishableKey('pk_test_my_key');
</script>
<%= form_tag charges_path do %>
<article>
<% if flash[:error].present? %>
<div id="error_explanation">
<p><%= flash[:error] %></p>
</div>
<% end %>
<label class="amount">
<span>Amount: $5.00</span>
</label>
</article>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
data-description="A month's subscription"
data-amount="500"
data-locale="auto"></script>
<% end %>
new form:
<%= form_tag charges_path, id: 'form' do %>
<div id="error_explanation">
<% if flash[:error].present? %>
<p><%= flash[:error] %></p>
<% end %>
</div>
<article>
<%= label_tag(:amount, 'Payment Amount:') %>
<%= text_field_tag(:amount) %>
</article>
<article>
<%= hidden_field_tag(:stripeToken) %>
<%= hidden_field_tag(:stripeEmail) %>
</article>
<button id='donateButton'>Pay Now</button>
<% end %>
<script src="https://checkout.stripe.com/checkout.js"></script>
<script type="text/javascript">
Stripe.setPublishableKey('pk_test_CcUZ1IJxEqLR5RvVE3p5tx3U');
</script>
<script>
var handler = StripeCheckout.configure({
key: '<%= Rails.configuration.stripe[:publishable_key] %>',
locale: 'auto',
name: 'Payments',
description: 'Wage',
token: function(token) {
$('input#stripeToken').val(token.id);
$('input#stripeEmail').val(token.id);
$('form').submit();
}
});
$('#donateButton').on('click', function(e) {
e.preventDefault();
$('#error_explanation').html('');
var amount = $('input#amount').val();
amount = amount.replace(/\$/g, '').replace(/\,/g, '')
amount = parseFloat(amount);
if (isNaN(amount)) {
$('#error_explanation').html('<p>Please enter a valid amount in CAD ($).</p>');
}
else if (amount < 5.00) {
$('#error_explanation').html('<p>Wage amount must be at least $5.</p>');
}
else {
amount = amount * 100; // Needs to be an integer!
handler.open({
amount: Math.round(amount)
})
}
});
// Close Checkout on page navigation
$(window).on('popstate', function() {
handler.close();
});
</script>
Now when I submit the custom amount, I am given the following error:
You have passed a blank string for 'source'. You should remove the
'source' parameter from your request or supply a non-blank value
Extracted source (around line #27): Stripe::Charge.create(
Not sure how to proceed. This error seems to be associated to creating charges, as the error is in the charges controller. Or it is in the javascript of the new custom form.
What am I missing?
I had exactly the similar problem. But after few hours of struggle I figured it out. The reason is following. If you are using Rails 4.+ and using Turbolinks along with it, then it loads entire javascript for that page and when you are loading modal the javascript on that modal page wont work. You have to switch off the turbolink.
For me I switched off at the link level which is the link responsible for loading the charge/new page. Example:
<%= link_to "Buy", new_charge_path(product_id: #product.id),'data-no-turbolink' => true %>
UPDATE: The answer bellow is correct. Just wanted to update what I did to solve the problem.
First I had to delete all my previous lines in the rails console.
Then I used the bye bug gem in my lines controller at the bottom of the create method to discover where the next bug occurred. I created a test line that I needed to delete again. so I ran
Line.last.delete in console.
This is the way my lines controller create method looks now (working no bugs)
def create
if user_signed_in?
#line = Line.create(line_params)
if #line
if params[:line][:previous_line_id].empty?
#line.story = Story.create
#line.save
else
#line.story = #line.previous_line.story
#line.save
end
redirect_to line_path(#line)
else
flash[:error] = #line.errors
redirect_to line_path(Line.find(params[:line][:previous_line_id]))
end
else
Finally I ran #Lines.each { |line| line.update.attribute(:story_id: 3)}
This gave the necessary association between lines and story.
ORIGINAL POST BELLOW.
I'm getting this error in my rails app. I think that when I create a new line or start a story, it doesn't automatically add it to a story object. I've listed my show.html.erb file as well as my lines controller.rb file.
What am I missing? How do I get the controller to add data to the story object correctly?
Thanks!
I added a few lines of code to my lines controller:
class LinesController < ApplicationController
def new
params[:previous_line_id].nil? ? #line = Line.new : #line = Line.find(params[:previous_line_id]).next_lines.create
#lines = #line.collect_lines
#ajax = true if params[:ajax]
render :layout => false if params[:ajax]
if #line.previous_line
#line.update_attribute(:story_id, #line.previous_line.story.id)
else
story = Story.create
#line.story = story
#line.save
end
end
def create
if user_signed_in?
#line = Line.create(line_params)
if #line
redirect_to line_path(#line)
else
flash[:error] = #line.errors
redirect_to line_path(Line.find(params[:line][:previous_line_id]))
end
else
flash[:error] = "Please sign in or register before creating a line!"
unless params[:line][:previous_line_id].empty?
redirect_to line_path(Line.find(params[:line][:previous_line_id]))
else
redirect_to root_path
end
end
end
# params[:id] should correspond to the first line of the story.
# if params[:deeper_line_id] is not nil, that means that they want to render up to the nested line id
def show
#lines = Line.find(params[:id]).collect_lines
#next_lines = #lines.last.next_lines.ranked
#lines.last.update_attribute(:score, #lines.last.score + 1)
end
def select_next
#line = Line.find(params[:id])
#line.update_attribute(:score, #line.score + 1)
#lines = [#line]
#next_lines = #line.next_lines.ranked
render :layout => false
end
def send_invite
if user_signed_in?
UserInvite.send_invite_email(current_user,Line.find(params[:id]), params[:email]).deliver
flash[:notice] = "Your invite was sent!"
else
flash[:error] = "Please sign in"
end
redirect_to Line.find(params[:id])
end
private
def line_params
params.require(:line).permit(:text, :previous_line_id, :user_id)
end
end
I added these lines to the controller pictured above
if #line.previous_line
#line.update_attribute(:story_id, #line.previous_line.story.id)
else
story = Story.create
#line.story = story
#line.save
end
Here is my show.html.erb file
<div class="row">
<div class="col-lg-2">
</div>
<div class="box-container col-lg-7 ">
<div id="story" class="box">
<% #lines.each do |line| %>
<span class="story-line" data-id="<%=line.id%>"><%= link_to line.text, '#', :class=>"story-line" %></span>
<% end %>
</div>
<div id="next-steps">
<%= render 'next_steps' %>
</div>
<span style="font-size:.9em; margin-bottom:15px; display:block;">*If the links don't work, try refreshing.</span>
</div>
<div class="col-lg-2" style="padding-right:25px;">
<%= render 'invite' %>
Your Fellow Collaborators: <br />
<div class="collaborators">
<% #lines.last.story.collaborators.uniq.each do |collaborator| %>
<%= link_to profile_path(:id => collaborator.id) do %>
<%= image_tag collaborator.profile_image_uri, :class => "prof-icon" %>
<% end %>
<% end %>
</div>
Story model
class Story < ActiveRecord::Base
has_many :lines
has_and_belongs_to_many :collaborators, :class_name => "User", :join_table => "collaborators_stories", :association_foreign_key => :collaborator_id
def first_line
self.lines.first_lines.first_lines.first
end
end
Here is my lines.rb file
class Line < ActiveRecord::Base
scope :first_lines, -> { where previous_line_id: nil}
scope :ranked, -> { order("score + depth DESC")}
belongs_to :user
belongs_to :story
belongs_to :previous_line, :class_name => "Line", :foreign_key => "previous_line_id"
has_many :next_lines, :class_name => "Line", :foreign_key => "previous_line_id"
validates_presence_of :text
after_create :update_depths
def update_depths
line = self.previous_line
while !line.nil?
line.update_attribute(:depth, line.depth + 1)
line = line.previous_line
end
end
def first_line
line = self
while !line.previous_line.nil?
line = line.previous_line
end
line
end
def collect_lines
line = self
lines = [self]
while !line.previous_line.nil?
lines.unshift(line.previous_line)
line = line.previous_line
end
lines
end
end
Problem is orphaned lines in your database. Look for them and associate it to a story, or delete it:
How to find orphaned records:
http://antonzolotov.com/2013/01/26/how-to-find-and-delete-orphaned-records-with-ruby-on-rails.html
Then review the create method to ensure a line should be part of a story:
#short example review activerecord relations
#story = Story.find(params[:story_id])
story.lines.create(line_params)
That should work.
EDIT:
def self.find_orphan_ids
Lines.where([ "user_id NOT IN (?) OR story_id NOT IN (?)", User.pluck("id"), Story.pluck("id") ]).destroy_all
end
In my application I have model "Regulation", form for creating regulations looks like this:
- if %W(edit update).include? action_name
= content_for :heading, t('partners.regulations.edit')
- else
= content_for :heading, t('partners.regulations.new')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation] do |f|
= f.error_notification
%ul.nav.nav-pills
%li
= link_to image_tag("flag_pl.png"), '#PL', class: 'regulation_pl'
%li
= link_to image_tag("flag_en.png"), '#EN', class: 'regulation_en'
.polish_regulation
%h1.page-header
= t('partners.regulations.polish')
= f.input :content_pl, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Pure', width: 750} }, error: false
.english_regulation
%h1.page-header
= t('partners.regulations.english')
= f.input :content_en, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Basic', width: 750} }, error: false
- if %W(edit update).include? action_name
= f.submit t('actions.save_changes'), class: "btn btn-lg btn-default"
- else
= f.submit t('partners.regulations.save'), class: "btn btn-lg btn-default"
In my routes I have:
namespace :partners do
resources :regulations, as: :rental_company_regulation, except: :show
end
My controller looks like this:
module Partners
class RegulationsController < ApplicationController
include Partners::BaseController
load_and_authorize_resource through: :rental_company, singleton: true
before_action :set_breadcrumbs
before_action :set_regulation, only: :new
def new
if #rental_company_regulation
redirect_to edit_partners_rental_company_regulation_path(#rental_company_regulation)
end
add_breadcrumb t('partners.regulations.new')
end
def create
if #regulation.save
flash[:notice] = t('partners.regulations.created')
redirect_to partners_root_path
else
add_breadcrumb t('partners.regulations.new')
render :new
end
end
def edit
add_breadcrumb t('partners.regulations.edit')
end
def update
if #regulation.update(regulation_params)
flash[:notice] = t('partners.regulations.updated')
redirect_to partners_root_path
else
add_breadcrumb t('partners.regulations.edit')
render :edit
end
end
protected
def set_regulation
#rental_company_regulation = Regulation.where(rental_company_id: rental_company).first
end
def set_breadcrumbs
add_breadcrumb current_partner.rental_company.name, :partners_root_path
end
private
def regulation_params
params.require(:regulation).permit(:content_pl, :content_en, :rental_company_id)
end
end
end
Creating resource from scratch works properly. But I went to:
"http://localhost:3000/partners/regulations/4/edit" to edit regulation I have the following error:
undefined method `partners_regulation_path' for #<#<Class:0x0000000242fae8>:0x00000007d9afb0>
I can't solve this problem. What's wrong?
Edit:
Rake routes:
partners_rental_company_regulation_index GET /partners/regulations(.:format) partners/regulations#index
POST /partners/regulations(.:format) partners/regulations#create
new_partners_rental_company_regulation GET /partners/regulations/new(.:format) partners/regulations#new
edit_partners_rental_company_regulation GET /partners/regulations/:id/edit(.:format) partners/regulations#edit
partners_rental_company_regulation PATCH /partners/regulations/:id(.:format) partners/regulations#update
Edit2:
I've changed my form too looks like this:
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_path
Now I can edit exisiting resource but can't create a new one. When I trying to create the new one I have the following error:
No route matches {:action=>"update", :controller=>"partners/regulations"} missing required keys: [:id]
What's wrong?
as
To simplify user2675613's answer, your error is basically caused by using the as argument in your routes
as: basically allows you to "name" the route:
#config/routes.rb
resources :users # -> users_path
resources :users, as: :members # -> members_path
Error
Your error is as follows:
undefined method `partners_regulation_path'
This basically means you're using a path which doesn't exist. This is because you've used the as: option in your routes:
#config/routes.rb
resources :partners do
resources :regulations #-> partners_regulation_path
end
resources :partners do
resources :regulations, as: "test" # -> partners_test_path
end
This is confirmed with your routes:
partners_rental_company_regulation_index
new_partners_rental_company_regulation
edit_partners_rental_company_regulation
partners_rental_company_regulation
Fix
The way to fix this is to remove the as: option from your routes:
#config/routes.rb
resources :partners do
resources :regulations #-> partner_regulations_path
end
Alternatively, if you wanted to keep the custom name for your paths, you'll have to change your path references to parental_company_regulation_path
As you can see you in your rake routes your url to edit a regulation is edit_partners_rental_company_regulation GET /partners/regulations/:id/edit(.:format) and to create a new one the url is new_partners_rental_company_regulation GET /partners/regulations/new(.:format).
You need to change the way you are using your form here. You can create a partial for all the common fields of form but you need to separate the url part in your form to make a create and update requests.
You can make a partial _form.html.haml with contents:
= f.error_notification
%ul.nav.nav-pills
%li
= link_to image_tag("flag_pl.png"), '#PL', class: 'regulation_pl'
%li
= link_to image_tag("flag_en.png"), '#EN', class: 'regulation_en'
.polish_regulation
%h1.page-header
= t('partners.regulations.polish')
= f.input :content_pl, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Pure', width: 750} }, error: false
.english_regulation
%h1.page-header
= t('partners.regulations.english')
= f.input :content_en, :as => :ckeditor, :input_html => { :ckeditor => {:toolbar => 'Basic', width: 750} }, error: false
Then inside your edit.html.haml you can have:
= content_for :heading, t('partners.regulations.edit')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_path do |f|
= render :partial => "form", :locals => { :f => f } #you need to pass other required locals too else it'll give error
= f.submit t('actions.save_changes'), class: "btn btn-lg btn-default"
Similarly inside your new.html.haml you can have:
= content_for :heading, t('partners.regulations.new')
.row
.col-md-6
= horizontal_simple_form_for [:partners, #regulation], url: partners_rental_company_regulation_index_path do |f|
= render :partial => "form", :locals => { :f => f } #you need to pass other required locals too else it'll give error
= f.submit t('partners.regulations.save'), class: "btn btn-lg btn-default"
I have a model which is linking to the show method:
<%= link_to "View Others", :controller => "browse",
:action => "show", :id => #id, :d => "25" %>
Clicking the link gives:
http://localhost:3000/browse/santa-cruz?d=25
Rails gives the error though:
No route matches {:controller=>"browse", :action=>"show", :id=>nil, :d=>"25"}
If I take the extra parameter off everything works.
<%= link_to "View Others", :controller => "browse",
:action => "show", :id => #id %>
Goes to http://localhost:3000/browse/santa-cruz
This page loads and I am getting the correct params[:id]
Any ideas?
Pasted bellow is the show for my controller
def show
if params[:d].nil? then
# Show list of addresses in city.
addresses = Address.where(:slug => params[:id])
profile = []
addresses.each do |ad|
profile << ad.profile
end
unless profile.blank?
#profile = Kaminari.paginate_array(profile).page(params[:page]).per(5)
#title = "Profiles Near " + addresses.first.city
#id = params[:id]
else
redirect_to :controller => 'pages', :action => 'notlaunched', :zip => params[:id]
end
else # :d exists
# show all within :d miles.
addresses = Address.where(:slug => params[:id])
nearby = Address.near("#{addresses.first.fulladdress}", params[:d], :order => :distance)
profiles = nearby.map{ |ad| ad.profile }.uniq
end
end
Here's the Index:
def index
cities = []
states = []
Address.find_each do |ad|
cities << { :city => ad.city, :slug => ad.slug } # slug becomes the :id of show
states << ad.state
end
#cities = cities.uniq
#states = states.uniq
#title = "Browse Cities"
end
I have a view which contain multiple links:
<% a.each do |q| %>
<%= link_to "stock it",
{ :action => "stock",
:qid => q.question_id,
:qur => q.question_answers_url,
:qti => q.title } ,
:remote => true %>
<div id="<%= "stock" + q.question_id.to_s %>"></div>
<% end %>
Each link generate AJAX-request. Here is a controller:
def stock
if(!Later.where(:question_id => params[:qid]).exists?)
later = Later.new(:question_id => params[:qid], :name => params[:qti], :url => params[:qur])
later.save
end
respond_to do |format|
format.js { render :layout=>false }
end
end
Now return to the view. Each link has a 'div' with unique id='stock'. When user press the link I need to add text to specific div with corresponding id.
I have a stock.js.erb file:
$("#stock<number>").html("some text");
How can I pass div-id to stock.js.erb and how can I use it ?
Common use is to add object.id to your DOM id. That what you exactly did:
<div id="<%= "stock_#{q.question_id}" %>"></div>
Then in your controller you shoud define your question_id or your exact question:
def stock
if(!Later.where(:question_id => params[:qid]).exists?)
later = Later.new(:question_id => params[:qid], :name => params[:qti], :url => params[:qur])
later.save
end
#question_id = params[:qid]
end
Now it will be shared with your stock.js.erb file:
$("#stock_<%= #question_id %>").html("some text");