lib/bindata/choice.rb in bindata-1.3.1 vs lib/bindata/choice.rb in bindata-1.4.0

- old
+ new

@@ -1,6 +1,7 @@ require 'bindata/base' +require 'bindata/dsl' module BinData # A Choice is a collection of data objects of which only one is active # at any particular time. Method calls will be delegated to the active # choice. @@ -53,23 +54,26 @@ # specifies the currently active choice. # <tt>:copy_on_change</tt>:: If set to true, copy the value of the previous # selection to the current selection whenever the # selection changes. Default is false. class Choice < BinData::Base + include DSLMixin - register_self + dsl_parser :choice mandatory_parameters :choices, :selection optional_parameter :copy_on_change class << self - def sanitize_parameters!(params, sanitizer) #:nodoc: + def sanitize_parameters!(params) #:nodoc: + params.merge!(dsl_params) + if params.needs_sanitizing?(:choices) choices = choices_as_hash(params[:choices]) ensure_valid_keys(choices) - params[:choices] = sanitizer.create_sanitized_choices(choices) + params[:choices] = params.create_sanitized_choices(choices) end end #------------- private @@ -98,47 +102,28 @@ raise ArgumentError, ":choices hash may not have symbols for keys" end end end + def initialize_shared_instance + if eval_parameter(:copy_on_change) == true + class << self + alias_method :hook_after_current_choice, :copy_previous_value + end + end + end + def initialize_instance @choices = {} @last_selection = nil end # A convenience method that returns the current selection. def selection eval_parameter(:selection) end - # This method does not exist. This stub only exists to document why. - # There is no #selection= method to complement the #selection method. - # This is deliberate to promote the declarative nature of BinData. - # - # If you really *must* be able to programmatically adjust the selection - # then try something like the following. - # - # class ProgrammaticChoice < BinData::Wrapper - # choice :selection => :selection - # attr_accessor :selection - # end - # - # type1 = [:string, {:value => "Type1"}] - # type2 = [:string, {:value => "Type2"}] - # - # choices = {5 => type1, 17 => type2} - # pc = ProgrammaticChoice.new(:choices => choices) - # - # pc.selection = 5 - # pc #=> "Type1" - # - # pc.selection = 17 - # pc #=> "Type2" - def selection=(sel) - raise NoMethodError, "See rdoc BinData::Choice.selection= for details" - end - def clear #:nodoc: current_choice.clear end def clear? #:nodoc: @@ -176,19 +161,20 @@ #--------------- private def hook_before_do_read; end + def hook_after_current_choice(*args); end def current_choice selection = eval_parameter(:selection) if selection.nil? raise IndexError, ":selection returned nil for #{debug_name}" end obj = get_or_instantiate_choice(selection) - copy_previous_value_if_required(selection, obj) + hook_after_current_choice(selection, obj) obj end def get_or_instantiate_choice(selection) @@ -201,32 +187,24 @@ raise IndexError, "selection '#{selection}' does not exist in :choices for #{debug_name}" end prototype.instantiate(nil, self) end - def copy_previous_value_if_required(selection, obj) + def copy_previous_value(selection, obj) prev = get_previous_choice(selection) - if should_copy_value?(prev, obj) - obj.assign(prev) - end + obj.assign(prev) unless prev.nil? remember_current_selection(selection) end - def should_copy_value?(prev, cur) - prev != nil and eval_parameter(:copy_on_change) == true - end - def get_previous_choice(selection) if selection != @last_selection and @last_selection != nil @choices[@last_selection] else nil end end def remember_current_selection(selection) - if selection != @last_selection - @last_selection = selection - end + @last_selection = selection end end end