Question

I'm trying to create a charge with stripe. I get the following error when attempting to create order object, but I have set attr_accessor :stripe_card_token. Does anyone know what I am doing wrong?

ActiveModel::MassAssignmentSecurity::Error in OrdersController#create
Can't mass-assign protected attributes: stripe_card_token

OrdersController - Create action

def create
@order = current_cart.build_order(params[:order])
@order.ip_address = request.remote_ip
@order.user_id = current_user.id


respond_to do |format|
  if @order.save_with_payment

    @order.add_line_items_from_cart(current_cart)         
    Cart.destroy(session[:cart_id])
    session[:cart_id] = nil


    format.html { render :action => "success", :notice => 'Thank you for your order.' }
    format.xml { render :xml => @order, :status => :created, :location => @order }

  else
    format.html { render :action => "new" }
    format.xml { render :xml => @order.errors,
    :status => :unprocessable_entity }
  end
end
end

OrderModel

class Order < ActiveRecord::Base
  # PAYMENT_TYPES = [ "visa", "master card", "Amex", "Discover" ] Controll the payment options via Model
  attr_accessible :first_name, :last_name, :ip_address, :cart_id, :house_id
  attr_accessor :stripe_card_token


  belongs_to :user
  belongs_to :house
  belongs_to :cart

  has_many :transactions, :class_name => "OrderTransaction"
  has_many :line_items, :dependent => :destroy

  validates :house_id, presence: true
  validates :cart_id, presence: true



  def price_in_cents 
    (cart.total_price*100).round
  end

  def add_line_items_from_cart(cart)
    cart.line_items.each do |item|
      item.cart_id = nil
      line_items << item
    end
  end

  def save_with_payment
    if valid?
      Stripe::Charge.create(amount: price_in_cents, currency: "cad", description:     current_user.name, card: stripe_card_token)
      # self.stripe_order_token = order.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

OrderView _Form

<%= f.error_notification %>
<%= f.error_messages %>
<%= f.hidden_field :stripe_card_token %>
<%= f.hidden_field :cart_id%>

<div class="form-inputs">
  <p><%#if user does not have a house Make a page (please order a home valuation first) %></p>
  <div class="contain">  
    <h3>Select House</h3>      
    <%= f.input :house_id, :as => :radio_buttons, :collection =>  current_user.houses.all.map{|h| [h.address, h.id]}%>        
  </div>

  <%= f.input :first_name %>
  <%= f.input :last_name %>

  <div class="field">
    <%= label_tag :card_number, "Credit Card Number" %>
    <%= text_field_tag :card_number, nil, name: nil %>
  </div>
  <div class="field">
    <%= label_tag :card_code, "Security Code on Card (CVV)" %>
    <%= text_field_tag :card_code, nil, name: nil %>
  </div>
  <div class="field">
    <%= 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>

  <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="form-actions">
  <%= f.button :submit %>
</div> 

Orders.js.coffee

jQuery ->
  Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
  order.setupForm()

order =
  setupForm: ->
    $('#new_order').submit ->
      $('input[type=submit]').attr('disabled', true)
      if $('#card_number').length
        order.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, order.handleStripeResponse)

  handleStripeResponse: (status, response) ->
    if status == 200
      $('#order_stripe_card_token').val(response.id)
      $('#new_order')[0].submit()
    else
      $('#stripe_error').text(response.error.message)
      $('input[type=submit]').attr('disabled', false) 
Was it helpful?

Solution

You still need to include :stripe_card_token under attr_accessible in your model

OTHER TIPS

Active record (the layer in your rails stack that provides an interface between your ruby code and your database) protects your database from unwanted end-user assignment using the attr_accessible method. if present in your model it makes sure that a request can't write to your database unless the attribute is listed.

You've got attr_accessible here but don't have :stripe_card_token listed, so you can't save to that field.

attr_accessible :first_name, :last_name, :ip_address, :cart_id, :house_id add , :stripe_card_token

You may have though the attr_accessor :stripe_card_token line would somehow be related, but that just sets the getter and setter methods for the attribute.

The difference is better laid out here In this question

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top