I've been working on integrating Stripe into my web application, and it doesn't seem to be working. To help me along, I've been using Ryan Bates's Rails Cast on integrating Stripe. Whenever I try to run the payment form, I get an error saying that "There was a problem with my credit card". I think the problem lies in my coffeescript file, but perhaps I'm wrong. I've included the stripe user token as a part of my user model instead of placing it into its own subscription model. Here is the coffeescript code I have:
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
subscription.setupForm()
user =
setupForm: ->
$('#new_user').submit ->
$('input[type=submit]').attr('disabled', true)
if $('#card_number').length
user.processCard()
false
else
true
processCard: ->
card =
number: $('#card_number').val()
cvc: $('#card_code').val()
expMonth: $('#card_month').val()
expYear: $('#card_year').val()
Stripe.createToken(card, user.handleStripeResponse)
handleStripeResponse: (status, response) ->
if status == 500
$('#user_stripe_card_token').val(response.id)
$('#new_user')[0].submit()
else
$('#stripe_error').text(response.error.message)
$('input[type=submit]').attr('disabled', false)
I'm a beginner when it comes to programming, so any help you can give me would be great.
Here's the error I get in my terminal when I try to sign up:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Xas+iA+a3op7jUi57qTr7XWQSClPscA7fR19rkclkEE=", "user"=>{"stripe_card_token"=>"", "name"=>"Jack", "email"=>"email#example.com", "phone_number"=>"203-xxx-xxxx", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Create my account"}
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('jjets718#yahoo.com') LIMIT 1
Stripe error while creating customer: Invalid token id:
My view for the signup is this:
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.hidden_field :stripe_card_token %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :phone_number, "Your cell phone number" %>
<%= f.text_field :phone_number %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Password confirmation" %>
<%= f.password_field :password_confirmation %>
<%= label_tag :card_number, "Credit Card Number" %>
<%= text_field_tag :card_number, nil, name: nil %>
<%= label_tag :card_code, "Security Code on Card (CVV)" %>
<%= text_field_tag :card_code, nil, name: nil %>
<%= label_tag :card_month, "Card 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"} %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
<div id="stripe_error">
<noscript>JavaScript is not enabled and is required for this form. First enable it in your web browser settings.</noscript>
</div>
My code for my controller is this for the create method:
def create
#user = User.new(params[:user])
if #user.save_with_payment
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to edit_user_path(current_user)
UserMailer.welcome_email(#user).deliver
else
render 'new'
end
end
My code for the database migration for the user token is this:
class AddStripeToUsers < ActiveRecord::Migration
def change
add_column :users, :stripe_customer_token, :string
end
end
And the code for the save_with_payment method in my model is this:
def save_with_payment
if valid?
customer = Stripe::Customer.create(description: email, plan: 1, card: stripe_card_token)
self.stripe_customer_token = customer.id
save!
end
rescue Stripe::InvalidRequestError => e
logger.error "Stripe error while creating customer: #{e.message}"
errors.add :base, "There was a problem with your credit card."
false
end
2 things that come to mind:
You should be doing a status check for 200, not 500
You may need to require the coffeescript file in your application.js
e.g. //= require users
I could be wrong, but at this point:
handleStripeResponse: (status, response) ->
if status == 500
$('#user_stripe_card_token').val(response.id)
In addition to changing if status == 500 to if status == 200, this line $('#user_stripe_card_token').val(response.id) may need to be $('#new_user_stripe_card_token').val(response.id). Make sure to check the input ID.
Related
I know about partial in rails, but it seems that I can only re-use exactly the same form with partial.
What if I have two forms that differ only in one field? For example, in my classroom app, I have one form for a peer-grader and one form for a teacher-grader.
The teacher's form is as follows. The peer-grader form is exactly the same, minus the grade field. How do I DRY this?
<%= form_for #doc,
url: student_homework_document_path(student_id: #doc.submitter_id,
id: #doc.id),
html: { multipart: true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :grade %>
<%= f.number_field :grade %>
<%= f.label :graded_file %>
<%= f.file_field :graded_file %>
<%= f.label :graded_file_source_code %>
<%= f.file_field :graded_file_source_code %>
<%= f.submit "Submit grading", class: "btn btn-large" %>
<% end %>
I would have thought you had one controller called teachers and one called peers or something. You could keep the form the same but add a variable to the peer-grader method such as #peer_grader = true. Then in your form add:
<% if #peer_grader = true %>
<%= f.label :grade %>
<%= f.number_field :grade %>
<% end %>
You would also need to set another variable called #url in both controllers set to the correct path and then update the form to:
<%= form_for #doc, url: #url, html: { multipart: true } do |f| %>
I'm trying to follow along with a tutorial. I am using the same methods as a Blog Post and Blog Comment type tutorial, just trying something a little different. I keep getting an error:
undefined method `to_key' for #(had to remove the first <)Agentinteraction::ActiveRecord_Relation:0x007fa4d43ca138>
With the errors highlighted as: NoMethodError in Agents#show
<% form_for #qrreviews, :url => create_qrreview_agents_path do |f| %>
Routes:
resources :agents do
collection do
post 'create_qrreview', to: 'agents#create_qrreview'
end
end
Agents Show Action:
def show
#qrreviews = Agentinteraction.where("agent_id = ?", #agent.id)
#agentinteraction = Agentinteraction.new
end
show.html.erb
<p id="notice"><%= notice %></p>
<%= #agent.name %>
<%= #agent.email %>
<%= #agent.team %>
<%= link_to 'Edit', edit_agent_path(#agent) %> |
<%= link_to 'Back', agents_path %>
QR Feedback:<br/><br/>
<%#= #comments.blog %>
<% #qrreviews.each do |qrreview| %>
<%= qrreview.agent_id %><br>
<%= qrreview.yes_or_no %><br>
<% end %>
<br/><br/>
<% form_for #qrreviews, :url => create_qrreview_agents_path do |f| %>
Category:
Interaction:
Act One Score:
Act Two Score:
Act Three Score:
Type of Interaction:
Training Needed?
Type of Training Needed?
<%= f.submit %>
<% end %>
undefined method `to_key' for Agentinteraction::ActiveRecord_Relation:0x007fa4d43ca138
The problem is you have define #qrreviews = Agentinteraction.where("agent_id = ?", #agent.id) which returns a AR_Relation.
Try changing
#qrreviews = Agentinteraction.where("agent_id = ?", #agent.id)
to
#qrreviews = Agentinteraction.where("agent_id = ?", #agent.id).first
Also
<% form_for #qrreviews, :url => create_qrreview_agents_path do |f| %>
should be
<%= form_for #qrreviews, :url => create_qrreview_agents_path do |f| %>
My goal is to create a profile page where the (logged in) user can choose to either update their email or their password (in separate forms so not both at the same time) without navigating away from the page.
Updating one's email is as simple as entering their new email and hitting the "Save Changes" submit button.
Updating one's password requires the user to enter their old password, their new password, and a confirmation of their new password then hitting the "Update Password" button. The problem must be in the update_pwd method.
users_controller.rb
# ...
def edit # template: edit.html.erb
#user = User.find(current_user)
end
def update_email
#user = User.find(current_user)
if params[:commit] == 'Save Changes'
if #user.update_attributes(user_params_email)
redirect_to me_url
flash[:notice] = "Your changes have been saved"
else # either invalid or taken
render :edit
end
else
render :edit
end
end
def update_pwd
#user = User.find(current_user)
if params[:commit] == 'Update Password'
if #user.update_attributes(user_params_pwd) && User.find_by(username: current_user.username).try(:authenticate, params[:current_password])
redirect_to me_url
flash[:notice] = "Password updated!"
else
flash.now[:alert] = #user.errors.full_messages[0]
render :edit
end
else
render :edit
end
end
private
#def user_params
#params.require(:user).permit(:id, :username, :email, :password, :password_confirmation)
#end
def user_params_email
params.require(:user).permit(:email)
end
def user_params_pwd
params.require(:user).permit(:password, :password_confirmation, :current_password)
end
edit.html.erb
<%= form_for(current_user, :url => {:controller => 'users', :action => 'update_email'}) do |f| %>
<% if #user.errors.any? %>
<% for message in #user.errors.full_messages %>
<li><%= message %></li>
<% end %>
<% end %>
<p> Current Email: <%= current_user.email %> </p>
<p> New Email: <%= f.text_field :email %> </p>
<%= f.submit "Save Changes" %>
<% end %>
<%= form_for(current_user, :url => {:controller => 'users', :action => 'update_pwd'}) do |g| %>
<p>Old Password<br>
<%= password_field_tag :current_password, params[:password] %></p>
<p>New Password<br>
<%= g.password_field :password %></p>
<p>Confirm New Password<br>
<%= g.password_field :password_confirmation %></p>
<%= g.submit "Update Password" %>
<% end %>
routes.rb
# ...
get '/me' => 'users#edit'
patch '/me' => 'users#update_email'
patch '/me' => 'users#update_pwd'
# ...
Now, I've been able to get the email updating to work as desired (with the necessary error messages/validations and so forth) but whenever the update password button is clicked, the view is rendered but nothing happens. Instead, it seems as if the update_email function is being called:
Started PATCH "/me" for ::1 at 2015-05-20 10:34:31 -0500
Processing by UsersController#update_email as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"msEsj6yxfdrbXjjdm6cH3JamrFU8R1EoZ5asmE831GSxLwpiiIW/wmGrr9HiQxFDySJtW5MKK6Ezq9hZaMNFtA==", "current_password"=>"[FILTERED]", "user"=>{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Update Password"}
←[1m←[36mUser Load (0.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1←[0m [["id", 2]]
DEPRECATION WARNING: You are passing an instance of ActiveRecord::Base to `find`. Please pass the id of the object by calling `.id`. (called from update_email ...)
user.rb
# ...
has_secure_password
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }
validates_uniqueness_of :email
validates :password, length:{ minimum: 8 }, on: :create
validates :password_confirmation, presence: true, on: :create
# ...
application_controller.rb
# ...
helper_method :current_user
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
rescue ActiveRecord::RecordNotFound
end
Error log (as seen above)
Started PATCH "/me" for ::1 at 2015-05-20 10:34:31 -0500
Processing by UsersController#update_email as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"msEsj6yxfdrbXjjdm6cH3JamrFU8R1EoZ5asmE831GSxLwpiiIW/wmGrr9HiQxFDySJtW5MKK6Ezq9hZaMNFtA==", "current_password"=>"[FILTERED]", "user"=>{"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Update Password"}
←[1m←[36mUser Load (0.0ms)←[0m ←[1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1←[0m [["id", 2]]
DEPRECATION WARNING: You are passing an instance of ActiveRecord::Base to `find`. Please pass the id of the object by calling `.id`. (called from update_email ...)
You can try the following, I think this will help.
Please revert back if you face any issue.
routes.rb
get '/me' => 'users#edit'
patch '/me' => 'users#update_data'
edit.html.erb
<%= form_for(current_user, :url => {:controller => 'users', :action => 'update_data'}) do |f| %>
<% if #user.errors.any? %>
<% for message in #user.errors.full_messages %>
<li><%= message %></li>
<% end %>
<% end %>
<p> Current Email: <%= current_user.email %> </p>
<p> New Email: <%= f.text_field :email %> </p>
<%= f.submit 'Save Changes', name: 'update_email' %>
<% end %>
<%= form_for(current_user, :url => {:controller => 'users', :action => 'update_data'}) do |g| %>
<p>Old Password<br>
<%= password_field_tag :current_password, params[:password] %></p>
<p>New Password<br>
<%= g.password_field :password %></p>
<p>Confirm New Password<br>
<%= g.password_field :password_confirmation %></p>
<%= g.submit 'Update Password', name: 'update_password' %>
<% end %>
users_controller.rb
def edit
#user = User.find(current_user)
end
def update_data
#user = User.find(current_user)
if params[:commit] == "update_email"
if #user.update_attributes(user_params_email)
flash[:notice] = "Your changes have been saved"
redirect_to me_url
else
render :edit
end
elsif params[:commit] == "update_password"
if #user.update_attributes(user_params_pwd) && User.find_by(username: current_user.username).try(:authenticate, params[:current_password])
flash[:notice] = "Password updated!"
redirect_to me_url
else
flash.now[:alert] = #user.errors.full_messages[0]
render :edit
end
else
render :edit
end
end
private
def user_params_email
params.require(:user).permit(:email)
end
def user_params_pwd
params.require(:user).permit(:password, :password_confirmation, :current_password)
end
i have a long list dropdown menu including all currencies, i want the last selected value to be the default selected value in the list.
i am using Rails 4.0.0 and ruby 2.0.0
i am not using a model, i am just using a controller. i have put the dropdown list options inside a helper.
form.html.erb
<div class="calculator">
<%= form_for :convertor, :url => {:controller => "converter", :action => "show" } do |f| %>
<%= f.label :from_currency %>
<%= f.select :from_currency, options_for_select(currencies, :selected => params[:from_currency]) %>
<%= f.text_field :amount, :placeholder => "Amount", id: "textfield" %>
<%= #amount %>
<br>
<%= f.label :to_currency %>
<%= f.select :to_currency, options_for_select(currencies, :selected => params[:to_currency].to_i ) %>
<%= #result %>
<br>
<%= f.submit "Calculate", class: "btn btn-large btn-primary", id: "submitButton" %>
<% end %>
</div>
the list options are loaded from a helper *<%= f.select :to_currency, options_for_select(currencies, :selected => params[:to_currency].to_i ) %>* with name currencies
the dropdown list, in a helper
def currencies
[
['United Arab Emirates Dirham (AED)', 'AED'],
['Netherlands Antillean Guilder (ANG)', 'ANG'],
['Argentine Peso (ARS)', 'ARS'],
['Australian Dollar (A$)', 'AUD'],
['Bangladeshi Taka (BDT)', 'BDT'],
['Bulgarian Lev (BGN)', 'BGN'],
['Bahraini Dinar (BHD)', 'BHD'],
]
end
what am i doing wrong here?
A couple of things:
options_for_select takes two arguments: the list of options and the value that you want selected.
You're passing through the value as a hash: :selected => params...
The parameter name is wrong.
In your controller, you're saying that the parameter is called this:
params[:convertor][:from_currency]
But in your view, you have params[:from_currency].
Therefore, the solution to this is to do this:
<%= f.select :from_currency, options_for_select(currencies, params[:convertor][:from_currency]) %>
This code works for me.
in application helper
module ApplicationHelper
def opts_for_select_cur
opts_for_select = [
['United Arab Emirates Dirham (AED)', 'AED'],
['Netherlands Antillean Guilder (ANG)', 'ANG'],
['Argentine Peso (ARS)', 'ARS'],
['Australian Dollar (A$)', 'AUD'],
['Bangladeshi Taka (BDT)', 'BDT'],
['Bulgarian Lev (BGN)', 'BGN'],
['Bahraini Dinar (BHD)', 'BHD'],
]
return opts_for_select
end
end
and in view
<script type="text/javascript">
$(document).ready(function(){
$('#st').change(function(){
var inputText = $('#st :selected').val();
$("#hidden_one").val(inputText);
$("a").attr("href", "?value="+inputText );
});
$('#aa').click(function(){
var inputText = $('#st :selected').val();
$("a").attr("href", "?value="+inputText );
});
});
<%= f.select :text, options_for_select(opts_for_select_cur, params[:value]), {}, { id: "st" } %>
<br>
<%= link_to "refresh",nil, id: "aa" %>
the result is a select box with selected value.
this can help
<%= f.label :from_currency %>
<% if #from_cur.present? %>
<%= f.select :from_currency, options_for_select(currencies, #from_cur) %>
<% else %>
<%= f.select :from_currency, options_for_select(currencies), :required => true %>
<% end %>
<%= f.text_field :amount, :placeholder => "Amount", :required => true, id: "textfield" %>
<br>
<%= f.label :to_currency %>
<% if #from_cur.present? %>
<%= f.select :to_currency, options_for_select(currencies, #to_cur), :required => true %>
<% else %>
<%= f.select :to_currency, options_for_select(currencies), :required => true %>
<% end %>
i appreciate.
I have this form:
<% #page_title = "Delete Technician: #{#technician.name}" %>
<%= link_to("<< Back to List", {:action => 'list', :id => #technician.id}, :class => 'back-link') %>
<div class="technician delete">
<h2>Delete Technician</h2>
<%= form_for(:technician, :url => {:action => 'destroy', :id => #technician.id}) do |f| %>
<p>Are you sure you want to permanently delete this technician?</p>
<p class="reference-name"><%= #technician.name %></p>
<div class="form-buttons">
<%= submit_tag("Delete Technician") %>
</div>
<% end %>
</div>
when I click on the submit button this is the url that I get:
www.site.com/technicians/1
instead of
www.site.com/technicians/destroy/1
am I not using the form_for helper correctly or is it a configuration somewhere?
You're making this more complicated than it needs to be. There is no reason for a form when a link or a button would do. Why not just this
<p>Are you sure you want to permanently delete this technician</p>
<div> <%= link_to "Delete", technician_path(#technician), :method => :delete %> </div>
That's it.