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