lib/efo_nelfo/property.rb in efo_nelfo-1.2.0 vs lib/efo_nelfo/property.rb in efo_nelfo-1.3.0
- old
+ new
@@ -1,156 +1,95 @@
+using EfoNelfo::PropertyTypes
+
module EfoNelfo
- module Property
+ class Property
+ VALID_OPTIONS = [:type, :required, :limit, :read_only, :default, :decimals]
+ VALID_TYPES = [:string, :integer, :boolean, :date]
- def self.included(base)
- base.send :extend, ClassMethods
- end
+ attr_reader :name, :options, :value
- def initialize_attributes(*args)
- if args && args.first.is_a?(Hash)
- args.first.each do |attr, value|
- send "#{attr}=", value
- end
- end
+ def self.validate_options!(options)
+ invalid_options = options.keys - VALID_OPTIONS
+ raise EfoNelfo::UnknownPropertyOption.new("Invalid options: #{invalid_options.join(',')}") if invalid_options.any?
+ raise EfoNelfo::InvalidPropertyType.new("Valid types are #{VALID_TYPES.join(',')}") unless VALID_TYPES.include?(options[:type])
end
- def attributes
- @attributes ||= initialize_default_attributes
- end
+ def initialize(name, defaults={})
- def properties
- self.class.properties
- end
+ options = {
+ type: :string,
+ required: false,
+ default: nil,
+ read_only: false,
+ decimals: nil,
+ limit: 100
+ }
+ options.update(defaults) if defaults.is_a?(Hash)
- def has_property?(property)
- properties.include? property
- end
+ self.class.validate_options! options
- def to_a
- properties.keys.map { |prop| formatted_for_csv(prop) }
+ @name = name
+ @options = options
+ @value = options[:default]
end
- private
+ # Assign a value to the property
+ # The value is converted to whatever specified by options[:type]
+ # Examples:
+ # (boolean) value = 'J' # => true
+ # (boolean) value = false # => false
+ # (date) value = '20120101' # => Date.new(2012,1,1)
+ # (integer) value = '2' # => 2
+ # (string) value = 'foo' # => 'foo'
+ def value=(new_value)
+ return nil if readonly?
- def initialize_default_attributes
- properties.inject({}) { |h,(name,options)| h[name] = options[:default]; h }
- end
-
- def format_value(value, type)
- case type
- when :integer
- value.nil? ? nil : value.to_i
- when :date
- if value.nil?
- nil
- elsif value.kind_of? String
- Date.parse value
+ @value = case
+ when boolean?
+ new_value.nil? || new_value == true || new_value == 'J' || new_value == 'j' || new_value == '' ? true : false
+ when date?
+ new_value.is_a?(Date) ? new_value : Date.parse(new_value) rescue nil
+ when integer?
+ new_value.nil? ? nil : new_value.to_i
else
- value
- end
- when :boolean
- value.nil? || value == true || value == 'J' || value == '' ? true : false
- else
- value
+ new_value
end
end
- # Format value for given attribute
- def formatted_for_csv(attr)
+ # returns formatted value suitable for csv output
+ def to_csv
+ output = value.to_csv
+ end
- if respond_to?("format_#{attr}")
- value = send "format_#{attr}"
- else
- value = send attr
+ # Returns integer to floating point based on specified decimals
+ # Example:
+ # If decimal is set to 4, and the value is 4000
+ # then to_f returns 0.4
+ def to_f
+ return nil if value.nil?
+ value.to_f.with_decimals decimals
+ end
+ alias :to_decimal :to_f
- type = properties[attr][:type]
+ # Returns true if the property is read only
+ def readonly?
+ options[:read_only]
+ end
- value = case type
- when :date
- value ? value.strftime("%Y%m%d") : nil
- when :boolean
- value == true ? "J" : nil
- else
- value
- end
- end
- value.respond_to?(:encode) ? value.encode(Encoding::ISO_8859_1) : value
+ # Returns true if the property is required
+ # Note: this is not in use yet
+ def required?
+ options[:required]
end
- module ClassMethods
- # Creates an attribute with given name.
- #
- # Options
- # - type String, Integer etc. Default is String
- # - required whether attribute is required. Default is false
- # - limit Length the attribute can be. Default is nil
- # - alias Norwegian alias name for the attribute
- #
- def property(name, options={})
+ def boolean?; type == :boolean; end
+ def date?; type == :date; end
+ def integer?; type == :integer; end
+ def string?; type == :string; end
- options = {
- type: :string,
- required: false,
- }.update options
-
- name = name.to_sym
-
- # ensure all options are valid
- valid_options = [:type, :required, :limit, :read_only, :alias, :default]
- invalid_options = options.keys - valid_options
- raise EfoNelfo::UnknownPropertyOption.new("Invalid option for #{name}: #{invalid_options.join(',')}") if invalid_options.any?
-
- # Store property info in @properties
- raise EfoNelfo::DuplicateProperty if properties.has_key?(name)
- properties[name] = options
-
- create_reader_for(name, options)
- create_setter_for(name, options) unless options[:read_only]
- create_question_for(name) if options[:type] == :boolean
- create_alias_for(name, options) if options[:alias]
- end
-
- # Returns all properties
- def properties
- @_properties ||= {}
- end
-
- private
-
- # Creates an attribute accessor for name
- def create_reader_for(name, options)
- define_method name do
- attributes[name]
- end
- end
-
- # Creates an attribute setter for name
- def create_setter_for(name, options)
- define_method "#{name}=" do |value|
- attributes[name] = format_value(value, options[:type])
- end
- end
-
- # Creates a name? accessor
- def create_question_for(name)
- define_method "#{name}?" do
- attributes[name] == true
- end
- end
-
- def create_alias_for(name, options)
- define_method(options[:alias]) do
- send name
- end
-
- unless options[:read_only]
- define_method("#{options[:alias]}=") do |val|
- send "#{name}=", val
- end
- end
- end
-
+ def method_missing(*args)
+ options.has_key?(args.first) ? options[args.first] : super
end
end
end