lib/volt/models/field_helpers.rb in volt-0.9.6 vs lib/volt/models/field_helpers.rb in volt-0.9.7.pre2

- old
+ new

@@ -1,93 +1,133 @@ # Provides a method to setup a field on a model. -module FieldHelpers - class InvalidFieldClass < RuntimeError; end +module Volt + module FieldHelpers + class InvalidFieldClass < RuntimeError; end - NUMERIC_CAST = lambda do |convert_method, val| - begin - orig = val + NUMERIC_CAST = lambda do |convert_method, val| + begin + orig = val - val = send(convert_method, val) + val = send(convert_method, val) - if RUBY_PLATFORM == 'opal' - # Opal has a bug in 0.7.2 that gives us back NaN without an - # error sometimes. - val = orig if val.nan? + if RUBY_PLATFORM == 'opal' + # Opal has a bug in 0.7.2 that gives us back NaN without an + # error sometimes. + val = orig if val.nan? + end + rescue TypeError, ArgumentError => e + # ignore, unmatched types will be caught below. + val = orig end - rescue TypeError, ArgumentError => e - # ignore, unmatched types will be caught below. - val = orig + + return val end - return val - end + FIELD_CASTS = { + String => :to_s.to_proc, + Fixnum => lambda {|val| NUMERIC_CAST[:Integer, val] }, + Numeric => lambda {|val| NUMERIC_CAST[:Float, val] }, + Float => lambda {|val| NUMERIC_CAST[:Float, val] }, + TrueClass => nil, + FalseClass => nil, + NilClass => nil, + Volt::Boolean => nil + } - FIELD_CASTS = { - String => :to_s.to_proc, - Fixnum => lambda {|val| NUMERIC_CAST[:Integer, val] }, - Numeric => lambda {|val| NUMERIC_CAST[:Float, val] }, - Float => lambda {|val| NUMERIC_CAST[:Float, val] }, - Time => nil, - TrueClass => nil, - FalseClass => nil, - NilClass => nil, - Volt::Boolean => nil - } + # If VoltTime has already been required by the time we load this class, we + # add it to the field casts: + if defined?(VoltTime) + FIELD_CASTS[VoltTime] = nil + end + module ClassMethods + # field lets you declare your fields instead of using the underscore syntax. + # An optional class restriction can be passed in. - module ClassMethods - # field lets you declare your fields instead of using the underscore syntax. - # An optional class restriction can be passed in. - def field(name, klasses = nil, options = {}) - if klasses - klasses = [klasses].flatten + def field(name, klasses = nil, options = {}) + name = name.to_sym + if klasses + klasses = [klasses].flatten - unless klasses.any? {|kl| FIELD_CASTS.key?(kl) } - klass_names = FIELD_CASTS.keys.map(&:to_s).join(', ') - msg = "valid field types is currently limited to #{klass_names}, you passed: #{klasses.inspect}" - fail FieldHelpers::InvalidFieldClass, msg - end + unless klasses.any? {|kl| FIELD_CASTS.key?(kl) } + klass_names = FIELD_CASTS.keys.map(&:to_s).join(', ') + msg = "valid field types is currently limited to #{klass_names}, you passed: #{klasses.inspect}" + fail FieldHelpers::InvalidFieldClass, msg + end - # Add NilClass as an allowed type unless allow_nil: false was passed. - unless options[:allow_nil] == false - klasses << NilClass + # defined in associations.rb + check_name_in_use(name) + + # Add NilClass as an allowed type unless nil: false was passed. + unless options[:nil] == false + options.delete(:nil) + klasses << NilClass + end end - end - self.fields_data ||= {} - self.fields_data[name] = [klasses, options] + # Normalize default + options.delete(:default) if options[:default] == nil - if klasses - # Add type validation, execpt for String, since anything can be cast to - # a string. - unless klasses.include?(String) - validate name, type: klasses + # Store the field defaults + if (default_val = options[:default]) + self.defaults[name] = default_val end - end - define_method(name) do - get(name) - end + self.fields[name] = [klasses, options] - define_method(:"#{name}=") do |val| - # Check if the value assigned matches the class restriction if klasses - # Cast to the right type - klasses.each do |kl| - if (func = FIELD_CASTS[kl]) - # Cast on the first available caster - val = func[val] - break + # Add type validation, execpt for String, since anything can be cast to + # a string. + unless klasses.include?(String) + validate name, type: klasses + end + end + + + # define the fields getter + define_method(name) do + get(name) + end + + define_method(:"#{name}=") do |val| + # Check if the value assigned matches the class restriction + if klasses + # Cast to the right type + klasses.each do |kl| + if (func = FIELD_CASTS[kl]) + # Cast on the first available caster + val = func[val] + break + end end end + + set(name, val) end + end - set(name, val) + def index(columns, options={}) + # Columns is stored in an array + columns = [columns].flatten.map {|c| c.to_sym } + + options[:columns] = columns + + # Add in default name + name = (options.delete(:name) || "#{collection_name}_#{columns.join('_')}_index").to_sym + self.indexes[name] = options end end - end - def self.included(base) - base.class_attribute :fields_data - base.send :extend, ClassMethods + def self.included(base) + base.class_attribute :fields + base.fields = {} + + base.class_attribute :indexes + base.indexes = {} + + base.class_attribute :defaults + base.defaults = {} + + base.send :extend, ClassMethods + end end end