I'm using ActiveMerchant with Authorize.net and already setup 2 models Order and Transaction. (http://railscasts.com/episodes/145-integrating-active-merchant)
I would like to get error message from the transaction if error occurred then output in flash message. Here is my code:
#order_controller.rb
def create
#order = Order.new(params[:order])
respond_to do |format|
if #order.save
if #order.purchase
format.html { redirect_to(#order, :notice => 'Order was successfully created.') }
format.xml { render :xml => #order, :status => :created, :location => #order }
else
flash[:error] = #order.transactions.response
format.html { render :action => "new" }
end
else
format.html { render :action => "new" }
format.xml { render :xml => #order.errors, :status => :unprocessable_entity }
end
end
end
And here is my transaction model:
#models/order_transaction.rb
class OrderTransaction < ActiveRecord::Base
belongs_to :order
serialize :params
def response=(response)
self.success = response.success?
self.authorization = response.authorization
self.message = response.message
self.params = response.params
rescue ActiveMerchant::ActiveMerchantError => e
self.success = false
self.authorization = nil
self.message = e.message
self.params = {}
end
end
The transaction data has been saved to the database as below:
#models/order.rb
class Order < ActiveRecord::Base
has_many :transactions, :class_name => "OrderTransaction"
attr_accessor :card_type, :card_number, :card_month, :card_year, :card_verification
def purchase
response = GATEWAY.purchase(charge_amount, credit_card, purchase_options)
transactions.create!(:action => "purchase", :amount => charge_amount, :response => response)
response.success?
end
...
end
I want to flash up this transaction error message when transaction failed. And what would I should do to get these errors if I have 2 transactions for one order.?
Any help would be much appreciated.
Thanks!
Related
I'm sending the following JSON to Rails 4.1.0
Started POST "/orders.json" for 127.0.0.1 at 2015-08-11 15:19:34 +0200
Processing by OrdersController#create as JSON
Parameters: {"order"=>{"name"=>"Jon", "surname"=>"Do", "line_items_attributes"=>[{"work_id"=>16, "quantity"=>1, "total_price"=>34.5}, {"work_id"=>12, "quantity"=>2, "total_price"=>40}]}}
Unpermitted parameters: line_items_attributes
but I'm getting Unpermitted parameters error. My Order model:
class Order < ActiveRecord::Base
belongs_to :user
belongs_to :dispatch_method
belongs_to :payment_method
has_many :line_items, :dependent => :destroy
accepts_nested_attributes_for :line_items
end
My orders_controller.rb
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
def index
#orders = Order.all
end
def show
end
def new
#order = Order.new
end
def edit
end
def create
#order = Order.create(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render action: 'show', status: :created, location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.json { head :no_content }
end
end
private
def set_order
#order = Order.find(params[:id])
end
def order_params
params.require(:order).permit(:name, :surname, line_items_attributes: [:id, :work_id, :quantity, :total_price])
end
end
I'm able to create and save a new instance of order, but not of a line_item.
You can try to redefine your order_params like this:
def order_params
json_params = ActionController::Parameters.new(JSON.parse(params[:order]))
return json_params.require(:name, :surname).permit(line_items_attributes: [:id, :work_id, :quantity, :total_price])
end
As you see, I am parsing params[:order] to avoid parsing the full params var. You might need to add another json level here but I hope you get the idea.
something like this
render :json => #booking, :include => [:paypal,
:boat_people,
:boat => {:only => :name, :include => {:port => {:only => :name, :include => {:city => {:only => :name, :include => {:country => {:only => :name}}}}},
:boat_model => {:only => :name, :include => {:boat_type => {:only => :name}}}}}]
In the seemingly never-ending quest to understand Braintree's obfuscated documentation, I ended up creating my own update UI with a list of BTPaymentMethod
The Braintree docs say to update a payment method with a token (which I see in my online sandbox vault). How do I retrieve an indivdual customers card token to update?
I'm using -[BTClient fetchPaymentMethodsWithSuccess:failure:], which returns BTPaymentMethodwhich only has thepayment_nonce property. Trying to update with this property return an error CVV is required.
def update_payment_default
#customer = Customer.where(id: params[:id]).first
if #customer.present?
#string = "customer_" + #customer.id.to_s
result = Braintree::Customer.update(
"my_customer_id"
:credit_card => {
:payment_method_nonce => params[:payment_method_nonce],
:options => {
:make_default => true
}
}
)
if result.success?
respond_to do |format|
msg = {:status => "SUCCESS", :message => "Updated payment payment method"}
format.json { render :json => msg } # don't do msg.to_json
end
else
respond_to do |format|
msg = {:status => "FAILED", :message => result.errors}
format.json { render :json => msg } # don't do msg.to_json
end
end
end
I have a simple has_one relationship setup but I want to add records to Damages table only when the text_field is not blank or nil. Right now it's adding records that are blank or nil to the other table.
My view:
<%= f.fields_for :damage do |builder| %>
<%= builder.label 'Damage' %><br />
<%= builder.text_field :dam_detail %>
<% end %>
Packjob Model:
class Packjob < ActiveRecord::Base
attr_accessible :pj_damage
has_one :damage
accepts_nested_attributes_for :damage
end
Damage Model:
class Damage < ActiveRecord::Base
attr_accessible :dam_detail
belongs_to :packjob
end
How do I allow only non blank or nil values being added?
Is best practice to add logic for this to the helper?
EDIT:
Here's the controller for Packjobs:
class PackjobsController < ApplicationController
# GET /packjobs
# GET /packjobs.json
def index
#packjobs = Packjob.includes(:damage).all
#packers = Packer.find(:all)
#rigs = Rig.find(:all, :order => "rig_type_number")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #packjobs }
end
end
# GET /packjobs/1
# GET /packjobs/1.json
def show
#packjob = Packjob.find(params[:id])
#packers = Packer.find(:all)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #packjob }
end
end
# GET /packjobs/new
# GET /packjobs/new.json
def new
#packjob = Packjob.new
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
#damage = #packjob.build_damage
##book = #author.build_book
respond_to do |format|
format.html # new.html.erb
format.json { render json: #packjob }
end
end
# GET /packjobs/1/edit
def edit
#packjob = Packjob.find(params[:id])
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
end
# POST /packjobs
# POST /packjobs.json
def create
#packjob = Packjob.new(params[:packjob])
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
respond_to do |format|
if #packjob.save
format.html { redirect_to #packjob, notice: 'Packjob was successfully created.' }
format.json { render json: #packjob, status: :created, location: #packjob }
else
format.html { render action: "new" }
format.json { render json: #packjob.errors, status: :unprocessable_entity }
end
end
end
# PUT /packjobs/1
# PUT /packjobs/1.json
def update
#packjob = Packjob.find(params[:id])
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
respond_to do |format|
if #packjob.update_attributes(params[:packjob])
format.html { redirect_to #packjob, notice: 'Packjob was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #packjob.errors, status: :unprocessable_entity }
end
end
end
# DELETE /packjobs/1
# DELETE /packjobs/1.json
def destroy
#packjob = Packjob.find(params[:id])
#packjob.destroy
respond_to do |format|
format.html { redirect_to packjobs_url }
format.json { head :no_content }
end
end
end
Also the I want the packjob to allow for blanks in damage text_field, I just don't want the records added to the Damages table..
This is a job for validations. Specifically, you want two things:
You want your Damage class to validate that :dam_detail is not blank or nil:
class Damage < ActiveRecord::Base
# ... rest of class here ...
validates :dam_detail, :presence => true, :length => { :minimum => 1 }
end
You want your Packjob class to validate that its contained Damage object is valid:
class Packjob < ActiveRecord::Base
# ... rest of class here ...
validates_associated :damage
end
I also recommend modifying your database schema to add the restriction that the dam_detail field cannot be null. See the migrations guide for more info.
Even though its more commonly used for has_many the cocoon gem https://github.com/nathanvda/cocoon is great for this. That gem will allow you to build the relation on the fly from the front end. it will also allow you to destroy the relation too.
I have set up members and teams models using has_many through association.
member.rb
has_many :teams, :through => :team_members
has_many :team_members
team.rb
has_many :members, :through => :team_members
has_many :team_members
team_member.rb
belongs_to :member
belongs_to :team
When I try to create a new team, I get this error:
undefined method `name' for nil:NilClass
params are:
{"utf8"=>"✓",
"authenticity_token"=>"aXpMxWxGlhogfn9EbBWciSjoMrYXbPxG8Kzha14na58=",
"team"=>{"name"=>"Ruby",
"email"=>"email#email.com",
"language"=>"En",
"link"=>"",
"logo"=>#<ActionDispatch::Http::UploadedFile:0xb3907f0 #original_filename="You-Are-Great-.gif",
#content_type="image/gif",
#headers="Content-Disposition: form-data; name=\"team[logo]\"; filename=\"You-Are-Great-.gif\"\r\nContent-Type: image/gif\r\n",
#tempfile=#<File:/tmp/RackMultipart20120723-1907-m3bi79>>},
"commit"=>"Create Team"}
The create method in teams_controller.rb is:
#team = Team.new(params[:team])
The team doesn't get created unless I assign the attributes manually one by one like
#team = Team.new(:name => params[:team][:name], :email => params[:team][:email]...)
and so! any ideas why?
EDIT:
teams_controller.rb:
class TeamsController < ApplicationController
# GET /teams
# GET /teams.json
def index
#teams = Team.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #teams }
end
end
# GET /teams/1
# GET /teams/1.json
def show
#team = Team.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #team }
end
end
# GET /teams/new
# GET /teams/new.json
def new
#team = Team.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #team }
end
end
# GET /teams/1/edit
def edit
#team = Team.find(params[:id])
end
# POST /teams
# POST /teams.json
def create
raise params.to_yaml
#team = Team.new(params[:team])
respond_to do |format|
if #team.save
#team_member = TeamMember.new(:team_id => #team.id, :member_id => current_member.id,
:accepted => true, :leader => true, :joined => Time.now)
if #team_member.save
format.html { redirect_to team_path(#team), notice: 'Team was successfully created.' }
format.json { render json: #team, status: :created, location: #team }
else
#team.destroy
format.html { render action: "new" }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
else
format.html { render action: "new" }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
end
end
# PUT /teams/1
# PUT /teams/1.json
def update
#team = Team.find(params[:id])
respond_to do |format|
if #team.update_attributes(params[:team])
format.html { redirect_to #team, notice: 'Team was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #team.errors, status: :unprocessable_entity }
end
end
end
# DELETE /teams/1
# DELETE /teams/1.json
def destroy
#team = Team.find(params[:id])
#team.destroy
respond_to do |format|
format.html { redirect_to teams_url }
format.json { head :no_content }
end
end
end
team.rb model:
class Team < ActiveRecord::Base
attr_accessible :name, :email, :language, :link, :logo, :team_leader
validates_presence_of :name
validates_presence_of :email
validates_presence_of :language
validates_uniqueness_of :name
has_many :leaders, :class_name => "TeamMember", :conditions => { :leader => true }
has_many :members, :through => :team_members
has_many :team_members, :conditions => { :accepted => true, :active => true }
has_attached_file :logo,
:styles => { :medium => "320x180>", :thumb => "100x100>" },
:url => "/assets/teams/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/teams/:id/:style/:basename.:extension"
end
I have been using attachment_fu on a project for a long time and all was fine but now as I am trying to bring the project up to rails 2.3.3 I am running into a strange bug that is driving me nuts. The Attachment, a logo in this case, validates correctly on create but does not fail validation on update. I have debugged it and it fails the intial validate but does not seem to throw an exception or at least not one that is caught by my rescue in the controller. Seems like I have tried everything but can't figure this one out.
Controller:
# POST /tournaments
# POST /tournaments.xml
def create
# Build tournament
#tournament = Tournament.new(params[:tournament].merge(:user_id => current_user.id) )
# Save the uploaded attachments
params[:uploads].each do |upload|
#tournament.documents << Document.new({:uploaded_data => upload[:document]}.merge(:description => upload[:description]))
end unless params[:uploads].nil?
# if supplied save an event logo
#logo = Logo.new({:uploaded_data => params[:logo][:upload_data]}) unless params[:logo].nil? or params[:logo][:upload_data].blank?
#tournament.logo = #logo unless #logo.nil?
respond_to do |format|
begin
Tournament.transaction do
#tournament.logo.save! unless #tournament.logo.nil?
#tournament.save!
end
flash[:notice] = 'Tournament was successfully created.'
format.html { redirect_to tournament_url(#tournament) }
format.xml { head :created, :location => tournament_url(#tournament) }
rescue
flash[:notice] = 'Errors prevented your Tournament from being saved'
format.html { render :action => "new" }
format.xml { render :xml => #tournament.errors, :status => :unprocessable_entity }
end
end
end
# PUT /tournaments/1
# PUT /tournaments/1.xml
def update
#tournament = Tournament.find(params[:id])
#tournament.user_id = session[:orig_user_id]
respond_to do |format|
begin
Tournament.transaction do
# Update Logo if necessary
unless params[:logo][:upload_data].blank?
#tournament.logo.destroy unless #tournament.logo.nil?
#tournament.logo = Logo.new({:uploaded_data => params[:logo][:upload_data]}.merge(:user_id => current_user.id))
end
# Save any uploaded documents
params[:uploads].each do |upload|
#tournament.documents << Document.new({:uploaded_data => upload[:document]}.merge(:description => upload[:description]))
end unless params[:uploads].nil?
# Update Tournamnet Attributes
#tournament.attributes = params[:tournament]
# Save the Tournament
#tournament.save!
end
flash[:notice] = 'Tournament was successfully updated.'
format.html { redirect_to tournament_url(#tournament) }
format.xml { head :ok, :location => tournament_url(#tournament) }
rescue
flash[:notice] = 'Errors prevented your Tournament from being updated'
format.html { render :action => "edit" }
format.xml { render :xml => #tournament.errors, :status => :unprocessable_entity }
end
end
end
Logo Model:
class Logo < Asset
validate_on_create :attachment_valid?
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 4.megabytes,
:resize_to => '810x150>',
:processor => :ImageScience,
:thumbnails => { :thumb => '270x50>' }
def attachment_valid?
content_type = attachment_options[:content_type]
unless content_type.nil? || content_type.include?(self.content_type)
errors.add(:upload_data, " * must be an image file (jpg, gif, or png)")
end
size = attachment_options[:size]
unless size.nil? || size.include?(self.size)
errors.add(:upload_data, "* image must be 4MB or less")
end
end
before_thumbnail_saved do |thumbnail|
record = thumbnail.parent
thumbnail.user_id = record.user_id
thumbnail.listing_id = record.listing_id
end
end
I am running the following
Rails 2.3.3
image_science 1.2.0
Thanks
--Tim
You could also use a :before_save callback to test the object. If it is invalid, raise an exception.
try adding:
validate_on_update :attachment_valid?