简体   繁体   中英

Connecting a shopping cart “total price” attribute to a payments configuration

I am starting to put together an application that includes, products, a shopping cart and payments. You start by adding the product to your cart by going to /products. Then if you navigate to /cart the system will populate your list of products ready to checkout. The plan is to link the "total price" attribute within the carts table into the payments table.

How do I go about linking two attributes from separate tables to make them the same? I have marked the two attributes that need to be the same, "total price" and "amount."

create_payments.rb

class CreatePayments < ActiveRecord::Migration
def change
  create_table :payments do |t|
    t.string :first_name
    t.string :last_name
    t.string :last4
    ***t.decimal :amount, precision: 12, scale: 3***
    t.boolean :success
    t.string :authorization_code

    t.timestamps null: false
    end
  end
end

create_order_items.rb

class CreateOrderItems < ActiveRecord::Migration
def change
  create_table :order_items do |t|
    t.references :product, index: true, foreign_key: true
    t.references :order, index: true, foreign_key: true
    t.decimal :unit_price, precision: 12, scale: 3
    t.integer :quantity
    ***t.decimal :total_price, precision: 12, scale: 3***

    t.timestamps null: false
    end
  end
end

Please let me know if any further files will be needed to help troubleshoot the problem. Thank you in advance for any type of assistance!

I think what you're looking for here is to write a custom "getter" method, ie a virtual attribute. You could also overwrite save or use an (activerecord callback)[ http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html]

For example:

class Payment < ActiveRecord::Base
  has_many :order_items

  # --------
  # option 1
  # --------

  def amount
    # sums up the total price of the associated order items
    self.order_items.pluck(:price).sum
  end

  # --------
  # option 2
  # --------

  def save(*args)
    self.amount = self.order_items.pluck(:price).sum
    super(*args)
  end

  # ----------
  # option 3
  # ----------

  before_save :set_amount
  def set_amount
    self.amount = self.order_items.pluck(:price).sum
  end

end

with the first option ("custom getter"), the aggregate column is not stored in the database and is dynamically recalculated each time it's value is accessed.

With the second option ("overriding save"), the amount column will be automatically set whenever save is called on a record.

The third option is probably the best in my opinion. It basically does the same thing as option 2, but looks a little cleaner.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM