Reputation: 768
I migrated my Rails application from 3.2.13 to 4.0.0, but while running the application, I am getting the error:
Started GET "/signup.html" for 127.0.0.1 at 2016-06-29 17:28:16 +0530 ActiveRecord::SchemaMigration Load (0.2ms) SELECT "schema_migrations".* FROM "schema_migrations" Processing by AccountsController#new as HTML Parameters: {"plan"=>"year"} Completed 500 Internal Server Error in 51ms ** [Airbrake] Notice was not sent due to configuration: Environment Monitored? false API key set? true
NoMethodError - undefined method
each' for nil:NilClass:
initialize' app/controllers/accounts_controller.rb:83:in
activemerchant (1.47.0) lib/active_merchant/billing/model.rb:11:inload_billing' activesupport (4.0.0) lib/active_support/callbacks.rb:437:in
_run__3203841093432473566__process_action__callbacks' activesupport (4.0.0) lib/active_support/callbacks.rb:80:inrun_callbacks'
process_action' actionpack (4.0.0) lib/action_controller/metal/rescue.rb:29:in `process_action'
actionpack (4.0.0) lib/abstract_controller/callbacks.rb:17:in
.......................................
This is my controller code :
class AccountsController < ApplicationController
#inherit_resources
ssl_required :new, :create
before_filter :load_billing, :only => [:new, :create]
def new
@account_name = Rails.application.config.custom.accounts.send(params[:account_name]).name
@account_signup_message = Rails.application.config.custom.accounts.send(params[:account_name]).signup_message
rescue
nil
end
def create
@address.first_name = @creditcard.first_name
@address.last_name = @creditcard.last_name
@account.address = @address
@account.creditcard = @creditcard
if @account.new_record?
if @account.save
flash[:notice] = 'Account was created.'
sign_in(@user, :bypass => true)
redirect_to session[:previous_url] || user_reports_path(@user)
else
render :action => 'new'
end
else
@user.account_id = @account.id
if @user.save
flash[:notice] = 'User was created.'
sign_in(@user, :bypass => true)
redirect_to session[:previous_url] || user_reports_path(@user)
else
render :action => 'new'
end
end
end
protected
def load_billing
@creditcard = ActiveMerchant::Billing::CreditCard.new(params[:account].blank? ? nil : params[:account][:creditcard]) #This is the line it is showing error.
@address = SubscriptionAddress.new(params[:account].blank? ? nil : params[:account][:address])
end
end
routes.rb:
get '/signup' => 'accounts#new'
accounts/new.html.erb:
<%= semantic_form_for(@account, :url => account_create_path, :html => { :multipart => true, :class => 'billing'}) do |f| %>
<%= f.inputs :for => :user do |u| %>
#name and email fields are mentioned.
<% end %>
<%= f.inputs :for => :creditcard do |c| %>
#name, card_no, cvv, expire_date etc;
<% end %>
<% end %>
This is my activemerchant (1.47.0) lib/active_merchant/billing/model.rb:
require "active_merchant/billing/compatibility"
require "active_merchant/empty"
module ActiveMerchant
module Billing
class Model
include Compatibility::Model
include Empty
def initialize(attributes = {})
attributes.each do |key, value|
send("#{key}=", value)
end
end
def validate
{}
end
private
def errors_hash(array)
array.inject({}) do |hash, (attribute, error)|
(hash[attribute] ||= []) << error
hash
end
end
end
end
end
include Empty is the error showing line in the above code. And there is no model.rb file for activemerchant version 1.20.4 (my previous). Please help me.
Upvotes: 1
Views: 227
Reputation: 3275
"include Empty is the error showing line in the above code. " No it is raising an exception on line 11 which is " attributes.each do |key, value|
" because attributes is nil.
So change this line:
@creditcard = ActiveMerchant::Billing::CreditCard.new(params[:account].blank? ? nil : params[:account][:creditcard])
to this:
@creditcard = ActiveMerchant::Billing::CreditCard.new(params[:account].blank? ? {} : params[:account][:creditcard])
now you will be sending through something that won't raise if you call .each on it.
foo = {}
=> {}
2.3.0 :002 > foo.each {|key, value| puts "#{key}=#{value}" }
=> {}
But just so that you understand:
In the initialize method this line
def initialize(attributes = {})
initializes an instance of the class with a default parameter of an empty hash if no other parameter is being passed in. In your ternary on this line:
@creditcard = ActiveMerchant::Billing::CreditCard.new(params[:account].blank? ? nil : params[:account][:creditcard])
this:
params[:account].blank? ? nil : params[:account][:creditcard]
says that if there are no account params, send nil as a parameter to initialize. The nil value overwrites the default({}) value and you get undefined method each on nil class because you are calling:
attributes.each do |key, value|
but you have defined attributes as nil.
Upvotes: 2
Reputation: 6574
ActiveMerchant.new requires an hash of attributes and their values(default is empty hash), but you are passing nil which is causing the error. Check this implementation for better understanding. I think that you need not pass anything(not even nil) if params[:account][:creditcard] is not present.
Upvotes: 1
Reputation: 109
You forgot to close square brackets on before_action call.
Upvotes: 0