module StrategyStores::ActiveRecord::Store
Public Class Methods
acts_as_strategy_store(store_attribute, options={})
click to toggle source
Define a new strategy store and all corresponding methods.
strategy_store
is the field to store the strategy. options
Same options as store method (expect ‘accessors’) and :
+use+ A strategy_ui_id. By default set to 'default' +prefix+ Prefix the strategy method by the store field name or by a given string
Calls superclass method
# File lib/strategy_store/active_record/store.rb, line 13 def self.acts_as_strategy_store(store_attribute, options={}) use_strategy = options.delete(:use) || :default # TODO : Refactor this into a fonction prefix = (op = options.delete(:prefix)) && ((op.is_a?(String) || op.is_a?(Symbol)) ? op : store_attribute) # Proc to return a symbol prefixed by the store_attribute if needed prefixed = Proc.new do |symbol| prefix.blank? ? symbol : "#{prefix}_#{symbol}".to_sym end store store_attribute, options.merge!(accessors: prefixed[:strategy_class]) # Return the strategy with loaded typed attributes define_method(prefixed[:strategy]) do # Create a dynamic instance var with store_attribute str_inst_var = "@_#{prefixed[:strategy]}".freeze # Proc to to call a method prefixed by the store_attribute if needed send_prefixed = Proc.new { |symbol, *args| __send__(prefixed[symbol], *args) } # Set the instance var this existing one or create it with the begin block instance_variable_set(str_inst_var, (!send_prefixed[:strategy_changed?] && instance_variable_get(str_inst_var)) || begin send_prefixed[:strategy_class] && send_prefixed[:strategy_class].new( self, send_prefixed[:initialize_or_retrive_strategy_hash] ) end ) end # Return true if the strategy has changed? define_method(prefixed[:strategy_changed?]) do __send__(prefixed[:strategy_class]) != instance_variable_get("@_#{prefixed[:strategy]}".freeze).class end # Return the strategy constantized define_method(prefixed[:strategy_class]) do super().to_s.safe_constantize end # Return the list of available strategies for this model field # TODO : rename strategies define_singleton_method(prefixed[:strategies]) do str_inst_var = "@_#{prefixed[:strategies]}".freeze instance_variable_set(str_inst_var, instance_variable_get(str_inst_var) || begin StrategyStore.fetch_strategy(use_strategy).class_implementations.to_a end ) end delegate prefixed[:strategies], to: :class # Make possible to accept hash of parameter like accept_neested_attributes define_method(prefixed[:strategy_attributes=]) do |attributes| _strategy = __send__(prefixed[:strategy]) assignable_attributes = attributes.slice(*_strategy.columns.keys) assignable_attributes.each do |attr_name, value| _strategy.send("#{attr_name}=", value) end end # PRIVATE METHODS # Get the strategy hash from store or initialize it if not exist. define_method(prefixed[:initialize_or_retrive_strategy_hash]) do __send__(store_attribute)[prefixed[:strategy]] ||= HashWithIndifferentAccess.new end __send__(:private, prefixed[:initialize_or_retrive_strategy_hash]) end