lib/dm-is-predefined/is/predefined.rb in dm-is-predefined-0.3.1 vs lib/dm-is-predefined/is/predefined.rb in dm-is-predefined-0.4.0

- old
+ new

@@ -2,127 +2,261 @@ module DataMapper module Is module Predefined # - # Fired when your plugin gets included into Resource. + # Fired when your plugin gets included into a Model. # + # @note + # If the model already includes `DataMapper::Migrations`, then + # {MigrationMethods} will be extended into the Model. + # + # @api private + # def is_predefined extend DataMapper::Is::Predefined::ClassMethods + + if defined?(DataMapper::Migrations) && + included_modules.include?(DataMapper::Migrations) + extend MigrationMethods + end end + # + # @since 0.4.0 + # + module MigrationMethods + # + # Auto-migrates the model, then creates all predefined resources. + # + # @param [Symbol] repository_name + # The repository to perform the migrations within. + # + # @return [true] + # + # @api public + # + def auto_migrate!(repository_name=self.repository_name) + result = super(repository_name) + + predefine!(repository_name) + return result + end + + # + # Auto-upgrades the model, then creates any missing predefined + # resources. + # + # @param [Symbol] repository_name + # The repository to perform the upgrade within. + # + # @return [true] + # + # @api public + # + def auto_upgrade!(repository_name=self.repository_name) + result = super(repository_name) + + predefine!(repository_name) + return result + end + end + module ClassMethods # + # All pre-defined resources of the model. + # + # @return [Hash{Symbol => Hash}] + # The Hash of pre-defined resources and their attributes. + # + # @api semipublic + # + def predefined_attributes + @predefined_attributes ||= {} + end + + # # Returns the names of the predefined resources. # # @return [Array<Symbol>] # The names of the predefined resources. # + # @since 0.4.0 + # + # @api public + # + def predefined + predefined_attributes.keys + end + + # + # @see #predefined + # + # @deprecated Will be removed in 1.0.0. + # # @since 0.2.1 # def predefined_names - predefined_attributes.keys + predefined end # - # Finds or auto-creates the pre-defined resource with the given name. + # Determines if a resource was predefined. # # @param [Symbol, String] name + # The name of the predefined resource to search for. + # + # @return [Boolean] + # Specifies whether the resource was predefined. + # + # @since 0.4.0 + # + # @api public + # + def predefined?(name) + predefined_attributes.has_key?(name.to_sym) + end + + # + # Finds or auto-creates the pre-defined resource with the given + # name. + # + # @param [Symbol, String] name # The name of the pre-defined resource. # + # @param [Hash{Symbol => Object}] extra_attributes + # Additional attributes to add to the predefined resource. + # # @return [DataMapper::Resource] # The pre-defined resource. # # @raise [UnknownResource] - # Indicates that there are no predefined attributes for the resource - # with the given name. + # Indicates that there are no predefined attributes for the + # resource with the given name. # # @since 0.2.1 # + # @api public + # def predefined_resource(name) name = name.to_sym - attributes = self.predefined_attributes[name] - unless attributes - raise(UnknownResource,"The resource '#{name}' was not predefined",caller) + unless predefined?(name) + raise(UnknownResource,"The resource '#{name}' was not predefined") end - self.first_or_create(attributes) + return first_or_create(predefined_attributes[name]) end # # Finds or auto-creates the predefined resource which shares the # given attributes. # - # @param [Hash{Symbol => Object}] desired_attributes + # @param [Hash{Symbol => Object}] conditions + # Query conditions. + # + # @param [Hash{Symbol => Object}] attributes # The attribute names and values that the predefined resource # should shared. # - # @return [DataMapper::Resource] + # @return [DataMapper::Resource, nil] # The predefined resource. # + # @since 0.4.0 + # + # @api public + # + def first_or_predefined(conditions={},attributes=conditions) + if (resource = first(conditions)) + return resource + end + + # if the resource wasn't found, search for matching + # predefined attributes + attributes = predefined_attributes.values.find do |attrs| + attrs.all? do |name,value| + attributes.has_key?(name) && (attributes[name] == value) + end + end + + # create the resource using the predefined attributes + create(attributes) if attributes + end + + # # @raise [UnknownResource] # Could not find a predefined resource that shared all of the # desired attributes. # + # @deprecated + # Will be removed in 1.0.0. Use {#first_or_predefined} instead. + # # @since 0.2.1 # - def predefined_resource_with(desired_attributes={}) - self.predefined_attributes.each do |name,attributes| - shares_attributes = desired_attributes.all? do |key,value| - key = key.to_sym - - attributes.has_key?(key) && (attributes[key] == value) - end - - return predefined_resource(name) if shares_attributes + # @api public + # + def predefined_resource_with(query={}) + unless (resource = first_or_predefined(query)) + # no pre-existing or predefined resource matching the query + raise(UnknownResource,"Could not find a predefined resource which shared the given attributes") end - raise(UnknownResource,"Could not find a predefined resource which shared the given attributes",caller) + return resource end - protected - # - # All pre-defined resources of the model. + # Creates the predefined resources. # - # @return [Hash{Symbol => Hash}] - # The Hash of pre-defined resources and their attributes. + # @param [Symbol] repository_name + # The repository to perform the upgrade within. # - def predefined_attributes - @predefined_attributes ||= {} + # @since 0.4.0 + # + # @api public + # + def predefine!(repository_name=self.repository_name) + DataMapper.repository(repository_name) do + predefined_attributes.each_value do |attributes| + first_or_create(attributes) + end + end end + protected + # # Defines a new pre-defined resource for the model. # # @param [Symbol, String] name # The name of the pre-defined resource. # # @param [Hash] attributes # The attributes for the pre-defined resource. # # @return [Hash] - # The attributes that will be assigned to the pre-defined resource. + # The attributes that will be assigned to the pre-defined + # resource. # + # @api public + # def predefine(name,attributes={}) - name = name.to_s + name = name.to_sym if attributes.empty? - raise(ArgumentError,"Cannot predefine a resource with no attributes",caller) + raise(ArgumentError,"Cannot predefine a resource with no attributes") end - self.predefined_attributes[name.to_sym] = attributes + predefined_attributes[name] = attributes class_eval %{ class << self - define_method(#{name.dump}) do - predefined_resource(#{name.dump}) + define_method(#{name.inspect}) do + predefined_resource(#{name.inspect}) end end } - attributes + return attributes end end # ClassMethods end # Predefined end # Is end # DataMapper