Class: Spree::Product
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Spree::Product
- Defined in:
- app/models/spree/product.rb,
app/models/spree/product/scopes.rb
Instance Attribute Summary collapse
-
#option_values_hash ⇒ Object
Returns the value of attribute option_values_hash.
-
#prototype_id ⇒ Object
Adding properties and option types on creation based on a chosen prototype.
Class Method Summary collapse
- .active(currency = nil) ⇒ Object
- .add_search_scope(name, &block) ⇒ Object
- .add_simple_scopes(scopes) ⇒ Object
-
.available(available_on = nil, currency = nil) ⇒ Object
Can’t use add_search_scope for this as it needs a default argument.
-
.group_by_products_id ⇒ Object
This method needs to be defined *as a method*, otherwise it will cause the problem shown in #1247.
- .like_any(fields, values) ⇒ Object
- .simple_scopes ⇒ Object
Instance Method Summary collapse
- #available? ⇒ Boolean
-
#categorise_variants_from_option(opt_type) ⇒ Object
split variants list into hash which shows mapping of opt value onto matching variants eg categorise_variants_from_option(color) => -> […], “blue” -> […].
-
#delete ⇒ Object
override the delete method to set deleted_at value instead of actually deleting the product.
-
#deleted? ⇒ Boolean
use deleted? rather than checking the attribute directly.
-
#duplicate ⇒ Object
for adding products which are closely related to existing ones define “duplicate_extra” for site-specific actions, eg for additional fields.
- #empty_option_values? ⇒ Boolean
-
#ensure_option_types_exist_for_values_hash ⇒ Object
Ensures option_types and product_option_types exist for keys in option_values_hash.
-
#has_variants? ⇒ Boolean
the master variant is not a member of the variants array.
- #possible_promotions ⇒ Object
- #property(property_name) ⇒ Object
- #set_property(property_name, property_value) ⇒ Object
- #tax_category ⇒ Object
- #to_param ⇒ Object
-
#variants_and_option_values(current_currency = nil) ⇒ Object
Suitable for displaying only variants that has at least one option value.
- #variants_with_only_master ⇒ Object
Instance Attribute Details
#option_values_hash ⇒ Object
Returns the value of attribute option_values_hash.
72 73 74 |
# File 'app/models/spree/product.rb', line 72 def option_values_hash @option_values_hash end |
#prototype_id ⇒ Object
Adding properties and option types on creation based on a chosen prototype
120 121 122 |
# File 'app/models/spree/product.rb', line 120 def prototype_id @prototype_id end |
Class Method Details
.active(currency = nil) ⇒ Object
209 210 211 |
# File 'app/models/spree/product/scopes.rb', line 209 def self.active(currency = nil) not_deleted.available(nil, currency) end |
.add_search_scope(name, &block) ⇒ Object
7 8 9 10 |
# File 'app/models/spree/product/scopes.rb', line 7 def self.add_search_scope(name, &block) self.singleton_class.send(:define_method, name.to_sym, &block) search_scopes << name.to_sym end |
.add_simple_scopes(scopes) ⇒ Object
21 22 23 24 25 26 27 28 29 |
# File 'app/models/spree/product/scopes.rb', line 21 def self.add_simple_scopes(scopes) scopes.each do |name| # We should not define price scopes here, as they require something slightly different next if name.to_s.include?("master_price") parts = name.to_s.match(/(.*)_by_(.*)/) order_text = "#{Product.quoted_table_name}.#{parts[2]} #{parts[1] == 'ascend' ? "ASC" : "DESC"}" self.scope(name.to_s, relation.order(order_text)) end end |
.available(available_on = nil, currency = nil) ⇒ Object
Can’t use add_search_scope for this as it needs a default argument
200 201 202 203 204 205 206 |
# File 'app/models/spree/product/scopes.rb', line 200 def self.available(available_on = nil, currency = nil) scope = joins(:master => :prices).where("#{Product.quoted_table_name}.available_on <= ?", available_on || Time.now) unless Spree::Config.show_products_without_price scope = scope.where('spree_prices.currency' => currency || Spree::Config[:currency]).where('spree_prices.amount IS NOT NULL') end scope end |
.group_by_products_id ⇒ Object
This method needs to be defined *as a method*, otherwise it will cause the problem shown in #1247.
220 221 222 223 224 225 226 227 228 229 |
# File 'app/models/spree/product/scopes.rb', line 220 def self.group_by_products_id if (ActiveRecord::Base.connection.adapter_name == 'PostgreSQL') # Need to check, otherwise `column_names` will fail if table_exists? group(column_names.map { |col_name| "#{table_name}.#{col_name}"}) end else group("#{self.quoted_table_name}.id") end end |
.like_any(fields, values) ⇒ Object
159 160 161 162 |
# File 'app/models/spree/product.rb', line 159 def self.like_any(fields, values) where_str = fields.map { |field| Array.new(values.size, "#{self.quoted_table_name}.#{field} #{LIKE} ?").join(' OR ') }.join(' OR ') self.where([where_str, values.map { |value| "%#{value}%" } * fields.size].flatten) end |
.simple_scopes ⇒ Object
12 13 14 15 16 17 18 19 |
# File 'app/models/spree/product/scopes.rb', line 12 def self.simple_scopes [ :ascend_by_updated_at, :descend_by_updated_at, :ascend_by_name, :descend_by_name ] end |
Instance Method Details
#available? ⇒ Boolean
148 149 150 |
# File 'app/models/spree/product.rb', line 148 def available? !(available_on.nil? || available_on.future?) end |
#categorise_variants_from_option(opt_type) ⇒ Object
split variants list into hash which shows mapping of opt value onto matching variants eg categorise_variants_from_option(color) => -> […], “blue” -> […]
154 155 156 157 |
# File 'app/models/spree/product.rb', line 154 def categorise_variants_from_option(opt_type) return {} unless option_types.include?(opt_type) variants.active.group_by { |v| v.option_values.detect { |o| o.option_type == opt_type} } end |
#delete ⇒ Object
override the delete method to set deleted_at value instead of actually deleting the product.
114 115 116 117 |
# File 'app/models/spree/product.rb', line 114 def delete self.update_column(:deleted_at, Time.now) variants_including_master.update_all(deleted_at: Time.now) 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.
144 145 146 |
# File 'app/models/spree/product.rb', line 144 def deleted? !!deleted_at end |
#duplicate ⇒ Object
for adding products which are closely related to existing ones define “duplicate_extra” for site-specific actions, eg for additional fields
136 137 138 139 |
# File 'app/models/spree/product.rb', line 136 def duplicate duplicator = ProductDuplicator.new(self) duplicator.duplicate end |
#empty_option_values? ⇒ Boolean
175 176 177 178 179 |
# File 'app/models/spree/product.rb', line 175 def empty_option_values? .empty? || .any? do |opt| opt.option_type.option_values.empty? end end |
#ensure_option_types_exist_for_values_hash ⇒ Object
Ensures option_types and product_option_types exist for keys in option_values_hash
126 127 128 129 130 131 132 |
# File 'app/models/spree/product.rb', line 126 def ensure_option_types_exist_for_values_hash return if option_values_hash.nil? option_values_hash.keys.map(&:to_i).each do |id| self.option_type_ids << id unless option_type_ids.include?(id) product_option_types.create({option_type_id: id}, without_protection: true) unless product_option_types.pluck(:option_type_id).include?(id) end end |
#has_variants? ⇒ Boolean
the master variant is not a member of the variants array
100 101 102 |
# File 'app/models/spree/product.rb', line 100 def has_variants? variants.any? end |
#possible_promotions ⇒ Object
195 196 197 198 |
# File 'app/models/spree/product.rb', line 195 def possible_promotions promotion_ids = promotion_rules.map(&:activator_id).uniq Spree::Promotion.advertised.where(id: promotion_ids).reject(&:expired?) end |
#property(property_name) ⇒ Object
181 182 183 184 |
# File 'app/models/spree/product.rb', line 181 def property(property_name) return nil unless prop = properties.find_by_name(property_name) product_properties.find_by_property_id(prop.id).try(:value) end |
#set_property(property_name, property_value) ⇒ Object
186 187 188 189 190 191 192 193 |
# File 'app/models/spree/product.rb', line 186 def set_property(property_name, property_value) ActiveRecord::Base.transaction do property = Property.where(name: property_name).first_or_create!(presentation: property_name) product_property = ProductProperty.where(product_id: id, property_id: property.id).first_or_initialize product_property.value = property_value product_property.save! end end |
#tax_category ⇒ Object
104 105 106 107 108 109 110 |
# File 'app/models/spree/product.rb', line 104 def tax_category if self[:tax_category_id].nil? TaxCategory.where(is_default: true).first else TaxCategory.find(self[:tax_category_id]) end end |
#to_param ⇒ Object
95 96 97 |
# File 'app/models/spree/product.rb', line 95 def to_param permalink.present? ? permalink : (permalink_was || name.to_s.to_url) end |
#variants_and_option_values(current_currency = nil) ⇒ Object
Suitable for displaying only variants that has at least one option value. There may be scenarios where an option type is removed and along with it all option values. At that point all variants associated with only those values should not be displayed to frontend users. Otherwise it breaks the idea of having variants
169 170 171 172 173 |
# File 'app/models/spree/product.rb', line 169 def variants_and_option_values(current_currency = nil) variants.includes(:option_values).active(current_currency).select do |variant| variant.option_values.any? end end |
#variants_with_only_master ⇒ Object
90 91 92 93 |
# File 'app/models/spree/product.rb', line 90 def variants_with_only_master ActiveSupport::Deprecation.warn("[SPREE] Spree::Product#variants_with_only_master will be deprecated in Spree 1.3. Please use Spree::Product#master instead.") master end |