Stripe token not carrying over to controller rails 4 - ruby-on-rails

The Issue
I've tested the CoffeeScript and the form makes the call to Stripe, sets the hidden field with the proper response token and submits the form. My issue is that once its submitted the controller doesn't seem to grab the token properly and throws this error: Stripe::InvalidRequestError - You must supply either a card or a customer id.
Next I tired taking the token that was generated and hard coded it into the controller to see if that would work. I submitted the form, that worked and payment was received on Stripes end. I'm pretty much out of ideas on what to try next. I'm wondering if I am forgetting something or missing something since payments is nested under assignments.
Gem Versions
Ruby: 2.1.0
Rails: 4.0.1
Stripe: 1.9.9
Files
/payment/new.html.erb
<%= form_for([#assignment, #payment]) do |f| %>
<% if #payment.errors.any? %>
<div class="error_messages">
<h2><%= pluralize(#payment.errors.count, "error") %> prohibited this subscription from being saved:</h2>
<ul>
<% #payment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.hidden_field :stripe_customer_token %>
<% if #payment.stripe_customer_token.present? %>
<p>This assignment has already been paid for.</p>
<% else %>
<div class="field">
<%= label_tag :card_number, "Credit Card Number" %>
<%= text_field_tag :card_number, nil, name: nil, placeholder: "00000000000000" %>
</div>
<div class="row">
<div class="field card__dates">
<%= 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"} %>
</div>
<div class="field card__cvv">
<%= label_tag :card_code, "CVV" %>
<%= text_field_tag :card_code, nil, name: nil, placeholder: "003", required: true, maxlength: 4, minlength: 3 %>
</div>
</div>
<% end %>
<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>
<div class="actions">
<%= f.submit "Pay " + number_to_currency(#assignment.price.to_s), class: 'btn btn__primary btn__large btn--fill' %>
</div>
payment_controller.rb
class PaymentsController < ApplicationController
def new
set_assignment
#payment = #assignment.build_payment
#price = #assignment.price
end
def create
set_assignment
#payment = #assignment.build_payment(payment_params)
if save_with_payment
redirect_to assignments_path, :notice => "Payment received, Thank you!"
# since payment was successful, set assignment paid to true
Assignment.update(#assignment, assignment_paid: true, project_status: "In Progress")
else
render :new
end
end
private
def save_with_payment
# Set your secret key: remember to change this to your live secret key in production
# See your keys here https://manage.stripe.com/account
Stripe.api_key = Rails.configuration.stripe[:secret_key]
# Get the credit card details submitted by the form
token = params[:stripe_customer_token]
# How much the assignment costs, which must be converted to cents
#amount = (#price * 100)
# Create the charge on Stripe's servers - this will charge the user's card
begin
charge = Stripe::Charge.create(
:amount => #amount,
:currency => "cad",
:card => token,
:description => "some description of the product"
)
rescue Stripe::CardError => e
redirect_to #assignment, :notice => "The card has been declined"
end
end
def set_assignment
#assignment = Assignment.friendly.find(params[:assignment_id])
end
def payment_params
params.require(:payment).permit(
:stripe_customer_token
)
end
end
payment.js.coffee
$ ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
payment.setupForm()
payment =
setupForm: ->
$('#new_payment').submit ->
$('input[type=submit]').attr('disabled', true)
if $('#card_number').length
payment.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, payment.handleStripeResponse)
handleStripeResponse: (status, response) ->
if status == 200
console.log response
$('#payment_stripe_customer_token').val(response.id)
$('#new_payment')[0].submit()
else
$('#stripe_error').text(response.error.message)
$('input[type=submit]').attr('disabled', false)
payment.rb
class Payment < ActiveRecord::Base
belongs_to :assignment
end

At least two problems as I saw. And I guess there may be more after progressing.
You don't have access to params within #save_with_payment
The problem happens in this line:
# Get the credit card details submitted by the form
token = params[:stripe_customer_token]
The params is protected by strong_params and you don't have access to it.
The fix is to permit all of the needed params in payment_params and reuse it within this method.
Actually you don't have #price within #create
This problem does not relate to the question directly but it exists.
This instance variable #price is in #new. And #create is another instance so you can't have it again.
The fix is to get it from payment_params

Related

Passing Rails 5 Form Value to Controller as Paramerter

I am having trouble passing a non-model form field from view to controller. The value I am trying to pass is amount
Thank you.
views/donations/index.html.erb
<%= form_tag donations_path, style: (current_user.card_last4? ? "display:none" : nil) do %>
<div id="error_explanation">
<% if flash[:error].present? %>
<p><%= flash[:error] %></p>
<% end %>
</div>
<article>
<%= label_tag(:amount, 'Donation Amount:') %>
<%= text_field_tag(:amount) %>
</article>
<%= link_to 'Donate', new_donation_path(amount: :amount), class: 'btn btn-primary', id: 'donateButton' %>
<% end %>
controllers/donations_controller.erb
def create
customer = current_user.stripe_customer
amount = params[:amount]
token = params[:stripeToken]
begin
Charge.charge(amount, token)
end
...
models/charge.rb
def self.charge(amount, token)
charge = Stripe::Charge.create(
amount: amount,
source: token,
currency: 'usd',
description: 'Test Charge'
)
end
...
Use a view tag like
<%= text_field_tag 'donation[amount]' %>
And permit the parameter in your controller
def donation_params
params.require(:donation).permit(:amount)
You can access the value with donation_params[:amount].
You shouldn't use link_to to trigger the form submission. Use submit_tag instead. Besides that, make sure your strong params whitelist whatever you're submitting.
I guess you are not using strong params. Why not just add |f| at the end like this
<%= form_tag donations_path, style: (current_user.card_last4? ? "display:none" : nil) do |f| %>
and then use <%= f.text_field :amount %>
Then at the params you should do something like params["donation"]["amount"] to get the value
EDIT: at the end change link_to for f.submit

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 :)

Can't send params (variables and one hardcoded value) to prefilled form in Rails 4

I am building a Rails 4 app which interacts heavily with a SOAP XML webservice. I am successfully making requests to the webservice with Savon using models inside the app.
But now I want to simply pass variables (and one hardcoded value) from the result of one request to pre-fill a form on another page before the user clicks submit and makes another request. I am doing this through an edit link at the moment. When I click on this it automatically calls the webservice (displaying an error message) - I don't want to call it at all at this stage.
I'm guessing that I can solve this somehow by changing the model and/or controller but I'm really stuck right now.
My view page which displays results from first request. (I need to send all the data in the edit link, which is very long):
<% if #search %>
<dl id ="reservation_info">
<h3><%= #search.restaurant_name %></h3>
<h4><%= #search.restaurant_phone_number %></h4>
<!-- HIDDEN -->
<% #search.restaurant_id %>
<dd>Booking ref: <%= #search.confirmation_number %></dd>
<!-- FOR CANCELLATION: -->
<% #search.reservation_id %>
<% #search.allowed_to_cancel_online %>
<dt><strong>Time / Date</strong></dt>
<dd><%= #search.dining_date_and_time %></dd>
<dt><strong>Guests</strong></dt>
<dd><%= #search.size %></dd>
<%= link_to 'Edit', guests_reservations_path(:partner_code => "DEV-DAN-BETH:73411"), restaurant_location_id: #search.location_id, session_id: #search.session_id, dining_date_and_time: #search.dining_date_and_time, first_name: #search.first_name, last_name: #search.last_name, email: #search.email, :method => :post %>
<dt><strong>Area</strong></dt>
<dd><%= #search.location_name %></dd>
<!-- HIDDEN -->
<% #search.location_id %>
<dt><strong>Your details:</strong></dt>
<dd><%= #search.first_name %></dd>
<dd><%= #search.last_name %></dd>
<dd><%= #search.session_id %></dd>
<dd><%= #search.email %></dd>
</dl>
<% end %>
Form which needs to be pre-filled / pre-populated:
<%= form_tag(reservations_path, method: :post) %>
<!-- ALWAYS HIDDEN FIELDS -->
<div class="field">
<%= text_field_tag :partner_code %>
</div>
<div class="field">
<%= text_field_tag :restaurant_location_id %>
</div>
<div class="field">
<%= text_field_tag :session_id %>
</div>
<!-- ACTION FIELDS -->
<div class="field">
<%= label_tag :dining_date_and_time %><br>
<%= text_field_tag :dining_date_and_time %>
</div>
<div class="field">
<%= label_tag :size, 'Guests' %><br>
<%= text_field_tag :size %>
</div>
<!-- HIDDEN PERSONAL DETAILS -->
<div class="field">
<%= label_tag :first_name %><br>
<%= text_field_tag :first_name %>
</div>
<div class="field">
<%= label_tag :last_name %><br>
<%= text_field_tag :last_name %>
</div>
<div class="field">
<%= label_tag :email %><br>
<%= text_field_tag :email %>
</div>
<div class="actions">
<%= submit_tag 'Continue', name: nil %>
</div>
1st request controller (not the best practice I know, but this is the only way it works, already tried to refactor it).:
class SearchesController < ApplicationController
def index
if params[:confirmation_number] && params[:email]
end
end
def show
#search = Search.new params[:confirmation_number], params[:email]
end
private
def search_params
params.require(:search).permit(:confirmation_number, :email)
end
end
Controller for second request (Guest is empty as not sure what to do there):
class ReservationsController < ApplicationController
def index
if params[:partner_code] && params[:restaurant_location_id] && params[:session_id] && params[:dining_date_and_time] && params[:size] && params[:first_name] && params[:last_name] && params[:email]
end
end
def show
#reservation = Reservation.new params[:partner_code], params[:restaurant_location_id], params[:session_id], params[:dining_date_and_time], params[:size], params[:first_name], params[:last_name], params[:email]
end
def guest
end
private
def reservation_params
params.require(:reservation).permit(:partner_code, :restaurant_location_id, :session_id, :dining_date_and_time, :size, :first_name, :last_name, :email, :confirmation_number)
end
end
2nd request model (the one which is calling automatically) Also, N.B Active Record inheritance is redundant here as values are not being saved to DB when webservice is called / form posted:
class Reservation < ActiveRecord::Base
attr_accessor :confirmation_number, :reservation_id, :dining_date_and_time, :size, :session_id, :first_name, :last_name, :confirmation_number, :allowed_to_cancel_online, :restaurant_phone_number, :restaurant_id, :restaurant_name, :location_id, :location_name, :email
def client
Savon.client(wsdl: "http://wsdl-example-uri", follow_redirects: :follow_redirects)
end
def initialize(partner_code, restaurant_location_id, session_id, dining_date_and_time, size, first_name, last_name, email)
message = {'PartnerCode' => partner_code, 'RestaurantLocationId' => restaurant_location_id, 'SessionId' => session_id, 'DiningDateAndTime' => dining_date_and_time, 'Size' => size}
message.merge!('Booker' => {'UserWithoutALogin' => {'FirstName' => first_name, 'LastName' => last_name, 'EMail' => email}})
response = client.call(:book_reservation, message: message)
if response.success?
data = response.to_array(:book_reservation_response).first
if data
#confirmation_number = data[:confirmation_number]
#reservation_id = data[:reservation_id]
end
else
errors.add "Failed to make SOAP request"
end
end
end
Set up boundries!
When dealing with API's and web services - it can be tempting to do it on the model layer - you add a little fetch_from_facebook method and start whittling out attributes_from_facebook methods and so forth. But this is a huge anti-pattern as it creates strong couplings between your application and the external service.
You definitely NEVER want to call an external service in the initialize method of your model as it will make testing extremely difficult. And you should ALMOST NEVER override the initialize method of an ActiveRecord model. If you do your models should at least have the expected interface:
def initialize(hash = {}, &block)
end
Don't be that guy - be nice to your fellow devs and respect the principle of least surprise.
Instead use service objects (plain old ruby objects) to handle fetching data from remote services.
Also if you are not saving to the database don't use ActiveRecord for you models! Instead just use a plain ruby class and include ActiveModel::Model.
What about forms?
Rails has many built in form helpers which make it easy to bind form inputs to a model instance:
<%= form_form(#reservation) do |f| %>
<div class="field">
<%= f.label_tag :dining_date_and_time %><br>
<%= f.text_field_tag :dining_date_and_time %>
</div>
<% end %>
See RailsGuides: Form Helpers. I would consider taking a break and do a basic tutorial of setting up a CRUD app before you continue on with you project. Dealing with external data sources is tricky and you need a solid foundation to start on.
Edit
This is an example of how you would use services to deal with interacting with an external API:
class PushReservationService
# Use dependency injection so we can mock the client in tests
def initialize(client = nil)
#client = client || Savon.client(
wsdl: "http://wsdl-example-uri",
follow_redirects: :follow_redirects
)
end
# return [reservation]
def call(reservation, **kwargs, &block)
# set default options
message = kwargs.merge(
'PartnerCode' => reservation.partner_code,
'RestaurantLocationId' => reservation.restaurant_location_id,
'SessionId' => reservation.session_id,
'DiningDateAndTime' => reservation.dining_date_and_time,
'Size' => reservation.size
)
response = #client.call(:book_reservation, message: message)
if response.success?
data = response.to_array(:book_reservation_response).first
if data
reservation.assign_attributes(
confirmation_number: data[:confirmation_number]
reservation_id: data[:reservation_id]
)
yield reservation, data if block_given?
reservation.save
return true
end
end
false
end
end
Calling them from your controller is pretty easy:
def create
#reservation = Reservation.new(reservation_params)
if #reservation.save
service = PushReservationService.new
if service.call(#reservation)
redirect_to #reservation, notice: 'Confirmed!'
else
# #todo strategy for dealing with failed confirmation.
flash[:alert] = 'Your reservation was created but we could not confirm your reservation.'
redirect_to edit_reservation_path(#reservation)
end
else
# render form again so that user can correct basic validation errors like a wrong email
render :new
end
end
This is basically how I would do based on my experience of dealing with SOAP based payment systems.
Within your boundaries everything is a run of the mill Rails app. Only your services have to deal with the huge PITA that is SOAP and the eccentricities of whatever API you are dealing with.

How to pass parameters from html.erb to a different html.erb

I'm playing with the messenger gem in rails 4.
I have a graph of nodes and I want to be able to bring up a message box (initially in a different page but will make it a partial later) when a node is pressed so that the current user can message that node.
The id for the clicked node is kept in a div called NameID
At the moment all I've got working is a button that opens the new message page and then you can choose a user from a drop down list. I guess I want that drop down list- the recipient- to be prepopulated from the currently clicked node on the index page.
Here is what I have so far:
index.html.erb
<p><a class="btn btn-lg btn-primary" id="BtnMessageNode" href="/messages/new">Start conversation</a></p>
<div id=NameID><<THIS IS POPULATED BY JAVASCRIPT>></div>
messages_controller.rb
class MessagesController < ApplicationController
before_action :authenticate_user!
def new
#chosen_recipient = User.find_by(id: params[:to].to_i) if params[:to]
end
def create
recipients = User.where(id: params['recipients'])
conversation = current_user.send_message(recipients, params[:message][:body], params[:message][:subject]).conversation
flash[:success] = "Message has been sent!"
redirect_to conversation_path(conversation)
end
end
helpers/messages_helper.rb
module MessagesHelper
def recipients_options(chosen_recipient = nil)
s = ''
User.all.each do |user|
s << "<option value='#{user.id}' data-img-src='#{gravatar_image_url(user.email, size: 50)}' #{'selected' if user == chosen_recipient}>#{user.name}</option>"
end
s.html_safe
end
end
messages/new.html.erb
<% page_header "Start Conversation" %>
<%= form_tag messages_path, method: :post do %>
<div class="form-group">
<%= label_tag 'message[subject]', 'Subject' %>
<%= text_field_tag 'message[subject]', nil, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= label_tag 'message[body]', 'Message' %>
<%= text_area_tag 'message[body]', nil, cols: 3, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= label_tag 'recipients', 'Choose recipients' %>
<%= select_tag 'recipients', recipients_options(#chosen_recipient), multiple: true, class: 'form-control chosen-it' %>
</div>
<%= submit_tag 'Send', class: 'btn btn-primary' %>
<% end %>
There are basically two ways to pass parameters to GET routes:
A. Named segments
/users/:user_id/message/new
This nested route would be great if you are sending a message to a single user.
B. Query parameters
Rails supports query parameters as well:
/message/new?to=2
Rails automatically adds query parameters to the params hash. So in this case you would do params[:to].
You can use the Rails route helpers so that you don't have to deal with encoding urls yourself:
new_message_path(to: #user.id)
Use query params for optional parameters like filters and sorting or in this case a preset. Don't use them like users?id=5.

Form not working on Access Denied redirection in Rails 4

I'm working on a Rails 4 web application, using Devise and CanCanCan.
When a user first signs up to create an account, they are redirected to a subscription page where they enter in credit card details, etc.
User Creation -> Subscription Creation = Form works
This is working absolutely perfectly and once they enter in their subscription information, a permission change is made on their account and they can then access a new part of the site. All good.
Now the issue I am having is, if a user signs up, then tries to access this new part of the site without subscribing, I redirect them to the subscription page. However when I do this, the form just doesn't work. They hit submit and nothing happens.
User Creation -> Tries to access resource, gets redirected to
Subscription Creation = Form doesn't work
Here is the code I am using to perform the redirection:
application_controller.rb
def access_denied(exception)
redirect_to(new_subscription_path, alert: exception.message + " Please subscribe.")
end
The strange thing is that I am using the exact same code to redirect when they first create a user account. This is shown here:
registrations_controller.rb
def after_sign_up_path_for(resource)
new_subscription_path
end
Here is the code for the subscription controller:
class SubscriptionsController < ApplicationController
before_filter :authenticate_user!
def new
#subscription = Subscription.new
end
def create
#subscription = Subscription.new(subscription_params)
#user = current_user
#subscription.user_id = current_user.id
if #subscription.save_with_payment
redirect_to success_path, :notice => "Thank you for subscribing!"
if current_user.role = "guest"
User.update(current_user.id, role: "read")
end
UserMailer.subscription_welcome_email(#user).deliver
else
render :new
end
end
def show
#subscription = Subscription.find(params[:id])
end
def destroy
#subscription = Subscription.find_by(user_id: current_user.id)
User.update(current_user.id, role: "guest")
unless #subscription.stripe_customer_id.nil?
customer = Stripe::Customer.retrieve(#subscription.stripe_customer_id)
customer.subscriptions.retrieve(customer.subscriptions.first.id).delete
end
#user = current_user
UserMailer.subscription_destroy_email(#user).deliver
#subscription.destroy
rescue Stripe::StripeError => e
logger.error "Stripe Error: " + e.message
errors.add :base, "Unable to cancel your subscription. #{e.message}."
false
end
def subscription_params
params.require(:subscription).permit(:stripe_card_token, :last_4_digits, :plan, :expiry_month, :expiry_year)
end
end
Form code:
<div class='panel panel-default'>
<div class='panel-heading'>
<h2>Subscribe</h2>
</div>
<div class='panel-body'>
<%= semantic_form_for #subscription, :html => {:class => 'main-form'} do |f| %>
<font color=red><b><%= f.semantic_errors *f.object.errors.keys %></b></font>
<%= f.hidden_field :stripe_card_token %>
<div id='stripe_error' class="alert alert-info" style='display:none'>
</div>
<span class="help-block">Nothing is billed to your card for 7 days. <b>Guaranteed. </b>
<br>If you choose to continue after 7 days, only then will you be billed.</span>
<div class='form-group'>
<%= label_tag :card_number, "Credit Card Number" %><%= image_tag "welcome/checkout/amex.png", alt: "American Express", class: "credit-card-image" %><%= image_tag "welcome/checkout/mastercard.png", alt: "Mastercard", class: "credit-card-image" %><%= image_tag "welcome/checkout/visa.png", alt: "Visa", class: "credit-card-image" %>
<%= text_field_tag :card_number, nil, name: nil, class: 'form-control input-box', :placeholder => 'Credit Card Number' %>
</div>
<div class='row'>
<div class="col-xs-6">
<%= label_tag :card_code, "Security Code on Card (CVC)" %><%= image_tag "welcome/checkout/credit.png", alt: "Credit Card Image", class: "credit-card-image" %>
<%= text_field_tag :card_code, nil, name: nil, class: 'form-control input-box', :placeholder => 'Security Code on Card (CVC)' %>
</div>
<div class="col-xs-6">
<%= label_tag :card_month, "Card Expiration" %><br>
<%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month", class: 'expiration'} %>
<%= select_year nil, {start_year: Date.today.year+1, end_year: Date.today.year+15}, {name: nil, id: "card_year", class: 'expiration'} %>
</div>
</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>
<div>
<%= f.submit "Subscribe", class: 'btn standard-button' %>
</div>
<% end %>
</div>
</div>
Can anyone assist? Let me know if any extra code is required. Thanks
EDIT: Just to make things weird, this error is only happening when I hit a link in my navigation that is new_subscription_path .. the access denied works fine if I type in manually the URL of the permissioned resource. Could there be something wrong with the path I am using in the header? Do I need to pass something specific into it? I've also tried to check if it was JavaScript by adding in a console log, but nothing comes through, so I don't think this is an issue, despite it feeling like a JS issue.
You should check you javascript. Clearly it blocks form from submission. I've looked at your previous question here and it looks like your handleStripeResponse handler always goes into else condition block not submitting form as the result. My bet is that $('meta[name="stripe-key"]').attr('content') is undefined after your redirection.
Disabled Turbolinks solved this problem

Resources