Class: Spree::Variant
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Spree::Variant
- Defined in:
- app/models/spree/variant.rb,
app/models/spree/variant/scopes.rb
Class Method Summary collapse
- .active(currency = nil) ⇒ Object
-
.has_option(option_type, *option_values) ⇒ Object
(also: has_options)
Returns variants that match a given option value.
Instance Method Summary collapse
- #amount_in(currency) ⇒ Object
- #can_stock?(quantity = 1) ⇒ Boolean
- #cost_price=(price) ⇒ Object
- #default_price ⇒ Object
-
#deleted? ⇒ Boolean
use deleted? rather than checking the attribute directly.
- #gross_profit ⇒ Object
- #has_default_price? ⇒ Boolean
- #in_stock?(quantity = 1) ⇒ Boolean
- #name_and_sku ⇒ Object
-
#on_backorder ⇒ Object
returns number of units currently on backorder for this variant.
- #option_value(opt_name) ⇒ Object
- #options=(options = {}) ⇒ Object
- #options_text ⇒ Object
- #price_in(currency) ⇒ Object
-
#product ⇒ Object
Product may be created with deleted_at already set, which would make AR’s default finder return nil.
- #set_option_value(opt_name, opt_value) ⇒ Object
-
#should_track_inventory? ⇒ Boolean
Shortcut method to determine if inventory tracking is enabled for this variant This considers both variant tracking flag and site-wide inventory tracking settings.
- #sku_and_options_text ⇒ Object
- #total_on_hand ⇒ Object
Class Method Details
.active(currency = nil) ⇒ Object
45 46 47 |
# File 'app/models/spree/variant.rb', line 45 def self.active(currency = nil) joins(:prices).where(deleted_at: nil).where('spree_prices.currency' => currency || Spree::Config[:currency]).where('spree_prices.amount IS NOT NULL') end |
.has_option(option_type, *option_values) ⇒ Object Also known as: has_options
Returns variants that match a given option value
Example:
product.variants_including_master.has_option(OptionType.find_by(name: ‘shoe-size’), OptionValue.find_by(name: ‘8’))
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'app/models/spree/variant/scopes.rb', line 12 def has_option(option_type, *option_values) option_types = OptionType.table_name option_type_conditions = case option_type when OptionType then { "#{option_types}.name" => option_type.name } when String then { "#{option_types}.name" => option_type } else { "#{option_types}.id" => option_type } end relation = joins(:option_values => :option_type).where(option_type_conditions) option_values_conditions = option_values.each do |option_value| option_value_conditions = case option_value when OptionValue then { "#{OptionValue.table_name}.name" => option_value.name } when String then { "#{OptionValue.table_name}.name" => option_value } else { "#{OptionValue.table_name}.id" => option_value } end relation = relation.where(option_value_conditions) end relation end |
Instance Method Details
#amount_in(currency) ⇒ Object
140 141 142 |
# File 'app/models/spree/variant.rb', line 140 def amount_in(currency) price_in(currency).try(:amount) end |
#can_stock?(quantity = 1) ⇒ Boolean
157 158 159 |
# File 'app/models/spree/variant.rb', line 157 def can_stock?(quantity=1) Spree::Stock::Quantifier.new(self).can_supply?(quantity) end |
#cost_price=(price) ⇒ Object
49 50 51 |
# File 'app/models/spree/variant.rb', line 49 def cost_price=(price) self[:cost_price] = parse_price(price) if price.present? end |
#default_price ⇒ Object
88 89 90 |
# File 'app/models/spree/variant.rb', line 88 def default_price Spree::Price.unscoped { super } end |
#deleted? ⇒ Boolean
use deleted? rather than checking the attribute directly. this allows extensions to override deleted? if they want to provide their own definition.
77 78 79 |
# File 'app/models/spree/variant.rb', line 77 def deleted? deleted_at end |
#gross_profit ⇒ Object
70 71 72 |
# File 'app/models/spree/variant.rb', line 70 def gross_profit cost_price.nil? ? 0 : (price - cost_price) end |
#has_default_price? ⇒ Boolean
132 133 134 |
# File 'app/models/spree/variant.rb', line 132 def has_default_price? !self.default_price.nil? end |
#in_stock?(quantity = 1) ⇒ Boolean
152 153 154 155 |
# File 'app/models/spree/variant.rb', line 152 def in_stock?(quantity=1) puts %q{[DEPRECATION] In Spree 2.2, Variant#in_stock? will no longer take a quantity. Use Variant#can_supply? instead.} can_stock?(quantity) end |
#name_and_sku ⇒ Object
144 145 146 |
# File 'app/models/spree/variant.rb', line 144 def name_and_sku "#{name} - #{sku}" end |
#on_backorder ⇒ Object
returns number of units currently on backorder for this variant.
54 55 56 |
# File 'app/models/spree/variant.rb', line 54 def on_backorder inventory_units.with_state('backordered').size end |
#option_value(opt_name) ⇒ Object
128 129 130 |
# File 'app/models/spree/variant.rb', line 128 def option_value(opt_name) self.option_values.detect { |o| o.option_type.name == opt_name }.try(:presentation) end |
#options=(options = {}) ⇒ Object
92 93 94 95 96 |
# File 'app/models/spree/variant.rb', line 92 def ( = {}) .each do |option| set_option_value(option[:name], option[:value]) end end |
#options_text ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 |
# File 'app/models/spree/variant.rb', line 58 def values = self.option_values.sort do |a, b| a.option_type.position <=> b.option_type.position end values.map! do |ov| "#{ov.option_type.presentation}: #{ov.presentation}" end values.to_sentence({ words_connector: ", ", two_words_connector: ", " }) end |
#price_in(currency) ⇒ Object
136 137 138 |
# File 'app/models/spree/variant.rb', line 136 def price_in(currency) prices.select{ |price| price.currency == currency }.first || Spree::Price.new(variant_id: self.id, currency: currency) end |
#product ⇒ Object
Product may be created with deleted_at already set, which would make AR’s default finder return nil. This is a stopgap for that little problem.
84 85 86 |
# File 'app/models/spree/variant.rb', line 84 def product Spree::Product.unscoped { super } end |
#set_option_value(opt_name, opt_value) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'app/models/spree/variant.rb', line 98 def set_option_value(opt_name, opt_value) # no option values on master return if self.is_master option_type = Spree::OptionType.where(name: opt_name).first_or_initialize do |o| o.presentation = opt_name o.save! end current_value = self.option_values.detect { |o| o.option_type.name == opt_name } unless current_value.nil? return if current_value.name == opt_value self.option_values.delete(current_value) else # then we have to check to make sure that the product has the option type unless self.product.option_types.include? option_type self.product.option_types << option_type end end option_value = Spree::OptionValue.where(option_type_id: option_type.id, name: opt_value).first_or_initialize do |o| o.presentation = opt_value o.save! end self.option_values << option_value self.save end |
#should_track_inventory? ⇒ Boolean
Shortcut method to determine if inventory tracking is enabled for this variant This considers both variant tracking flag and site-wide inventory tracking settings
167 168 169 |
# File 'app/models/spree/variant.rb', line 167 def should_track_inventory? self.track_inventory? && Spree::Config.track_inventory_levels end |
#sku_and_options_text ⇒ Object
148 149 150 |
# File 'app/models/spree/variant.rb', line 148 def "#{sku} #{}".strip end |
#total_on_hand ⇒ Object
161 162 163 |
# File 'app/models/spree/variant.rb', line 161 def total_on_hand Spree::Stock::Quantifier.new(self).total_on_hand end |