Class: PricingPlans::Configuration
- Inherits:
-
Object
- Object
- PricingPlans::Configuration
- Includes:
- DSL
- Defined in:
- lib/pricing_plans/configuration.rb
Constant Summary
Constants included from DSL
Instance Attribute Summary collapse
-
#auto_price_labels_from_processor ⇒ Object
Auto-fetch price labels from processor when possible (Stripe via stripe-ruby).
-
#controller_plan_owner_method ⇒ Object
readonly
Global controller ergonomics Optional global resolver for controller plan owner.
-
#controller_plan_owner_proc ⇒ Object
readonly
Global controller ergonomics Optional global resolver for controller plan owner.
-
#debug ⇒ Object
Debug mode - set to true to enable debug output.
-
#default_cta_text ⇒ Object
Optional ergonomics.
-
#default_cta_url ⇒ Object
Optional ergonomics.
-
#default_currency_symbol ⇒ Object
Default currency symbol when Stripe isn't available.
-
#default_plan ⇒ Object
Returns the value of attribute default_plan.
-
#downgrade_policy ⇒ Object
Optional downgrade policy hook for CTA ergonomics Signature: ->(from:, to:, plan_owner:) { [allowed_boolean, reason_string_or_nil] }.
-
#event_handlers ⇒ Object
readonly
Returns the value of attribute event_handlers.
-
#free_price_caption ⇒ Object
Optional free caption copy (UI copy holder).
-
#highlighted_plan ⇒ Object
Returns the value of attribute highlighted_plan.
-
#interval_default_for_ui ⇒ Object
Optional default interval for UI toggles.
-
#message_builder ⇒ Object
Optional global message builder proc for human copy (i18n/hooks) Signature suggestion: (context:, **kwargs) -> string Contexts used: :over_limit, :grace, :feature_denied Example kwargs: limit_key:, current_usage:, limit_amount:, grace_ends_at:, feature_key:, plan_name:.
-
#period_cycle ⇒ Object
Returns the value of attribute period_cycle.
-
#plan_owner_class ⇒ Object
Returns the value of attribute plan_owner_class.
-
#plans ⇒ Object
readonly
Returns the value of attribute plans.
-
#price_cache ⇒ Object
Cache for Stripe prices.
-
#price_cache_ttl ⇒ Object
Seconds for cache TTL for Stripe lookups.
-
#price_components_resolver ⇒ Object
Semantic pricing components resolver hook: ->(plan, interval) { PriceComponents | nil }.
-
#price_label_resolver ⇒ Object
Optional: custom resolver for displaying price labels from processor Signature: ->(plan) { "$amount/mo" }.
-
#redirect_on_blocked_limit ⇒ Object
When a limit check blocks, controllers can redirect to a global default target.
Instance Method Summary collapse
-
#controller_plan_owner(method_name = nil, &block) ⇒ Object
Global controller plan owner resolver API Usage: config.controller_plan_owner :current_organization # or config.controller_plan_owner { current_account }.
-
#initialize ⇒ Configuration
constructor
A new instance of Configuration.
-
#on_block(limit_key = nil) {|plan_owner, limit_key| ... } ⇒ Object
Register a callback for block events.
-
#on_grace_start(limit_key = nil) {|plan_owner, limit_key, grace_ends_at| ... } ⇒ Object
Register a callback for grace period start events.
-
#on_warning(limit_key = nil) {|plan_owner, limit_key, threshold| ... } ⇒ Object
Register a callback for warning events.
- #plan(key, &block) ⇒ Object
- #select_defaults_from_dsl! ⇒ Object
- #validate! ⇒ Object
- #validate_dsl_markers! ⇒ Object
Constructor Details
#initialize ⇒ Configuration
Returns a new instance of Configuration.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/pricing_plans/configuration.rb', line 55 def initialize @plan_owner_class = nil @default_plan = nil @highlighted_plan = nil @period_cycle = :billing_cycle @default_cta_text = nil @default_cta_url = nil @message_builder = nil @controller_plan_owner_method = nil @controller_plan_owner_proc = nil @redirect_on_blocked_limit = nil @price_label_resolver = nil @auto_price_labels_from_processor = true @price_components_resolver = nil @default_currency_symbol = "$" @price_cache = (defined?(Rails) && Rails.respond_to?(:cache)) ? Rails.cache : nil @price_cache_ttl = 600 # 10 minutes @free_price_caption = "Forever free" @interval_default_for_ui = :month @downgrade_policy = ->(from:, to:, plan_owner:) { [true, nil] } @debug = false @plans = {} @event_handlers = { warning: {}, grace_start: {}, block: {} } end |
Instance Attribute Details
#auto_price_labels_from_processor ⇒ Object
Auto-fetch price labels from processor when possible (Stripe via stripe-ruby)
37 38 39 |
# File 'lib/pricing_plans/configuration.rb', line 37 def auto_price_labels_from_processor @auto_price_labels_from_processor end |
#controller_plan_owner_method ⇒ Object (readonly)
Global controller ergonomics Optional global resolver for controller plan owner. Per-controller settings still win. Accepts:
- Symbol: a controller helper to call (e.g., :current_organization)
- Proc: instance-exec'd in the controller (self is the controller)
19 20 21 |
# File 'lib/pricing_plans/configuration.rb', line 19 def controller_plan_owner_method @controller_plan_owner_method end |
#controller_plan_owner_proc ⇒ Object (readonly)
Global controller ergonomics Optional global resolver for controller plan owner. Per-controller settings still win. Accepts:
- Symbol: a controller helper to call (e.g., :current_organization)
- Proc: instance-exec'd in the controller (self is the controller)
19 20 21 |
# File 'lib/pricing_plans/configuration.rb', line 19 def controller_plan_owner_proc @controller_plan_owner_proc end |
#debug ⇒ Object
Debug mode - set to true to enable debug output
13 14 15 |
# File 'lib/pricing_plans/configuration.rb', line 13 def debug @debug end |
#default_cta_text ⇒ Object
Optional ergonomics
11 12 13 |
# File 'lib/pricing_plans/configuration.rb', line 11 def default_cta_text @default_cta_text end |
#default_cta_url ⇒ Object
Optional ergonomics
11 12 13 |
# File 'lib/pricing_plans/configuration.rb', line 11 def default_cta_url @default_cta_url end |
#default_currency_symbol ⇒ Object
Default currency symbol when Stripe isn't available
41 42 43 |
# File 'lib/pricing_plans/configuration.rb', line 41 def default_currency_symbol @default_currency_symbol end |
#default_plan ⇒ Object
Returns the value of attribute default_plan.
9 10 11 |
# File 'lib/pricing_plans/configuration.rb', line 9 def default_plan @default_plan end |
#downgrade_policy ⇒ Object
Optional downgrade policy hook for CTA ergonomics Signature: ->(from:, to:, plan_owner:) { [allowed_boolean, reason_string_or_nil] }
52 53 54 |
# File 'lib/pricing_plans/configuration.rb', line 52 def downgrade_policy @downgrade_policy end |
#event_handlers ⇒ Object (readonly)
Returns the value of attribute event_handlers.
53 54 55 |
# File 'lib/pricing_plans/configuration.rb', line 53 def event_handlers @event_handlers end |
#free_price_caption ⇒ Object
Optional free caption copy (UI copy holder)
47 48 49 |
# File 'lib/pricing_plans/configuration.rb', line 47 def free_price_caption @free_price_caption end |
#highlighted_plan ⇒ Object
Returns the value of attribute highlighted_plan.
9 10 11 |
# File 'lib/pricing_plans/configuration.rb', line 9 def highlighted_plan @highlighted_plan end |
#interval_default_for_ui ⇒ Object
Optional default interval for UI toggles
49 50 51 |
# File 'lib/pricing_plans/configuration.rb', line 49 def interval_default_for_ui @interval_default_for_ui end |
#message_builder ⇒ Object
Optional global message builder proc for human copy (i18n/hooks) Signature suggestion: (context:, **kwargs) -> string Contexts used: :over_limit, :grace, :feature_denied Example kwargs: limit_key:, current_usage:, limit_amount:, grace_ends_at:, feature_key:, plan_name:
31 32 33 |
# File 'lib/pricing_plans/configuration.rb', line 31 def @message_builder end |
#period_cycle ⇒ Object
Returns the value of attribute period_cycle.
9 10 11 |
# File 'lib/pricing_plans/configuration.rb', line 9 def period_cycle @period_cycle end |
#plan_owner_class ⇒ Object
Returns the value of attribute plan_owner_class.
32 33 34 |
# File 'lib/pricing_plans/configuration.rb', line 32 def plan_owner_class @plan_owner_class end |
#plans ⇒ Object (readonly)
Returns the value of attribute plans.
53 54 55 |
# File 'lib/pricing_plans/configuration.rb', line 53 def plans @plans end |
#price_cache ⇒ Object
Cache for Stripe prices. Defaults to in-memory store if nil. Should respond to read/write with ttl.
43 44 45 |
# File 'lib/pricing_plans/configuration.rb', line 43 def price_cache @price_cache end |
#price_cache_ttl ⇒ Object
Seconds for cache TTL for Stripe lookups
45 46 47 |
# File 'lib/pricing_plans/configuration.rb', line 45 def price_cache_ttl @price_cache_ttl end |
#price_components_resolver ⇒ Object
Semantic pricing components resolver hook: ->(plan, interval) { PriceComponents | nil }
39 40 41 |
# File 'lib/pricing_plans/configuration.rb', line 39 def price_components_resolver @price_components_resolver end |
#price_label_resolver ⇒ Object
Optional: custom resolver for displaying price labels from processor Signature: ->(plan) { "$amount/mo" }
35 36 37 |
# File 'lib/pricing_plans/configuration.rb', line 35 def price_label_resolver @price_label_resolver end |
#redirect_on_blocked_limit ⇒ Object
When a limit check blocks, controllers can redirect to a global default target. Accepts:
- Symbol: a controller helper to call (e.g., :pricing_path)
- String: an absolute/relative path or full URL
- Proc: instance-exec'd in the controller (self is the controller). Signature: ->(result) { ... } Result contains: limit_key, plan_owner, message, metadata
26 27 28 |
# File 'lib/pricing_plans/configuration.rb', line 26 def redirect_on_blocked_limit @redirect_on_blocked_limit end |
Instance Method Details
#controller_plan_owner(method_name = nil, &block) ⇒ Object
Global controller plan owner resolver API Usage:
config.controller_plan_owner :current_organization
# or
config.controller_plan_owner { current_account }
110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/pricing_plans/configuration.rb', line 110 def controller_plan_owner(method_name = nil, &block) if method_name @controller_plan_owner_method = method_name.to_sym @controller_plan_owner_proc = nil elsif block_given? @controller_plan_owner_proc = block @controller_plan_owner_method = nil else @controller_plan_owner_method end end |
#on_block(limit_key = nil) {|plan_owner, limit_key| ... } ⇒ Object
Register a callback for block events.
143 144 145 146 147 |
# File 'lib/pricing_plans/configuration.rb', line 143 def on_block(limit_key = nil, &block) raise PricingPlans::ConfigurationError, "Block required for on_block" unless block_given? key = limit_key || :_all @event_handlers[:block][key] = block end |
#on_grace_start(limit_key = nil) {|plan_owner, limit_key, grace_ends_at| ... } ⇒ Object
Register a callback for grace period start events.
134 135 136 137 138 |
# File 'lib/pricing_plans/configuration.rb', line 134 def on_grace_start(limit_key = nil, &block) raise PricingPlans::ConfigurationError, "Block required for on_grace_start" unless block_given? key = limit_key || :_all @event_handlers[:grace_start][key] = block end |
#on_warning(limit_key = nil) {|plan_owner, limit_key, threshold| ... } ⇒ Object
Register a callback for warning events.
125 126 127 128 129 |
# File 'lib/pricing_plans/configuration.rb', line 125 def on_warning(limit_key = nil, &block) raise PricingPlans::ConfigurationError, "Block required for on_warning" unless block_given? key = limit_key || :_all @event_handlers[:warning][key] = block end |
#plan(key, &block) ⇒ Object
95 96 97 98 99 100 101 102 |
# File 'lib/pricing_plans/configuration.rb', line 95 def plan(key, &block) raise PricingPlans::ConfigurationError, "Plan key must be a symbol" unless key.is_a?(Symbol) raise PricingPlans::ConfigurationError, "Plan #{key} already defined" if @plans.key?(key) plan_instance = PricingPlans::Plan.new(key) plan_instance.instance_eval(&block) @plans[key] = plan_instance end |
#select_defaults_from_dsl! ⇒ Object
156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/pricing_plans/configuration.rb', line 156 def select_defaults_from_dsl! # If not explicitly configured, derive from any plan marked via DSL sugar if @default_plan.nil? dsl_default = @plans.values.find(&:default?)&.key @default_plan = dsl_default if dsl_default end if @highlighted_plan.nil? dsl_highlighted = @plans.values.find(&:highlighted?)&.key @highlighted_plan = dsl_highlighted if dsl_highlighted end end |
#validate! ⇒ Object
149 150 151 152 153 154 155 |
# File 'lib/pricing_plans/configuration.rb', line 149 def validate! select_defaults_from_dsl! validate_required_settings! validate_plan_references! validate_dsl_markers! validate_plans! end |
#validate_dsl_markers! ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/pricing_plans/configuration.rb', line 169 def validate_dsl_markers! defaults = @plans.values.select(&:default?) highlights = @plans.values.select(&:highlighted?) if defaults.size > 1 keys = defaults.map(&:key).join(", ") raise PricingPlans::ConfigurationError, "Multiple plans marked default via DSL: #{keys}. Only one plan can be default." end if highlights.size > 1 keys = highlights.map(&:key).join(", ") raise PricingPlans::ConfigurationError, "Multiple plans marked highlighted via DSL: #{keys}. Only one plan can be highlighted." end end |