undefined method `each' for nil:NilClass (ActiveMerchant) - ruby-on-rails-5

After filling payment information, when I click on 'place order' I get this error
NoMethodError in OrdersController#create
undefined method `each' for nil:NilClass
OrdersController
def create
#order = Order.new(order_params)
#order.add_line_items_from_cart(#cart)
credit_card = ActiveMerchant::Billing::CreditCard.new(params[:credit_card])
respond_to do |format|
if #order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
format.html { redirect_to category_url(Category.first), notice: 'Thank you for your order.' }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
order model:
attr_accessor :card_no, :card_cvv, :expiry_date
I'm guessing i need to group :card_no, :card_cvv and :expiry_date in a data structure labelled 'credit_card' but I don't know how. Thanks!
Edit:
NoMethodError (undefined method `each' for nil:NilClass):
app/controllers/orders_controller.rb:32:in `new'
app/controllers/orders_controller.rb:32:in `create'
Rendering C:/RailsInstaller/Ruby2.2.0/lib/ruby/........

You need to get the params according to what you're sending from your form, so, if you want to access to them, you must take the params from the order root, that's to say, the card_no will be params[:order][:card_no], and this way all of them.
And in order to make use of the ActiveMerchant gem and to create a new "CreditCard", you need to pass there your values received from the form, something like:
credit_card = ActiveMerchant::Billing::CreditCard.new(
:first_name => params[:order][:first_name],
:last_name => params[:order][:last_name],
:number => params[:order][:card_cvv],
:month => params[:order][:month],
:year => Time.now.year+1, # documentation value
:verification_value => '000' # documentation value
)

Related

Rails: nested resources and routing errors

I've got a Template model, and a Doc model. They're nested resources, with the Templates being the parent, thus:
resources :templates do
get "/documents/lock/:id" => "docs#lock", :as => :lock_doc
get "/documents/unlock/:id" => "docs#unlock", :as => :unlock_doc
get "/documents/pdf/:id" => "docs#pdf", :as => :pdf_doc
resources :docs, :path => :documents
end
That part, I think, all works fine. When I try to submit the form for creating a doc the record exists but I get routing errors, thus:
ActionController::RoutingError (No route matches {:action=>"edit", :controller=>"docs", :template_id=>nil, :id=>#<Doc id: 2, user_id: "admin", cover: "1209hpnl", message: "The world economic outlook is improving, albeit slo...", created_at: "2013-01-07 03:54:05", updated_at: "2013-01-07 03:54:05", issue_code: "1209hpnl", title: "January 2013", locked: nil, retired: "active", template: nil>}):
app/controllers/docs_controller.rb:134:in `block (2 levels) in create'
app/controllers/docs_controller.rb:132:in `create'
The lines correspond to the create method:
def create
#doc = Doc.new(params[:doc])
respond_to do |format|
if #doc.save
format.html { redirect_to share_url(#doc), notice: "Saved. You may from here #{view_context.link_to('edit', edit_template_doc_url(#doc))} it further, #{view_context.link_to('finalise', template_lock_doc_url(#doc))} it, or return #{view_context.link_to('home', root_url)}.".html_safe }
format.json { render json: #doc, status: :created, location: #doc }
else
format.html { render action: "new" }
format.json { render json: #doc.errors, status: :unprocessable_entity }
end
end
end
I think the problem lies somewhere in here, but I can't for the life of me figure it out.
Cheers for any help!
EDIT: with rake routes
template_lock_doc GET /templates/:template_id/documents/lock/:id(.:format) docs#lock
template_unlock_doc GET /templates/:template_id/documents/unlock/:id(.:format) docs#unlock
template_pdf_doc GET /templates/:template_id/documents/pdf/:id(.:format) docs#pdf
template_docs GET /templates/:template_id/documents(.:format) docs#index
POST /templates/:template_id/documents(.:format) docs#create
new_template_doc GET /templates/:template_id/documents/new(.:format) docs#new
edit_template_doc GET /templates/:template_id/documents/:id/edit(.:format) docs#edit
template_doc GET /templates/:template_id/documents/:id(.:format) docs#show
PUT /templates/:template_id/documents/:id(.:format) docs#update
DELETE /templates/:template_id/documents/:id(.:format) docs#destroy
templates GET /templates(.:format) templates#index
POST /templates(.:format) templates#create
new_template GET /templates/new(.:format) templates#new
edit_template GET /templates/:id/edit(.:format) templates#edit
template GET /templates/:id(.:format) templates#show
PUT /templates/:id(.:format) templates#update
DELETE /templates/:id(.:format) templates#destroy
The problem is in your call to edit_template_doc_url(#doc) inside the notice string. You need to supply the template as well, like this:
edit_template_doc_url(params[:template_id], #doc)

how to pass id of the controller

How to pass id. my controller is:
class AttachementsController < ApplicationController
def index
#pdf = Attachement.find(params[:resume_id])
# send_file(#pdf.file.url, :type => 'application/pdf', :disposition => 'inline',:stream => false)
redirect_to #pdf.file.url
end
end
and my test case of the controller is:
require 'spec_helper'
describe AttachementsController do
describe "GET 'index'" do
it "should be successful" do
get 'index', :id => "#attachements.id"
response.should be_success
end
end
end
and my error is:
AttachementsController GET 'index' should be successful
Failure/Error: get 'index', :id => "#attachements.id"
ActiveRecord::RecordNotFound:
Couldn't find Attachement without an ID
# ./app/controllers/attachements_controller.rb:3:in `index'
# ./spec/controllers/attachements_controller_spec.rb:7:in `block (3 levels) in <top (required)>'
You don't need the quotes around #attachements.id.
get 'index', :id => #attachements.id

How do I pass a params parameter into an rspec controller test?

I have the following rspec test:
def valid_attributes
{ "product_id" => "1" }
end
describe "POST create" do
describe "with valid params" do
it "creates a new LineItem" do
expect {
post :create, {:line_item => valid_attributes}, valid_session #my valid_session is blank
}.to change(LineItem, :count).by(1)
end
Which fails with this error:
1) LineItemsController POST create with valid params redirects to the created line_item
Failure/Error: post :create, {:line_item => valid_attributes}, valid_session
ActiveRecord::RecordNotFound:
Couldn't find Product without an ID
# ./app/controllers/line_items_controller.rb:44:in `create'
# ./spec/controllers/line_items_controller_spec.rb:87:in `block (4 levels) in <top (required)>'
This is my controller's create action:
def create
#cart = current_cart
product = Product.find(params[:product_id])
#line_item = #cart.line_items.build(:product => product)
respond_to do |format|
if #line_item.save
format.html { redirect_to #line_item.cart, notice: 'Line item was successfully created.' }
format.json { render json: #line_item.cart, status: :created, location: #line_item }
else
format.html { render action: "new" }
format.json { render json: #line_item.errors, status: :unprocessable_entity }
end
end
end
As you can see, my action expects a product_id from the request's params object. How should I work this product_id into my rspec test?
I've tried placing this before statement:
before(:each) do
ApplicationController.any_instance.stub(:product).and_return(#product = mock('product'))
end
. . . but it changes nothing. I am missing some rspec concept here somewhere.
Try like this:
describe "POST create" do
describe "with valid params" do
it "creates a new LineItem" do
expect {
post :create, :product_id => 1
}.to change(LineItem, :count).by(1)
end
Hope it helps.
I ended up resolving my issue by using a fixture instead of attempting to mock the solution as suggested in another answer.
The reason for this is that the controller does the query to get information from the database: product = Product.find(params[:product_id]) and I found a fixture-based solution was quicker to resolve my problem than one using a mock and I could not figure out how to stub the query quickly (the fixtures also help with another test on the controller so it eventually helped anyway.
For reference:
I referenced my fixture with this line toward the top of the test: fixtures :products
I changed my test to:
describe "POST create" do
describe "with valid params" do
it "creates a new LineItem" do
expect {
post :create, :product_id => products(:one).id
}.to change(LineItem, :count).by(1)
end
And here is my fixture file, products.yml:
one:
name: FirstProduct
price: 1.23
two:
name: SecondProduct
price: 4.56

Rails 3.2.2 - Possible to add custom node to as_json

As it's not currently possible for me to use a json templating engine (jbuilder or rabl) as per Rails3 ActionView Template Handlers doesn't work on Production Server I'm wondering how to best change this controller action to include a custom node with as_json (or something else)
class Mobile::AndroidUsersController < SecureMobileUserController
skip_before_filter :authorize, :only => :create
respond_to :json
# POST /mobile_users
# POST /mobile_users.xml
def create
#mobile_user = AndroidUser.find_by_auth(params[:mobile_user][:auth])
unless #mobile_user
#mobile_user = AndroidUser.new(params[:mobile_user])
else
#mobile_user.attributes = params[:mobile_user]
end
respond_to do |format|
if #mobile_user.save
format.json #Add a custom token node here
else
:unprocessable_entity }
format.json { render json: #mobile_user.errors, status: :unprocessable_entity }
:unprocessable_entity }
end
end
end
end
I just need to add a custom node called token that has a value that I get from calling a method on the MobileUser class
:token => MobileUser.next_token
You can change the call to as_json like this:
format.json {render :json => #mobile_user.as_json(:methods => [:next_token])}

Rails3 and Rspec2 controller testing with a namespace

I'm trying to test a controller with a name space, following is my controller (/admin/sites_controller.rb):
class Admin::SitesController < AdminController
def create
#site = Site.new(params[:site])
respond_to do |format|
if #site.save
format.html { redirect_to(#site, :notice => 'Site was successfully created.') }
format.xml { render :xml => #site, :status => :created, :location => #site }
else
format.html { render :action => "new" }
format.xml { render :xml => #site.errors, :status => :unprocessable_entity }
end
end
end
end
and following is my routes.rb file
namespace :admin do
resources :sites
end
I'm using rspec2 to test my controller and following is my controller spec
describe Admin::SitesController do
describe "POST create" do
describe "with valid params" do
it "creates a new Site" do
expect {
post :create, :site => valid_attributes
}.to change(Site, :count).by(1)
end
end
end
end
But when I run the spec it gives me the following routing error
Admin::SitesController POST create with valid params creates a new Site
Failure/Error: post :create, :site => valid_attributes
NoMethodError:
undefined method `site_url' for #<Admin::SitesController:0xb5fbe6d0>
# ./app/controllers/admin/sites_controller.rb:47:in `create'
# ./app/controllers/admin/sites_controller.rb:45:in `create'
# ./spec/controllers/admin/sites_controller_spec.rb:78
# ./spec/controllers/admin/sites_controller_spec.rb:77
I guess its because of the 'admin' name space I'm using, but how can I fix that?
I'm using
Rails3
Rspec2
Linux
When you namespace the route, you're creating URL and path helpers that look like this:
HTTP Verb Path action helper
GET /admin/sites index admin_sites_path
GET /admin/sites/new new new_admin_site_path
POST /admin/sites create admin_sites_path
GET /admin/sites/:id show admin_site_path(:id)
GET /admin/sites/:id/edit edit edit_admin_site_path(:id)
PUT /admin/sites/:id update admin_site_path(:id)
DELETE /admin/sites/:id destroy admin_site_path(:id)
So you can either use those directly in your code (i.e. redirect_to admin_site_path(#site) ), or you can do something like:
redirect_to([:admin, #site])