lib/ronin/ui/cli/model_command.rb in ronin-1.0.0 vs lib/ronin/ui/cli/model_command.rb in ronin-1.1.0.rc1

- old
+ new

@@ -18,58 +18,73 @@ # require 'ronin/ui/cli/command' require 'ronin/database' -require 'set' - module Ronin module UI module CLI # - # A base-command for querying and exporting {Model}s. + # A base-command for querying {Model}s. # class ModelCommand < Command - class_option :csv, :type => :boolean - class_option :xml, :type => :boolean - class_option :yaml, :type => :boolean - class_option :json, :type => :boolean + class_option :database, :type => :string, + :aliases => '-D' # # The model to query. # # @return [DataMapper::Resource] # The model that will be queried. # - # @since 1.0.0 + # @since 1.1.0 # - def self.model - @model + # @api semipublic + # + def self.query_model + @query_model ||= if self.superclass < ModelCommand + self.superclass.query_model + end end # # The query options for the command. # - # @return [Set] + # @return [Array<Symbol>] # The query options and their query method names. # # @since 1.0.0 # + # @api semipublic + # def self.query_options - @query_options ||= Set[] + @query_options ||= [] end # - # Default method performs the query and prints the found resources. + # Iterates over the query options for the command. # - # @since 1.0.0 + # @yield [name] + # The given block will be passed the names of the query options. # - def execute - Database.setup + # @yieldparam [Symbol] name + # The name of a query option. + # + # @return [Enumerator] + # If no block is given, an Enumerator object will be returned. + # + # @since 1.1.0 + # + def self.each_query_option(&block) + return enum_for(:each_query_option) unless block - print_resources(query) + self.class.ancestors.each do |ancestor| + if ancestor < ModelCommand + ancestor.query_options.each(&block) + end + end end protected # @@ -79,14 +94,16 @@ # The model class. # # @return [DataMapper::Resource] # The model that will be queried. # - # @since 1.0.0 + # @since 1.1.0 # - def self.model=(model) - @model = model + # @api semipublic + # + def self.model(model) + @query_model = model end # # Defines a query option for the command. # @@ -96,111 +113,79 @@ # @param [Hash] options # Additional options. # # @since 1.0.0 # + # @api semipublic + # def self.query_option(name,options={}) query_options << name class_option(name,options) end # - # Invokes a query method on a query. + # Sets up the {Database}. # - # @param [DataMapper::Collection] query - # The query. + # @since 1.1.0 # - # @param [Symbol] name - # The method name to call. + # @api semipublic # - # @param [Array] arguments - # Additional arguments to pass to the query method. - # - # @return [DataMapper::Collection] - # The modified query. - # - # @since 1.0.0 - # - def query_method(query,name,arguments=[]) - query_method = begin - query.model.method(name) - rescue NameError - raise("Undefined query method #{query.model}.#{name}") - end + def setup + super - case query_method.arity - when 0 - query.send(name) - when 1 - query.send(name,arguments) - else - query.send(name,*arguments) + if self.options[:database] + Database.repositories[:default] = options[:database] end + + Database.setup end # # Builds a new query using the options of the command. # - # @yield [query] - # If a block is given, it will be passed the new query. - # - # @yieldparam [DataMapper::Collection] query - # The new query. - # # @return [DataMapper::Collection] # The new query. # + # @raise [RuntimeError] + # The query option does not map to a query-method or property + # defined in the Model. + # # @since 1.0.0 # + # @api semipublic + # def query - new_query = self.class.model.all - - self.class.ancestors.each do |ancestor| - if ancestor < ModelCommand - ancestor.query_options.each do |name| - unless options[name].nil? - new_query = query_method(new_query,name,options[name]) - end - end - end + unless self.class.query_model + raise("query model not defined for #{self.class}") end - new_query = yield(new_query) if block_given? - return new_query - end + query = self.class.query_model.all - # - # Default method which will print every queried resource. - # - # @param [DataMapper::Resource] resource - # A queried resource from the Database. - # - # @since 1.0.0 - # - def print_resource(resource) - puts resource - end + self.class.each_query_option do |name| + value = options[name] - # - # Prints multiple resources. - # - # @param [DataMapper::Collection, Array<DataMapper::Resource>] resources - # The query to print. - # - # @since 1.0.0 - # - def print_resources(resources) - if options.csv? - print resources.to_csv - elsif options.xml? - print resources.to_xml - elsif options.yaml? - print resources.to_yaml - elsif options.json? - print resources.to_json - else - resources.each { |resource| print_resource(resource) } + # skip unset options + next if value.nil? + + if query_model.properties.named?(name) + query = query.all(name => value) + elsif query_model.respond_to?(name) + query_method = query_model.method(name) + + query = case query_method.arity + when 0 + query.send(name) + when 1 + query.send(name,value) + else + query.send(name,*value) + end + else + raise("unknown query method or property #{name} for #{query_model}") + end end + + return query end end end end