How to get value from other class in Rails - ruby-on-rails

I'm not sure if I am phrasing this question correctly. I am using the Stripe API for a Harry Potter themed Rails online store demo app. I followed the Stripe boilerplate code, so I currently have the amount set at a hardcoded value of $1.00. In my shopping cart, there is a method that displays the total cost of all items in the cart. That works fine, but I can't figure out how to pass that value to the Charges controller so that it sets that as the amount of the payment.
I'm fairly new to Rails, so any helpful explanations would be greatly appreciated.
Here is my charges/new.html.erb file:
<%= 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: $1.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="100"
data-locale="auto"></script>
<% end %>
Here is my Charges controller:
class ChargesController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
def new
end
def create #METHOD IS CALLED AFTER PAYMENT IS MADE
# Amount in cents
#amount = 100
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => 'Witch or Wizard',
:currency => 'usd'
)
Cart.destroy(session[:cart_id])
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
Here is my carts/show.html.erb file:
<p id="notice"><%= notice %></p>
<h2>My Cart</h2>
<table class="table table-responsive table-striped">
<thead>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Total Price in Galleons</th>
<th>Total Price in Muggle Currency</th>
</tr>
<tbody>
<%= render(#cart.line_items) %>
<tr>
<td>Total</td>
<td><%= number_to_currency(#cart.total_price * 7.35) %></td>
<td></td>
<td></td>
</tr>
</tbody>
</thead>
</table>
<br>
<div class="row">
<div class="col-md-3">
<div class="row">
<div class="col-md-4">
<%= link_to 'Back', products_path, :class => 'btn btn-primary whiteText' %>
</div>
<div class="col-md-4">
<%= link_to "Checkout", new_charge_path, :class => 'btn btn-success whiteText' %>
</div>
<div class="col-md-4">
<%= link_to 'Empty Cart', #cart, method: :delete, data: {confirm: 'Are you sure you want to empty your cart?'}, :class => 'btn btn-danger whiteText' %>
</div>
</div>
</div>
<div class="col-md-9"></div>
</div>
Here is my Carts controller:
class CartsController < ApplicationController
before_action :set_cart, only: [:show, :edit, :update, :destroy]
rescue_from ActiveRecord::RecordNotFound, with: :invalid_cart
# GET /carts
# GET /carts.json
def index
#carts = Cart.all
end
# GET /carts/1
# GET /carts/1.json
def show
end
# GET /carts/new
def new
#cart = Cart.new
end
# GET /carts/1/edit
def edit
end
# POST /carts
# POST /carts.json
def create
#cart = Cart.new(cart_params)
respond_to do |format|
if #cart.save
format.html { redirect_to #cart, notice: 'Cart was successfully created.' }
format.json { render :show, status: :created, location: #cart }
else
format.html { render :new }
format.json { render json: #cart.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /carts/1
# PATCH/PUT /carts/1.json
def update
respond_to do |format|
if #cart.update(cart_params)
format.html { redirect_to #cart, notice: 'Cart was successfully updated.' }
format.json { render :show, status: :ok, location: #cart }
else
format.html { render :edit }
format.json { render json: #cart.errors, status: :unprocessable_entity }
end
end
end
# DELETE /carts/1
# DELETE /carts/1.json
def destroy
#cart.destroy if #cart.id == session[:cart_id]
session[:cart_id] = nil
respond_to do |format|
format.html { redirect_to root_path, notice: 'Cart was emptied.' }
format.json { head :no_content }
end
end
def update_quantity
#line_item.update_attribute(:quantity)
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cart
#cart = Cart.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def cart_params
params.fetch(:cart, {})
end
def invalid_cart
logger.error "Attempt to access invalid cart #{params[:id]}"
redirect_to root_path, notice: 'Invalid cart'
end
end
Here is my Cart model:
class Cart < ApplicationRecord
has_many :line_items, dependent: :destroy
def add_product(product)
current_item = line_items.find_by(product_id: product.id)
if current_item
current_item.quantity += 1
else
current_item = line_items.build(product_id: product.id)
end
current_item
end
def total_price
line_items.to_a.sum {|item| item.total_price}
end
def convert_to_muggle(galleons)
line_items.to_a.sum {|item| item.convert_to_muggle}
end
end
And here is my routes file:
Rails.application.routes.draw do
resources :charges
resources :orders
resources :line_items
resources :carts
devise_for :users
match 'users/:id' => 'users#destroy', :via => :delete, :as => :admin_destroy_user
resources :users, only: [:index, :show, :edit, :update]
root 'products#index'
resources :products
controller :products do
post '/products/destroy' => 'products#destroy', as: :destroy
get '/products/add_to_cart' => 'products#add_to_cart', as: :add_to_cart
get '/products/remove_from_cart' => 'products#remove_from_cart', as: :remove_from_cart
end
controller :line_items do
post '/line_items/increase_quantity' => 'line_items#increase_quantity', as: :increase_quantity
end
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

In your charges_controller, change the amount:
#amount = #cart.total_price * 735
And your charges/new.html.erb:
<span>Amount: <%= number_to_currency(#cart.total_price * 7.35) %></span>
and
data-amount="<%= #cart.total_price * 735 %>"
Let me know if that helps.

Related

View Rails record Associations in modal

In my Rails app I have 3 models Kid, Classroom, and Teacher. Basically, I have a table in my view which lists all the classrooms, when I click on a button I want a modal to pop up that lists the teachers and students assigned to that classroom, as there is an association where a Classroom has_many Teachers and has_many Kids. I have the code ready for the modal, I have copied it below, however I am having a difficult time scoping a specific classroom object to the modal. All help is appreciated!
<div class="modal fade" id="showClassModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 id="showClassroomHeader"></h4>
</div>
<div class="modal-body">
<h4>Teachers Assigned</h4>
<ol>
<% #classroom.teachers.each do |teacher| %>
<li><%= teacher.first_name %> <%= teacher.last_name %></li>
<% end %>
</ol>
<br>
<h4>Students</h4>
<ol>
<% #classroom.kids.each do |kid| %>
<li><%= kid.first_name %> <%= kid.last_name %></li>
<% end %>
</ol>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<% if current_user.admin? %>
<button class="btn btn-warning" id="editClassroomBtn">Edit</button>
<% end %>
</div>
</div>
</div>
EDIT:
Classroom controller:
class ClassroomsController < ApplicationController
before_action :set_classroom, only: [:show, :edit, :update, :destroy]
# GET /classrooms
# GET /classrooms.json
def index
#user ||= current_user
if current_user.admin?
#classrooms = Classroom.all
else
#classrooms = #user.classrooms.all
end
end
# GET /classrooms/1
# GET /classrooms/1.json
def show
classroom = Classroom.find(params[:id])
render :text => classroom.class_desc
end
# GET /classrooms/new
def new
#classroom = Classroom.new
end
# GET /classrooms/1/edit
def edit
end
# POST /classrooms
# POST /classrooms.json
def create
#classroom = Classroom.new(classroom_params)
classroom.user = current_user
respond_to do |format|
if #classroom.save
format.html { redirect_to root_url, notice: 'Classroom was successfully created.' }
format.json { render :show, status: :created, location: #classroom }
else
format.html { render :new }
format.json { render json: #classroom.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /classrooms/1
# PATCH/PUT /classrooms/1.json
def update
respond_to do |format|
if #classroom.update(classroom_params)
format.html { redirect_to root_url, notice: 'Classroom was successfully updated.' }
format.json { render :show, status: :ok, location: #classroom }
else
format.html { render :edit }
format.json { render json: #classroom.errors, status: :unprocessable_entity }
end
end
end
# DELETE /classrooms/1
# DELETE /classrooms/1.json
def destroy
#classroom.destroy
respond_to do |format|
format.html { redirect_to classrooms_url, notice: 'Classroom was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_classroom
#classroom = Classroom.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def classroom_params
params.require(:classroom).permit(:class_name, :class_desc, :capacity, :start_range, :end_range)
end
end
Routes.rb:
Rails.application.routes.draw do
resources :rationales
resources :teachers
resources :classrooms
resources :kids
devise_for :users, :skip => [:sessions]
as :user do
get 'login' => "devise/sessions#new", :as => :new_user_session
post 'login' => 'devise/sessions#create', :as => :user_session
delete 'logout' => 'devise/sessions#destroy', :as => :destroy_user_session
end
root :to => 'kids#index'
resources :kids do
get 'discharge', on: :member
end
resources :kids do
get 'restore', on: :member
end
end
As mentioned in the comments section above, adding the modal inside <% #classrooms.each do |classroom| %> did the trick!

Deleting Nested Reviews Deletes the whole Post Created

I am setting a nested review scaffold inside the Post scaffold however, when i try to delete a review that is nested inside the show page in the Post, The whole post is deleted. how can i delete only the reviews without the post?
here's my code:
posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user! , except: [:index,:show]
before_filter :check_user, only: [:edit,:update,:destroy]
# GET /posts
# GET /posts.json
def search
if params[:search].present?
#posts = Post.search(params[:search])
else
#posts = Post.all
end
end
def index
if params[:tag]
#posts = Post.tagged_with(params[:tag])
else
#posts = Post.all
end
end
# GET /posts/1
# GET /posts/1.json
def show
#reviews = Review.where(post_id: #post.id)
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to root_url, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:title, :description,:image,:all_tags)
end
def check_user
if current_user.id != #post.user_id
redirect_to root_path , alert: "Sorry this Post belongs to someone else"
end
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users
resources :posts do
collection do
get 'search'
end
resources :reviews , except: [:show,:index] do
member do
get "like" => "reviews#upvote"
get "dislike" => "reviews#downvote"
end
end
end
get 'pages/help'
get 'pages/blog'
get 'pages/contact'
get 'pages/tour'
resources :posts
root 'posts#index'
get 'tags/:tag', to: 'posts#index', as: "tag"
end
reviews_controller.rb
class ReviewsController < ApplicationController
before_action :set_review, only: [ :edit, :update, :destroy, :upvote,:downvote]
before_action :set_post
before_action :authenticate_user!
respond_to :html
def new
#review = Review.new
respond_with(#review)
end
def edit
end
def create
#review = Review.new(review_params)
#review.user_id = current_user.id
#review.post_id = #post.id
#review.save
redirect_to post_path(#post)
end
def update
#review.update(review_params)
respond_with(#post)
end
def destroy
#review.destroy
respond_with(#review)
end
def upvote
#review.upvote_from current_user
redirect_to :back
end
def downvote
#review.downvote_from current_user
redirect_to :back
end
private
def set_review
#review = Review.find(params[:id])
end
def set_post
unless #post = Post.where(id: params[:post_id]).first
redirect_to posts_path, flash: {alert: "Post doesn't exists"}
end
end
def review_params
params.require(:review).permit(:comment)
end
end
models/review.rb
class Review < ActiveRecord::Base
acts_as_votable
belongs_to :user
belongs_to :post
end
models/post.rb
class Post < ActiveRecord::Base
searchkick
has_many :reviews , dependent: :destroy
has_many :taggings
has_many :tags, through: :taggings
#Paperclip Installation
has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
def all_tags=(names)
self.tags = names.split(",").map do |name|
Tag.where(name: name.strip).first_or_create!
end
end
def all_tags
self.tags.map(&:name).join(", ")
end
def self.tagged_with(name)
Tag.find_by_name!(name).posts
end
end
views/posts/index.html.erb
<table class="table">
<thead>
<tr>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><h4><%=link_to post.title , post%></h4></td>
<td><%=raw tag_links(post.all_tags)%></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<%end%>
</tbody>
</table>
<%= link_to 'new post', new_post_path %>
views/posts/show.html.erb
<div class="center">
<div class="right-align">
<h2><%= #post.title %></h2>
<hr>
</div>
<%if #post.image.exists?%>
<%= image_tag #post.image.url(:medium) %>
<%end%>
<div class="right-align">
<%= markdown #post.description %>
<br>
<table class="table table-bordered">
<tbody>
<% #reviews.each do |review|%>
<tr>
<td >
Welcome back <%= current_user.name %>
<h4><%= link_to "like" ,like_post_review_path(#post, review) , class: " btn btn-primary glyphicon glyphicon-chevron-up"%></h4>
<p><%= review.get_upvotes.size%></p>
<p><%= review.get_downvotes.size%></p>
<h4><%= link_to "Dislike" , dislike_post_review_path(#post, review) , class: "btn btn-primary glyphicon glyphicon-chevron-down"%></h4>
<p><%= markdown review.comment %></p>
<p><%= link_to "Edit", edit_post_review_path(#post, review) %></p>
<p><%= link_to 'Destroy', #review, method: :delete, data: { confirm: 'Are you sure?' } %></p>
</td>
</tr>
<%end%>
</tbody>
</table>
<p><%= link_to 'Write Review', new_post_review_path(#post) , class: "btn btn-primary" %></p>
<%= link_to 'Edit', edit_post_path(#post) %> |
<%= link_to 'Back', posts_path %>
</div>
</div>
Update:
i tried changing the code as suggested in the destroy method and in the Reviews Controller and the Post Show page but still getting the error. Here's the error i am getting :
Look like a typo, change:
<p><%= link_to 'Destroy', #review, method: :delete, data: { confirm: 'Are you sure?' } %></p>
to:
<p><%= link_to 'Destroy', review, method: :delete, data: { confirm: 'Are you sure?' } %></p>
and change your reviews controller destroy:
def destroy
#review.destroy
redirect_to :back
end

Acts_as_taggable gem. Cloud

I have a list of categories. When you click on a category lets say Computers it should only show a tag cloud of the items in that category in this case Computers. Tags from the Mobile Phone category should not be showing.
Currently my tag cloud shows all tags across all categories.
Im using the Acts_as_tagable_gem https://github.com/mbleigh/acts-as-taggable-on
How would someone go about showing only the tags inside that category?
Here is my view. Please refer to tag_cloud
<p id="notice"><%= notice %></p>
<div class = "col-md-3">
<h1>
<strong><%= #category.name %></strong>
</h1>
</div>
<div class = "col-md-9">
<div id="tag_cloud">
<% tag_cloud Item.tag_counts, %w[s m l] do |tag, css_class| %>
<%= link_to tag.name, tag_path(tag.name, id: #category.id), class: css_class %>
<% end %>
</div>
</div>
<div class = "col-md-12">
<div class="line-separator"></div>
</div>
<div class = "col-md-12">
<div id="items" class="transitions-enabled">
<% #items.each do |item| %>
<div class="box panel panel-default">
<div class="itemlisttitle"><%= item.title %></div>
<%= link_to image_tag(item.image.url (:medium)), item %>
<div class ="panel-body">
<div class = "itemlistprice">$<%= item.price %></div>
<div class = "itemlistretailer"><%= image_tag item.user.avatar(:thumb) %> Retailer: <%= link_to item.user.username, item.user %></div>
</div>
</div>
<% end %>
</div>
</div>
Routes Please refer to the last line
Rails.application.routes.draw do
resources :categories
get 'password_resets/new'
get 'password_resets/edit'
get 'sessions/new'
resources :users
get 'user_items' => 'users#show_user_items'
root 'items#home'
get 'signup' => 'users#new'
get 'show' => 'users#show'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :items
get 'items_new' => 'items#new'
get 'tags/:tag', to: 'categories#show', as: :tag
Category Controller Please refer to show action
class CategoriesController < ApplicationController
before_action :set_category, only: [:show]
before_action :admin_user, only: [:destroy, :index, :edit]
def index
#categories = Category.all
end
def show
if params[:tag]
#items = Item.tagged_with(params[:tag])
else
#items = Item.where(category_id: #category.id).order("created_at DESC")
end
end
def new
#category = Category.new
end
def edit
end
def create
#category = Category.new(category_params)
respond_to do |format|
if #category.save
format.html { redirect_to #category, notice: 'Category was successfully created.' }
format.json { render :show, status: :created, location: #category }
else
format.html { render :new }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #category.update(category_params)
format.html { redirect_to #category, notice: 'Category was successfully updated.' }
format.json { render :show, status: :ok, location: #category }
else
format.html { render :edit }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
def destroy
#category.destroy
respond_to do |format|
format.html { redirect_to categories_url, notice: 'Category was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_category
#category = Category.find(params[:id])
end
def category_params
params.require(:category).permit(:name, :parent_id)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.try(:admin?)
end
end

Rails : error param is missing or the value is empty : annonce

I want to creat a classified ads website for a project in school and I try to create a form to send a message by email at a member of the website. The email adress is contained in a model which is name "Membre" and this model is link at a model who is name "Annonce" which contained the ad.
But when I try to create that, I have this error :
param is missing or the value is empty: annonce
app/controllers/annonces_controller.rb:104:in `annonce_params'
app/controllers/annonces_controller.rb:29:in `create'
Here the Ad controller :
class AnnoncesController < ApplicationController
before_action :set_annonce, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, :except => [:index]
# GET /annonces
# GET /annonces.json
def index
#annonces = Annonce.all
end
# GET /annonces/1
# GET /annonces/1.json
def show
end
# GET /annonces/new
def new
#annonce = Annonce.new
end
# GET /annonces/1/edit
def edit
end
# POST /annonces
# POST /annonces.json
def create
#annonce = Annonce.new(annonce_params)
#annonce.membre_id = current_membre.id
respond_to do |format|
if #annonce.save
format.html { redirect_to #annonce, notice: t('annonce_cree_succes') }
format.json { render :show, status: :created, location: #annonce }
else
format.html { render :new }
format.json { render json: #annonce.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /annonces/1
# PATCH/PUT /annonces/1.json
def update
respond_to do |format|
if #annonce.update(annonce_params)
format.html { redirect_to #annonce, notice: t('annonce_cree_succes') }
format.json { render :show, status: :ok, location: #annonce }
else
format.html { render :edit }
format.json { render json: #annonce.errors, status: :unprocessable_entity }
end
end
end
# DELETE /annonces/1
# DELETE /annonces/1.json
def destroy
#annonce.destroy
respond_to do |format|
format.html { redirect_to annonces_url, notice: t('annonce_destroy_succes') }
format.json { head :no_content }
end
end
# GET /annonces/contact/1
def contact
#form_contact = FormContact.new
if #form_contact.valid?
#MembreMailer.email_contact(Membre.where(:id => #annonce.membre_id ),current_membre,#annonce,#message)
#annonce = Annonce.find(params[:id])
#recepteur = Membre.where(:id => #annonce.membre_id )
#membre = current_membre
mail(:to => "#{recepteur.pseudo} <#{recepteur.email}>", subject: 'Reponse à l\'une de vos annnonces')
redirect_to root
end
end
# GET /annonces/report/1
def report
#annonce = Annonce.find(params[:id])
end
private
def authenticate_user!
if membre_signed_in?
#super
else
redirect_to login_path, :notice => 'Merci de vous connecter pour effecter cette action'
## if you want render 404 page
## render :file => File.join(Rails.root, 'public/404'), :formats => [:html], :status => 404, :layout => false
end
end
# Use callbacks to share common setup or constraints between actions.
def set_annonce
#annonce = Annonce.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def annonce_params
params.require(:annonce).permit(:id, :titre, :corps, :prix, :membre_id, :categorie, :created_at, :image)
end
Here the view contact :
<div class="col-md-offset-2 col-md-8 well panel panel-default">
<h2 class='panel-heading text-center'><%= t('contacter') %></h2>
<div class="panel-body text-center">
<%= form_for(:form_contact, :url => {:action => :create}) do |f| %>
<div class="field block-center">
<%= f.label "message" %></br>
<%= f.text_area(:message, size: "50x15")%>
</div></br>
<div class="actions form-group col-md-offset-3 col-md-6">
<%= submit_tag t('envoyer'), :class => "btn btn-large btn-block btn-primary" %>
</div>
<% end %>
</div>
</div>
<p class='row'> </p>
And here the FormContact class:
class FormContact < ActiveForm::Base
attr_accessor :message
validates_presence_of :message
def new
#form_contact = FormContact.new(login_form)
end
def index
#form_contact = FormContact.new
end
private
def login_form
params.require(:form_contact).permit(:message)
end
end
How can I fix that ?
Thanks in advance
This is routing error, you should call the create method of FormContactsController, not AnnoncesController create method.
<%= form_for(:form_contact, :url => {:controller => "FormContactsController", :action => :create}) do |f| %>

RAILS - Stripe Recipient Id Error

I'm building a two sided marketplace, where users are paid out when an item of theirs, sells.
I have a form that a user fills out when wanting to list an item on the marketplace. It includes many inputs, but the important ones for this question are the Stripe COUNTRY, ACCOUNT, and ROUTING inputs. This is so that they can be paid automatically after their items sells.
I'm storing a Stripe recipient ID in the user database, so that they don't have to enter their bank account info every time they post a new item. (Which can be seen in the #create action) Everything that I'm about to post below works perfectly, BUT ONLY ONCE. After posting an item the first time, the user Recipient ID successfully saves to my user database. BUT, if that user attempts to post another item, I get a Stripe error, saying that: "You must supply either a card, customer, or bank account to create a token.", when attempting to submit the form. This error is shown in my Stripe dashboard as well.
I am under the assumption that is has to do with Strong Params? At first, I did not have :Country, :Routing_number, or :Account_number in the params in the listing_controller, so I have added them in, but it did not fix the error. Am I close? Can anyone spot what I'm doing wrong?
_FORM.HTML.ERB:
<%= form_for #listing, :html => { :multipart => true } do |f| %>
<% if #listing.errors.any? %>
<div id="error_explanation" class="alert alert-danger alert-dismissable">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">× </button>
<h2><%= pluralize(#listing.errors.count, "error") %> prohibited this listing from being saved:</h2>
<ul>
<% #listing.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div id="stripe_error" class="alert alert-danger" style="display:none">
<noscript> Javascript is disabled. Order cannot be placed. First enable it in your browser.</noscript>
<% if current_user.recipient.blank? %>
<br>
<h1>Bank Account Information</h1>
<p class="sm-message">(You'll only need to enter this once.)</p>
<div class="form-group">
<%= label_tag :country %>
<%= text_field_tag :country, nil, { :name => nil, :'data-stripe' => "country", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :routing_number %>
<%= text_field_tag :routing_number, nil, { :name => nil, :'data-stripe' => "routingNumber", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :account_number %>
<%= text_field_tag :account_number, nil, { :name => nil, :'data-stripe' => "accountNumber", class: "form-control" } %>
</div>
<% end %>
<div class="form-group">
<%= f.submit class: "btn btn-primary btn-lg" %>
</div>
<% end %>
</div>
LISTING_CONTROLLER.RB
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, only: [:seller, :new, :create, :edit, :update, :destroy]
before_filter :check_user, only: [:edit, :update, :destroy]
def seller
#listings = Listing.where(user: current_user).order("created_at DESC")
end
# GET /listings
# GET /listings.json
def index
#listings = Listing.all.order("created_at DESC")
end
# GET /listings/1
# GET /listings/1.json
def show
end
# GET /listings/new
def new
#listing = Listing.new
end
# GET /listings/1/edit
def edit
end
# POST /listings
# POST /listings.json
def create
#listing = Listing.new(listing_params)
#listing.user_id = current_user.id
if current_user.recipient.blank?
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
recipient = Stripe::Recipient.create(
:name => current_user.name,
:type => "individual",
:bank_account => token
)
current_user.recipient = recipient.id
current_user.save
end
respond_to do |format|
if #listing.save
format.html { redirect_to #listing, notice: 'Listing was successfully created.' }
format.json { render :show, status: :created, location: #listing }
else
format.html { render :new }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /listings/1
# PATCH/PUT /listings/1.json
def update
respond_to do |format|
if #listing.update(listing_params)
format.html { redirect_to #listing, notice: 'Listing was successfully updated.' }
format.json { render :show, status: :ok, location: #listing }
else
format.html { render :edit }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /listings/1
# DELETE /listings/1.json
def destroy
#listing.destroy
respond_to do |format|
format.html { redirect_to listings_url, notice: 'Listing was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing
#listing = Listing.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_params
params.require(:listing).permit(:name, :description, :price, :duration, :street, :city, :state, :image, :duration, :category, :terms,
:country, :account_number, :routing_number, :stripeToken)
end
def check_user
if current_user != #listing.user
redirect_to root_url, alert: "Sorry, that is not your listing."
end
end
end
LISTING.JS.COFFEE
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
listing.setupForm()
listing =
setupForm: ->
$('#new_listing').submit ->
if $('input').length > 8
$('input[type=submit]').attr('disabled', true)
Stripe.bankAccount.createToken($('#new_listing'), listing.handleStripeResponse)
false
handleStripeResponse: (status, response) ->
if status == 200
$('#new_listing').append($('<input type="hidden" name="stripeToken" />').val(response.id))
$('#new_listing')[0].submit()
else
$('#stripe_error').text(response.error.message).show()
$('input[type=submit]').attr('disabled', false)
STRIPE DASHBOARD INFORMATION BEING RETURNED:
key: "pk_test_WgTil6dDhXN6JqzqZI4Gjw0M"
callback: "sjsonp1404518718631"
_method: "POST"
error:
type: "invalid_request_error"
message: "You must supply either a card, customer, or bank account to create a token."
The problem might be here:
current_user.recipient = recipient.id
current_user.save
You're saving an ID where an object is expected. Try:
current_user.recipient = recipient
current_user.save

Resources