lib/gorillib/model/field.rb in gorillib-0.4.1pre vs lib/gorillib/model/field.rb in gorillib-0.4.2pre
- old
+ new
@@ -13,11 +13,11 @@
# [Gorillib::Model] Model owning this field
attr_reader :model
# [Hash] all options passed to the field not recognized by one of its own current fields
- attr_reader :extra_attributes
+ attr_reader :_extra_attributes
# Note: `Gorillib::Model::Field` is assembled in two pieces, so that it
# can behave as a model itself. Defining `name` here, along with some
# fudge in #initialize, provides enough functionality to bootstrap.
# The fields are then defined properly at the end of the file.
@@ -26,25 +26,27 @@
attr_reader :type
class_attribute :visibilities, :instance_writer => false
self.visibilities = { :reader => :public, :writer => :public, :receiver => :public, :tester => false }
-
# @param [#to_sym] name Field name
# @param [#receive] type Factory for field values. To accept any object as-is, specify `Object` as the type.
# @param [Gorillib::Model] model Field's owner
# @param [Hash{Symbol => Object}] options Extended attributes
# @option options [String] doc Description of the field's purpose
# @option options [true, false, :public, :protected, :private] :reader Visibility for the reader (`#foo`) method; `false` means don't create one.
# @option options [true, false, :public, :protected, :private] :writer Visibility for the writer (`#foo=`) method; `false` means don't create one.
# @option options [true, false, :public, :protected, :private] :receiver Visibility for the receiver (`#receive_foo`) method; `false` means don't create one.
#
- def initialize(name, type, model, options={})
+ def initialize(model, name, type, options={})
Validate.identifier!(name)
+ type_opts = options.extract!(:blankish, :empty_product, :items, :keys, :of)
+ type_opts[:items] = type_opts.delete(:of) if type_opts.has_key?(:of)
+ #
@model = model
@name = name.to_sym
- @type = self.factory_for(type)
+ @type = Gorillib::Factory.factory_for(type, type_opts)
default_visabilities = visibilities
@visibilities = default_visabilities.merge( options.extract!(*default_visabilities.keys) )
@doc = options.delete(:name){ "#{name} field" }
receive!(options)
end
@@ -54,33 +56,32 @@
# @return [String] the field name
def to_s
name.to_s
end
- def factory_for(type)
- Gorillib::Factory(type)
- end
-
# @return [String] Human-readable presentation of the field definition
def inspect
- args = [name.inspect, type.to_s]
- "field(#{args.join(", ")})"
+ args = [name.inspect, type.to_s, attributes.reject{|k,v| k =~ /^(name|type)$/}.inspect]
+ "field(#{args.join(",")})"
end
+ def inspect_compact
+ "field(#{name})"
+ end
def to_hash
- attributes.merge!(@visibility).merge!(@extra_attributes)
+ attributes.merge!(@visibility).merge!(@_extra_attributes)
end
def ==(val)
- super && (val.extra_attributes == self.extra_attributes) && (val.model == self.model)
+ super && (val._extra_attributes == self._extra_attributes) && (val.model == self.model)
end
def self.receive(hsh)
name = hsh.fetch(:name)
type = hsh.fetch(:type)
model = hsh.fetch(:model)
- new(name, type, model, hsh)
+ new(model, name, type, hsh)
end
#
# returns the visibility
#
@@ -108,25 +109,46 @@
#
# Now we can construct the actual fields.
#
+ field :position, Integer, :tester => true, :doc => "Indicates this is a positional initialization arg -- you can pass it as a plain value in the given slot to #initialize"
+
# Name of this field. Must start with `[A-Za-z_]` and subsequently contain only `[A-Za-z0-9_]` (required)
# @macro [attach] field
# @attribute $1
# @return [$2] the $1 field $*
- field :name, String, :writer => false, :doc => "The field name. Must start with `[A-Za-z_]` and subsequently contain only `[A-Za-z0-9_]` (required)"
+ field :name, String, position: 0, writer: false, doc: "The field name. Must start with `[A-Za-z_]` and subsequently contain only `[A-Za-z0-9_]` (required)"
- # Factory for the field's values
- field :type, Class
+ field :type, Class, position: 1, doc: "Factory to generate field's values"
- # Field's description
- field :doc, String
+ field :doc, String, doc: "Field's description"
# remove the attr_reader method (needed for scaffolding), leaving the meta_module method to remain
remove_possible_method(:name)
end
+
+
+ class SimpleCollectionField < Gorillib::Model::Field
+ field :item_type, Class, default: Whatever, doc: "Factory for collection items"
+ # field :collection_attrs, Hash, default: Hash.new, doc: "Extra attributes to pass to the collection on creation -- eg. key_method"
+
+ def initialize(model, name, type, options={})
+ super
+ collection_type = self.type
+ item_type = self.item_type
+ key_method = options[:key_method] if options[:key_method]
+ raise "Please supply an item type for #{self.inspect} -- eg 'collection #{name.inspect}, of: FooClass'" unless item_type
+ self.default ||= ->{ collection_type.new(item_type: item_type, belongs_to: self, key_method: key_method) }
+ end
+
+ def inscribe_methods(model)
+ super
+ model.__send__(:define_collection_receiver, self)
+ end
+ end
+
end
end
# * aliases
# * order