class Rutty::Nodes
Simple container class for {Rutty::Node} instances. Contains methods to load node data from file, write data back to the file, and filter nodes based on user-supplied criteria.
@author Josh Lindsey @since 2.1.0
Public Class Methods
Loads the users’s node data from the yaml file contained in the specified dir.
@param [String] dir The directory to look in for the filename specified by {Rutty::Consts::NODES_CONF_FILE} @return [Rutty::Nodes] The filled instance of {Rutty::Node} objects @see Rutty::Consts::NODES_CONF_FILE
# File lib/rutty/nodes.rb, line 20 def load_config dir require 'yaml' Rutty::Nodes.new YAML.load(File.open(File.join(dir, Rutty::Consts::NODES_CONF_FILE)).read) end
Public Instance Methods
Filters out the {Rutty::Node} objects contained in this instance based on user-defined criteria.
@param [Hash, []] opts The filter criteria @option opts [String] :keypath (nil) The path to the private key @option opts [String] :user (nil) The user to login as @option opts [Integer] :port (nil) The port to connect to @option opts [String] :tags (nil) The tags to filter by @return [Rutty::Nodes] A duplicate of this object, but containing the {Rutty::Node} objects after filtering.
# File lib/rutty/nodes.rb, line 35 def filter opts = {} return self if opts.all ary = self.dup ary.delete_if { |n| n.keypath != opts.keypath } unless opts.keypath.nil? ary.delete_if { |n| n.user != opts.user } unless opts.user.nil? ary.delete_if { |n| n.port != opts.port } unless opts.port.nil? ary.delete_if &get_tag_query_filter(opts.tags) unless opts.tags.nil? ary end
Same as {#filter}, but destructive on this object instead of a duplicate.
@param (see filter
) @option (see filter
) @return [Rutty::Nodes] This object with the requested nodes filtered out.
# File lib/rutty/nodes.rb, line 54 def filter! opts = {} return self if opts.all self.delete_if { |n| n.keypath != opts.keypath } unless opts.keypath.nil? self.delete_if { |n| n.user != opts.user } unless opts.user.nil? self.delete_if { |n| n.port != opts.port } unless opts.port.nil? self.delete_if &get_tag_query_filter(opts.tags) unless opts.tags.nil? self end
Writes the updated nodes config back into the nodes.yaml file in the specified dir.
@param (see Rutty::Nodes.load_config
) @see (see Rutty::Nodes.load_config
)
# File lib/rutty/nodes.rb, line 70 def write_config dir File.open(File.join(dir, Rutty::Consts::NODES_CONF_FILE), 'w') do |f| YAML.dump(self, f) end end
Private Instance Methods
Builds and returns a Proc
for {#filter}. The Proc should be passed a {Rutty::Node} object when called. The Proc calls {Rutty::Node#has_tag?} on the passed in object to determine tag inclusion.
In other words, the Proc returned by this should be suitable for passing to Array#reject!, as that’s what {#filter} calls.
@param [String] query_str The string passed in by the user via the --tags
option @return [Proc] The generated filter Proc
@see recursive_build_query_proc_string
@see Rutty::Nodes#filter
@since 2.3.0
# File lib/rutty/nodes.rb, line 92 def get_tag_query_filter query_str require 'rutty/proc_classes' filter = nil if query_str =~ /^[A-Za-z_-]+$/ # Single tag query, no need to fire up the parser filter = Procs::SingleTagQuery.new { |n| !n.has_tag? query_str } elsif query_str =~ /^(?:[A-Za-z_-]+,?)+$/ # Old-style comma-separated tag query. Still no # need to fire up the parser, just additively compare. tags = query_str.split(',') filter = Procs::MultipleTagQuery.new { |n| (n.tags & tags).empty? } else # New sql-like tag query. Need the parser for this. require 'treetop' require 'rutty/treetop/syntax_nodes' require 'rutty/treetop/tag_query' parser = TagQueryGrammarParser.new parsed_syntax_tree = parser.parse(query_str) raise InvalidTagQueryString.new "Unable to parse tag query string" if parsed_syntax_tree.nil? proc_str = recursive_build_query_proc_string parsed_syntax_tree.elements proc_str = proc_str.rstrip << ') }' filter = eval(proc_str) end filter end
Builds a string to be eval
‘d into a Proc by {#get_tag_query_filter}. Recursively walks a Treetop parsed syntax tree, building the string as it goes. The string is not actually evaluated into a Proc object in this method; that happens in {#get_tag_query_filter}.
@param [Array<Treetop::Runtime::SyntaxNode>] elems A multidimensional array ultimately
consisting of Treetop SyntaxNodes or children thereof.
@param [String] str The string to build on. Passed around over recursions. @return [String] The completed string to evaluate into a Proc.
@see get_tag_query_filter
@since 2.3.0
# File lib/rutty/nodes.rb, line 139 def recursive_build_query_proc_string elems, str = '' return str if elems.nil? or elems.empty? str = 'Procs::SqlLikeTagQuery.new { |n| !(' if str.empty? elem = elems.shift case elem.class.to_s when 'TagQueryGrammar::Tag' str << "n.has_tag?('#{elem.text_value}') " when 'TagQueryGrammar::AndLiteral' str << "&& " when 'TagQueryGrammar::OrLiteral' str << "|| " when 'TagQueryGrammar::GroupStart' str << '(' when 'TagQueryGrammar::GroupEnd' str.rstrip! str << ')' when 'TagQueryGrammar::QueryGroup' str = recursive_build_query_proc_string elem.elements, str # For some reason, Treetop won't let me assign a class to the "query" rule, # so it defaults to this class. This should be the only parsed rule that evaluates # to this generic class. when 'Treetop::Runtime::SyntaxNode' str = recursive_build_query_proc_string elem.elements, str end recursive_build_query_proc_string elems, str end