Class: SolidusPromotions::Condition Abstract
- Inherits:
-
Spree::Base
- Object
- Spree::Base
- SolidusPromotions::Condition
- Includes:
- Spree::Preferences::Persistable
- Defined in:
- app/models/solidus_promotions/condition.rb
Overview
Subclass and override #applicable? and #eligible? to implement a custom condition.
Base class for all promotion conditions.
Conditions determine whether a promotion is eligible to be applied to a specific promotable object (such as an order or line item). Each condition subclass implements the eligibility logic and specifies what type of objects it can be applied to.
Conditions work at different levels:
-
Order-level conditions (include OrderLevelCondition): Check entire orders
-
Line item-level conditions (include LineItemLevelCondition): Check individual line items
-
Hybrid conditions (include LineItemApplicableOrderLevelCondition): Check orders but can also filter which line items are eligible
Direct Known Subclasses
SolidusPromotions::Conditions::FirstOrder, SolidusPromotions::Conditions::FirstRepeatPurchaseSince, SolidusPromotions::Conditions::ItemTotal, SolidusPromotions::Conditions::LineItemOptionValue, SolidusPromotions::Conditions::LineItemProduct, SolidusPromotions::Conditions::LineItemTaxon, SolidusPromotions::Conditions::MinimumQuantity, SolidusPromotions::Conditions::NthOrder, SolidusPromotions::Conditions::OneUsePerUser, SolidusPromotions::Conditions::OptionValue, SolidusPromotions::Conditions::OrderOptionValue, SolidusPromotions::Conditions::OrderProduct, SolidusPromotions::Conditions::OrderTaxon, SolidusPromotions::Conditions::PriceOptionValue, SolidusPromotions::Conditions::PriceProduct, SolidusPromotions::Conditions::PriceTaxon, SolidusPromotions::Conditions::Product, SolidusPromotions::Conditions::ShippingMethod, SolidusPromotions::Conditions::Store, SolidusPromotions::Conditions::Taxon, SolidusPromotions::Conditions::User, SolidusPromotions::Conditions::UserLoggedIn, SolidusPromotions::Conditions::UserRole
Class Method Summary collapse
-
.applicable_to(classes) ⇒ Array<SolidusPromotions::Condition>
Returns the subset of conditions that can compute eligibility instances of the provided array of classes.
-
.eligible_method_for(promotable_class) ⇒ Symbol
Generates the eligibility method name for a promotable.
- .inherited(klass) ⇒ Object
Instance Method Summary collapse
-
#applicable?(promotable) ⇒ Boolean
Determines if this condition can be applied to a given promotable object.
-
#eligibility_errors ⇒ ActiveModel::Errors
Returns an errors object for tracking eligibility failures.
-
#eligible?(promotable) ⇒ Boolean
Determines if the promotable object meets this condition’s eligibility requirements.
- #level ⇒ Object
-
#preload_relations ⇒ Array<Symbol>
Returns relations that should be preloaded for this condition.
-
#to_partial_path ⇒ String
Returns the partial path for rendering this condition in the admin interface.
-
#updateable? ⇒ Boolean
Determines if this condition can be updated in the admin interface.
Class Method Details
.applicable_to(classes) ⇒ Array<SolidusPromotions::Condition>
Returns the subset of conditions that can compute eligibility instances of the provided array of classes.
64 65 66 67 68 |
# File 'app/models/solidus_promotions/condition.rb', line 64 def applicable_to(classes) SolidusPromotions.config.conditions.select do |condition_class| (condition_class.instance_methods & classes.map { |k| eligible_method_for(k) }).any? end end |
.eligible_method_for(promotable_class) ⇒ Symbol
Generates the eligibility method name for a promotable
73 74 75 |
# File 'app/models/solidus_promotions/condition.rb', line 73 def eligible_method_for(promotable_class) :"#{promotable_class.name.demodulize.underscore}_eligible?" end |
.inherited(klass) ⇒ Object
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'app/models/solidus_promotions/condition.rb', line 125 def self.inherited(klass) def klass.method_added(method_added) if method_added == :eligible? Spree.deprecator.warn <<~MSG Please refactor `#{name}`. You're defining `eligible?`. Instead, define method for each type of promotable that your condition can be applied to. For example: ``` class MyCondition < SolidusPromotions::Condition def applicable?(promotable) promotable.is_a?(Spree::Order) end def eligible?(order) order.total > 20 end ``` can now become ``` class MyCondition < SolidusPromotions::Condition def order_eligible?(order) order.total > 20 end end ``` MSG end super end super end |
Instance Method Details
#applicable?(promotable) ⇒ Boolean
Determines if this condition can be applied to a given promotable object.
102 103 104 |
# File 'app/models/solidus_promotions/condition.rb', line 102 def applicable?(promotable) respond_to?(eligible_method_for(promotable)) end |
#eligibility_errors ⇒ ActiveModel::Errors
Returns an errors object for tracking eligibility failures.
When #eligible? determines that a promotable doesn’t meet the condition, it should add descriptive errors to this object. These errors are used to provide feedback about why a promotion isn’t being applied.
176 177 178 |
# File 'app/models/solidus_promotions/condition.rb', line 176 def eligibility_errors @eligibility_errors ||= ActiveModel::Errors.new(self) end |
#eligible?(promotable) ⇒ Boolean
Determines if the promotable object meets this condition’s eligibility requirements.
This typically dispatches to a specific eligibility method defined on a subclass, such as ‘#order_eligible?` or `line_item_eligible?`.
117 118 119 120 121 122 123 |
# File 'app/models/solidus_promotions/condition.rb', line 117 def eligible?(promotable, ...) if applicable?(promotable) send(eligible_method_for(promotable), promotable, ...) else raise NotImplementedError, "Please implement #{eligible_method_for(promotable)} in your condition" end end |
#level ⇒ Object
156 157 158 |
# File 'app/models/solidus_promotions/condition.rb', line 156 def level raise NotImplementedError, "level should be implemented in a sub-class of SolidusPromotions::Condition" end |
#preload_relations ⇒ Array<Symbol>
Returns relations that should be preloaded for this condition.
Override this method in subclasses to specify associations that should be eager loaded to avoid N+1 queries when evaluating conditions.
89 90 91 |
# File 'app/models/solidus_promotions/condition.rb', line 89 def preload_relations [] end |
#to_partial_path ⇒ String
Returns the partial path for rendering this condition in the admin interface.
187 188 189 |
# File 'app/models/solidus_promotions/condition.rb', line 187 def to_partial_path "solidus_promotions/admin/condition_fields/#{model_name.element}" end |
#updateable? ⇒ Boolean
Determines if this condition can be updated in the admin interface.
A condition is considered updateable if it has any preferences that can be configured.
196 197 198 |
# File 'app/models/solidus_promotions/condition.rb', line 196 def updateable? preferences.any? end |