Class: Rutty::Nodes

Inherits:
Array
  • Object
show all
Defined in:
lib/rutty/nodes.rb

Overview

Simple container class for 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

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.load_config(dir) ⇒ Rutty::Nodes

Loads the users’s node data from the yaml file contained in the specified dir.

Parameters:

Returns:

See Also:

Since:

  • 2.1.0



20
21
22
23
# 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

Instance Method Details

#filter(opts = {}) ⇒ Rutty::Nodes

Filters out the Rutty::Node objects contained in this instance based on user-defined criteria.

Parameters:

  • opts (Hash, #[]) (defaults to: {})

    The filter criteria

Options Hash (opts):

  • :keypath (String) — default: nil

    The path to the private key

  • :user (String) — default: nil

    The user to login as

  • :port (Integer) — default: nil

    The port to connect to

  • :tags (String) — default: nil

    The tags to filter by

Returns:

Since:

  • 2.1.0



35
36
37
38
39
40
41
42
43
44
45
46
# 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

#filter!(opts = {}) ⇒ Rutty::Nodes

Same as #filter, but destructive on this object instead of a duplicate.

Parameters:

  • opts (Hash, #[]) (defaults to: {})

    The filter criteria

Options Hash (opts):

  • :keypath (String) — default: nil

    The path to the private key

  • :user (String) — default: nil

    The user to login as

  • :port (Integer) — default: nil

    The port to connect to

  • :tags (String) — default: nil

    The tags to filter by

Returns:

  • (Rutty::Nodes)

    This object with the requested nodes filtered out.

Since:

  • 2.1.0



54
55
56
57
58
59
60
61
62
63
# 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

#get_tag_query_filter(query_str) ⇒ Proc (private)

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.

Parameters:

  • query_str (String)

    The string passed in by the user via the --tags option

Returns:

  • (Proc)

    The generated filter Proc

See Also:

Since:

  • 2.3.0



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# 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

#recursive_build_query_proc_string(elems, str = '') ⇒ String (private)

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.

Parameters:

  • elems (Array<Treetop::Runtime::SyntaxNode>)

    A multidimensional array ultimately consisting of Treetop SyntaxNodes or children thereof.

  • str (String) (defaults to: '')

    The string to build on. Passed around over recursions.

Returns:

  • (String)

    The completed string to evaluate into a Proc.

See Also:

Since:

  • 2.3.0



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# 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

#write_config(dir) ⇒ void

Writes the updated nodes config back into the nodes.yaml file in the specified dir.

Parameters:

See Also:

Since:

  • 2.1.0



70
71
72
73
74
# 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