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