Module: ActiveCart::Acts::Item::ClassMethods

Defined in:
lib/active_cart/acts_as_cart.rb

Instance Method Summary collapse

Instance Method Details

#acts_as_cart_item(options = {}) ⇒ Object

acts_as_cart_item - Sets up an ActiveModel as an cart item.

Cart Items are slightly different to regular items (that may be created in a backend somewhere). When building shopping carts, one of the problems when building shopping carts is how to store the items associated with a particular invoice. One method is to serialize Items and storing them as a blob. This causes problem if the object signature changes, as you won't be able to deserialize an object at a later date. The other option is to duplicate the item into another model which is the option acts_as_cart takes (ActiveCart itself can do either, by using a storage engine that supports the serialization option). As such, carts based on act_as_cart will need two tables, most likely named items and cart_items. In theory, cart_items only needs the fields required to fulfill the requirements of rendering an invoice (or general display), but it's probably easier to just duplicate the fields. The cart_items will also require a cart_id and a quantity field acts_as_cart uses the 'original' polymorphic attribute to store a reference to the original Item object. The compound attribute gets nullified if the original Item gets deleted.

When adding an item to a cart, you should pass in the actual concrete item, not the cart_item - the model will take care of the conversion.

For complex carts with multiple item types, you will probably need to use STI, as it's basically impossible to use a polymorphic relationship (If someone can suggest a better way, I'm all ears). That said, there is no easy way to model complex carts, so I'll leave this as an exercise for the reader.

Options:

cart: The cart model. Association as a belongs_to. Default: cart
quantity_column: The column that stores the quantity of this item stored in the cart. Default: quantity
name_column: The column that stores the name of the item. Default: name
price_column: The column that stores the price of the item. Default: price
foreign_key: The column that stores the reference to the cart. Default: [cart]_id (Where cart is the value of the cart option)

Example

class Item < ActiveModel::Base
  acts_as_item
end


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/active_cart/acts_as_cart.rb', line 163

def acts_as_cart_item(options = {})
  cattr_accessor :aaci_config
  
  self.aaci_config = {
    :cart => :cart,
    :quantity_column => :quantity,
    :name_column => :name,
    :price_column => :price
  }
  self.aaci_config.merge!(options)
  self.aaci_config[:foreign_key] = (self.aaci_config[:cart].to_s + "_id").to_sym unless options[:foreign_key]

  class_eval do
    include ActiveCart::Item
  
    def id
      read_attribute(:id)
    end

    def name
      read_attribute(self.aaci_config[:name_column])
    end

    def quantity
      read_attribute(self.aaci_config[:quantity_column])
    end 

    def quantity=(quantity)
      write_attribute(self.aaci_config[:quantity_column], quantity)
    end

    def price
      read_attribute(self.aaci_config[:price_column])
    end
  end
  
  # Creates a new cart_item item for the passed in concrete item
  #
  # The default copies all the common attributes from the passed in item to new cart_item (Except id and timestamps). Override it if you want to do something special.
  #
  def new_from_item(item, options = {})
    cart_item = item.send(self.to_s.tableize).build(options)
    cart_item.attributes.map {|attribute| attribute if item.respond_to?(attribute[0].to_s) && !attribute[0].to_s.include?("_at") }.compact.each {|attribute| cart_item.send("#{attribute[0]}=", item.send(attribute[0].to_s))}
    # TODO Add a callback
    cart_item
    # TODO Add a callback
  end

  belongs_to self.aaci_config[:cart], :foreign_key => self.aaci_config[:foreign_key]
  belongs_to :original, :polymorphic => true
end

#new_from_item(item, options = {}) ⇒ Object

Creates a new cart_item item for the passed in concrete item

The default copies all the common attributes from the passed in item to new cart_item (Except id and timestamps). Override it if you want to do something special.



203
204
205
206
207
208
209
# File 'lib/active_cart/acts_as_cart.rb', line 203

def new_from_item(item, options = {})
  cart_item = item.send(self.to_s.tableize).build(options)
  cart_item.attributes.map {|attribute| attribute if item.respond_to?(attribute[0].to_s) && !attribute[0].to_s.include?("_at") }.compact.each {|attribute| cart_item.send("#{attribute[0]}=", item.send(attribute[0].to_s))}
  # TODO Add a callback
  cart_item
  # TODO Add a callback
end