mongo3 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -29,11 +29,16 @@
29
29
 
30
30
  == ROAD MAP:
31
31
 
32
- * Provide support for db authentication
33
- * Ability to drilldown in collections and query for content
32
+ * Provide support for db authentication [done]
33
+ * Ability to drilldown in collections and query for content [done]
34
34
  * CRUD on dbs, collections, indexes, users
35
35
  * Support for managing shards and replication
36
36
 
37
+ == DEPENDENCIES
38
+
39
+ * mongo + mongo_ext
40
+ * agnostic-will_paginate
41
+
37
42
  == INSTALL:
38
43
 
39
44
  sudo gem install mongo3
@@ -53,8 +58,10 @@
53
58
  port: 27017
54
59
 
55
60
  beta:
56
- host: beta_host_name
57
- port: 27017
61
+ host: beta_host_name
62
+ port: 27017
63
+ user: bobo
64
+ password: secret
58
65
 
59
66
  === Launch It!
60
67
 
data/Rakefile CHANGED
@@ -29,3 +29,9 @@ PROJ.rcov.opts = ["--sort", "coverage", "-T"]
29
29
  PROJ.ignore_file = "*.log"
30
30
  PROJ.spec.opts << '--color'
31
31
  PROJ.rdoc.include = %w[.rb]
32
+
33
+ # Dependencies
34
+ depend_on "mongo" , ">= 0.18.1"
35
+ depend_on "mongo_ext" , ">= 0.18.1"
36
+ depend_on "agnostic-will_paginate", ">= 3.0.0"
37
+
data/config/mongo3.yml CHANGED
@@ -1,12 +1,12 @@
1
1
  development:
2
- :host: localhost
3
- :port: 27017
2
+ host: localhost
3
+ port: 27017
4
4
 
5
5
  beta:
6
- :host: dev8
7
- :port: 27018
8
- :user: "blee"
9
- :password: "fred"
6
+ host: dev8
7
+ port: 27018
8
+ user: "blee"
9
+ password: "fred"
10
10
 
11
11
  # production:
12
12
  # :host: dev8
@@ -1,7 +1,58 @@
1
+ require 'json'
2
+
1
3
  module Collections
2
4
 
3
- get "/cltns" do
4
- puts "Cltns"
5
+ # ---------------------------------------------------------------------------
6
+ # Paginate on a collection
7
+ get "/cltn/:page" do
8
+ @back_url = "/explore/back"
9
+ @page = params[:page].to_i || 1
10
+ @title = title_for( session[:path_names] )
11
+
12
+ load_cltn( params[:page].to_i )
13
+ erb :cltn_list
14
+ end
15
+
16
+ # ---------------------------------------------------------------------------
17
+ post "/cltn_refresh/:page" do
18
+ selected_cols = params[:cols].keys.sort
19
+ session[:selected_cols] = selected_cols
20
+
21
+ load_cltn( params[:page].to_i )
22
+
23
+ erb :cltn_update_js, :layout => false
5
24
  end
6
25
 
26
+ # ---------------------------------------------------------------------------
27
+ # BOZO !! Validation....
28
+ post "/cltn_search" do
29
+ json = params[:search].gsub( /'/, "\"" )
30
+ if json.empty?
31
+ @query = {}
32
+ @sort = {}
33
+ else
34
+ tokens = json.split( "|" )
35
+ @query = JSON.parse( tokens.shift )
36
+ @sort = tokens.empty? ? [] : JSON.parse( tokens.first )
37
+ end
38
+ session[:query_params] = [@query, @sort]
39
+
40
+ load_cltn
41
+ erb :cltn_update_js, :layout => false
42
+ end
43
+
44
+ # ===========================================================================
45
+ helpers do
46
+ def load_cltn( page=1 )
47
+ query_params = session[:query_params] || [{},[]]
48
+ @query = [query_params.first.to_json, query_params.last.to_json].join(",")
49
+ @page = page
50
+ path_names = session[:path_names]
51
+ path_ids = session[:path_ids]
52
+
53
+ @cltn = options.connection.paginate_cltn( path_names, query_params, @page, 15 )
54
+ @cols = @cltn.first.keys.sort
55
+ @selected_cols = session[:selected_cols] || @cols[0...5]
56
+ end
57
+ end
7
58
  end
@@ -1,7 +1,16 @@
1
1
  module Databases
2
2
 
3
- get "/dbs" do
4
- puts "Dbs"
5
- end
3
+ # ---------------------------------------------------------------------------
4
+ get "/db/:page" do
5
+ page = params[:page].to_i || 1
6
+ path_ids = session[:path_ids]
7
+ path_names = session[:path_names]
8
+
9
+ @cltns = options.connection.paginate_db( path_names, page, 10 )
10
+ @title = title_for( path_names )
11
+ @back_url = "/explore/back"
12
+
13
+ erb :db_list
14
+ end
6
15
 
7
16
  end
@@ -4,27 +4,56 @@ module Explore
4
4
  get '/explore' do
5
5
  reset_crumbs!
6
6
  @root = options.connection.build_tree
7
+ Mongo3::Node.dump( @root )
7
8
  erb :explore
8
9
  end
9
10
 
10
11
  # -----------------------------------------------------------------------------
11
- get '/explore/show/:path/:crumbs' do
12
- path = params[:path]
13
- crumbs = params[:crumbs]
12
+ get '/explore/back' do
13
+ session[:selected_cols] = nil
14
+ session[:query_params] = nil
15
+
16
+ back_paths!
17
+ path_ids = session[:path_ids]
18
+ path_names = session[:path_names]
14
19
 
15
- @info = options.connection.show( path, crumbs )
20
+ reset_crumbs!
21
+ crumbs_from_path( path_ids, path_names )
22
+
23
+ @root = options.connection.build_partial_tree( path_ids, path_names )
24
+ # Mongo3::Node.dump( @root )
25
+
26
+ # need to adjust crumbs in case something got blown...
27
+ @center = path_ids.split( "|" ).last
28
+
29
+ erb :explore
30
+ end
31
+
32
+ # -----------------------------------------------------------------------------
33
+ get '/explore/show/:path_ids/:path_names' do
34
+ path_ids = params[:path_ids]
35
+ path_names = params[:path_names]
36
+
37
+ @info = options.connection.show( path_names )
38
+
39
+ session[:path_ids] = path_ids
40
+ session[:path_names] = path_names
16
41
 
17
42
  partial :info
18
43
  end
19
44
 
20
45
  # -----------------------------------------------------------------------------
21
- get '/explore/more_data/:path/:crumbs/*' do
22
- path = params[:path]
23
- crumbs = params[:crumbs]
46
+ get '/explore/more_data/:path_ids/:path_names/*' do
47
+ path_ids = params[:path_ids]
48
+ path_names = params[:path_names]
49
+
50
+ session[:path_ids] = path_ids
51
+ session[:path_names] = path_names
24
52
 
25
- crumbs_from_path( path, crumbs )
53
+ crumbs_from_path( path_ids, path_names )
26
54
 
27
- @sub_tree = options.connection.build_sub_tree( path, crumbs )
55
+ @sub_tree = options.connection.build_sub_tree( path_ids, path_names )
56
+ # Mongo3::Node.dump_adj( @sub_tree )
28
57
  @node_id = @sub_tree.first[:id]
29
58
 
30
59
  erb :more_data_js, :layout => false
@@ -38,8 +67,10 @@ module Explore
38
67
 
39
68
  # -----------------------------------------------------------------------------
40
69
  get '/explore/center/:node_id' do
41
- @node_id = params[:node_id]
70
+ @node_id = params[:node_id]
71
+
42
72
  pop_crumb!( @node_id )
73
+
43
74
  erb :center_js, :layout => false
44
75
  end
45
76
 
@@ -0,0 +1,19 @@
1
+ require 'will_paginate/view_helpers/base'
2
+ require 'will_paginate/view_helpers/link_renderer'
3
+
4
+ module WillPaginate::ViewHelpers
5
+ class LinkRenderer
6
+ def url( page )
7
+ "#{@options[:params][:url]}/#{page}"
8
+ end
9
+ end
10
+ end
11
+
12
+
13
+ module CollectionHelper
14
+
15
+ helpers do
16
+ include WillPaginate::ViewHelpers::Base
17
+ end
18
+
19
+ end
@@ -1,23 +1,23 @@
1
1
  module CrumbHelper
2
2
 
3
3
  helpers do
4
- def crumbs_from_path( path, crumbs )
5
- crumb_tokens = crumbs.split( "|" )
6
- path_tokens = path.split( "|" )
4
+ def crumbs_from_path( path_ids, path_names )
5
+ path_id_tokens = path_ids.split( "|" )
6
+ path_name_tokens = path_names.split( "|" )
7
7
 
8
8
  @crumbs = []
9
9
  count = 0
10
- crumb_tokens.each do |crumb|
11
- @crumbs << [crumb, "/explore/center/#{path_tokens[count]}"]
10
+ path_name_tokens.each do |crumb|
11
+ @crumbs << [crumb, "/explore/center/#{path_id_tokens[count]}"]
12
12
  count += 1
13
13
  end
14
14
  session[:crumbs] = @crumbs
15
15
  end
16
16
 
17
17
  def pop_crumb!( node_id )
18
+ path = "/explore/center/#{node_id}"
18
19
  level = 0
19
20
  range = nil
20
- path = "/explore/center/#{node_id}"
21
21
  @crumbs.each do |pair|
22
22
  if pair.last == path
23
23
  range = level
@@ -36,7 +36,7 @@ module CrumbHelper
36
36
 
37
37
  def add_crumb( title, url )
38
38
  titles = @crumbs.map{ |p| p.first }
39
- unless titles.include?( title )
39
+ unless titles.include?( title )
40
40
  @crumbs.pop if @crumbs.size == 3
41
41
  @crumbs << [title, url]
42
42
  session[:crumbs] = @crumbs
@@ -13,6 +13,29 @@ module MainHelper
13
13
 
14
14
  helpers do
15
15
 
16
+ def back_paths!
17
+ path_ids = session[:path_ids]
18
+ path_names = session[:path_names]
19
+ new_path_ids = path_ids.split( "|" )
20
+ new_path_ids.pop
21
+ session[:path_ids] = new_path_ids.join( "|" )
22
+
23
+ new_path_names = path_names.split( "|" )
24
+ new_path_names.pop
25
+ session[:path_names] = new_path_names.join( "|" )
26
+ end
27
+
28
+ def title_for( path_names )
29
+ tokens = path_names.split( "|" )
30
+ buff = case tokens.length
31
+ when 2 : "Environment"
32
+ when 3 : "Database"
33
+ else "Collection"
34
+ end
35
+
36
+ buff += " <em>#{tokens.last}</em>"
37
+ end
38
+
16
39
  def display_info( info )
17
40
  return info if info.is_a?( String )
18
41
  if info.is_a?( Hash )
data/lib/main.rb CHANGED
@@ -3,6 +3,8 @@ require 'sinatra'
3
3
  require 'forwardable'
4
4
  require File.join( File.dirname(__FILE__), 'mongo3.rb' )
5
5
  require 'mongo'
6
+ gem 'agnostic-will_paginate'
7
+ require 'will_paginate'
6
8
 
7
9
  set :public, File.join( File.dirname(__FILE__), %w[public] )
8
10
  set :views , File.join( File.dirname(__FILE__), %w[views] )
@@ -21,9 +23,9 @@ end
21
23
  # Before filters
22
24
  before do
23
25
  unless request.path =~ /\.[css gif png js]/
24
- @crumbs = session[:crumbs]
26
+ @crumbs = session[:crumbs]
25
27
  unless @crumbs
26
- @crumbs = [ ['HOME', '/center'] ]
28
+ @crumbs = [ ['home', '/explore/center/home'] ]
27
29
  session[:crumbs] = @crumbs
28
30
  end
29
31
  end
@@ -4,25 +4,14 @@ module Mongo3
4
4
  def initialize( config_file )
5
5
  @config_file = config_file
6
6
  end
7
-
8
- # Connects to mongo given an environment
9
- # BOZO !! Auth...
10
- # TODO - Need to close out connection via block
11
- def connect_for( env, &block )
12
- info = landscape[env]
13
- puts ">>> Connecting for #{env} -- #{info[:host]}-#{info[:port]}"
14
- con = Mongo::Connection.new( info[:host], info[:port] )
15
- yield con
16
- con.close()
17
- end
18
-
19
- def show( path, crumbs )
20
- path_tokens = path.split( "|" )
21
- crumb_tokens = crumbs.split( "|" )
22
- info = OrderedHash.new
23
- env = path_tokens[1]
7
+
8
+ def show( path_names )
9
+ path_name_tokens = path_names.split( "|" )
10
+ info = OrderedHash.new
11
+ env = path_name_tokens[1]
24
12
 
25
- if path_tokens.size == 2
13
+ info[:title] = path_name_tokens.last
14
+ if path_name_tokens.size == 2
26
15
  connect_for( env ) do |con|
27
16
  info[:name] = env
28
17
  info[:host] = con.host
@@ -31,62 +20,89 @@ module Mongo3
31
20
  con.database_info.sort { |a,b| b[1] <=> a[1] }.each { |e| info[:databases][e[0]] = to_mb( e[1] ) }
32
21
  info[:server] = con.server_info
33
22
  end
34
- elsif path_tokens.size == 3
35
- db_name = crumb_tokens.pop
36
- connect_for( env ) do |con|
23
+ elsif path_name_tokens.size == 3
24
+ db_name = path_name_tokens.pop
25
+ connect_for( env ) do |con|
37
26
  db = con.db( db_name )
38
- info[:size] = to_mb( con.database_info[db_name] )
39
- info[:node] = db.nodes
27
+ info[:edit] = "/db/1"
28
+ info[:size] = to_mb( con.database_info[db_name] )
29
+ info[:node] = db.nodes
40
30
  info[:collections] = db.collection_names.size
41
31
  info[:error] = db.error
42
32
  info[:last_status] = db.last_status
43
33
  end
44
- elsif path_tokens.size == 4
45
- cltn_name = crumb_tokens.pop
46
- db_name = crumb_tokens.pop
34
+ elsif path_name_tokens.size == 4
35
+ cltn_name = path_name_tokens.pop
36
+ db_name = path_name_tokens.pop
47
37
  connect_for( env ) do |con|
48
- db = con.db( db_name )
49
- cltn = db[cltn_name]
50
- info[:size] = cltn.count
38
+ db = con.db( db_name )
39
+ cltn = db[cltn_name]
40
+ indexes = db.index_information( cltn_name )
51
41
 
52
- indexes = db.index_information( cltn_name )
53
- info[:indexes] = format_indexes( db.index_information( cltn_name ) ) if indexes and !indexes.empty?
42
+ info[:edit] = "/cltn/1"
43
+ info[:size] = cltn.count
44
+ info[:indexes] = format_indexes( indexes ) if indexes and !indexes.empty?
54
45
  end
55
- end
56
-
46
+ end
57
47
  info
58
48
  end
49
+
50
+ def paginate_db( path_names, page=1, per_page=10 )
51
+ path_name_tokens = path_names.split( "|" )
52
+ env = path_name_tokens[1]
53
+ list = nil
54
+ connect_for( env ) do |con|
55
+ db_name = path_name_tokens.pop
56
+ db = con.db( db_name )
57
+ cltn = db.collection_names.sort
59
58
 
60
- def format_indexes( indexes )
61
- formatted = {}
62
- indexes.each_pair do |key, values|
63
- buff = []
64
- values.each do |pair|
65
- buff << "#{pair.first} [#{pair.last}]"
66
- end
67
- formatted[key] = buff
68
- end
69
- formatted
59
+ list = WillPaginate::Collection.create( page, per_page, cltn.size ) do |pager|
60
+ offset = (page-1)*per_page
61
+ names = cltn[offset..(offset+per_page)]
62
+ cltns = []
63
+ names.each do |name|
64
+ list = db[name]
65
+ row = OrderedHash.new
66
+ row[:name] = name
67
+ row[:count] = list.count
68
+ cltns << row
69
+ end
70
+ pager.replace( cltns )
71
+ end
72
+ end
73
+ list
70
74
  end
71
-
75
+
76
+ def paginate_cltn( path_names, query_params=[{},[]], page=1, per_page=10 )
77
+ path_name_tokens = path_names.split( "|" )
78
+ env = path_name_tokens[1]
79
+ list = nil
80
+ connect_for( env ) do |con|
81
+ cltn_name = path_name_tokens.pop
82
+ db_name = path_name_tokens.pop
83
+ db = con.db( db_name )
84
+ cltn = db[cltn_name]
85
+
86
+ list = WillPaginate::Collection.create( page, per_page, cltn.count ) do |pager|
87
+ offset = (page-1)*per_page
88
+ sort = query_params.last.empty? ? [ ['_id', Mongo::DESCENDING] ] : query_params.last
89
+ pager.replace( cltn.find( query_params.first,
90
+ :sort => sort,
91
+ :skip => offset,
92
+ :limit => per_page ).to_a)
93
+ end
94
+ end
95
+ list
96
+ end
97
+
72
98
  # Fetch the environment landscape from the config file
73
99
  def landscape
74
100
  config
75
101
  end
76
102
 
77
- # db request occurs within dist 2
78
- def db_request?( path )
79
- path.size == 2
80
- end
81
-
82
- # cltn request occurs within dist 3
83
- def cltn_request?( path )
84
- path.size == 3
85
- end
86
-
87
103
  # Build environment tree
88
104
  def build_tree
89
- root = Node.new( "home", "home", :path => 'home', :crumbs => 'home' )
105
+ root = Node.make_node( "home" )
90
106
 
91
107
  # iterate thru envs
92
108
  id = 1
@@ -97,39 +113,77 @@ module Mongo3
97
113
  end
98
114
  root
99
115
  end
116
+
117
+ # Build environment tree
118
+ def build_partial_tree( path_ids, path_names )
119
+ path_id_tokens = path_ids.split( "|" )
120
+ path_name_tokens = path_names.split( "|" )
121
+ bm_env = path_name_tokens[1]
122
+ bm_cltn = path_name_tokens.pop if path_name_tokens.size == 4
123
+ bm_db = path_name_tokens.pop if path_name_tokens.size == 3
124
+
125
+ root = Node.make_node( "home" )
126
+
127
+ # iterate thru envs
128
+ config.each_pair do |env, info|
129
+ node = Node.new( env, env, :dyna => true )
130
+ root << node
131
+ if node.name == bm_env
132
+ connect_for( env ) do |con|
133
+ count = 0
134
+ data = { :dyna => true }
135
+ con.database_names.each do |db_name|
136
+ db = con.db( db_name, :strict => true )
137
+ cltns = db.collection_names.size
138
+ db_node = Node.new( "#{env}_#{count}", "#{db_name}(#{cltns})", data.clone )
139
+ node << db_node
140
+ count += 1
141
+ if bm_db and db_node.name =~ /^#{bm_db}/
142
+ cltn_count = 0
143
+ data = { :dyna => false }
144
+ db.collection_names.each do |cltn_name|
145
+ size = db[cltn_name].count
146
+ cltn_node = Node.new( "#{db_name}_#{cltn_count}", "#{cltn_name}(#{size})", data.clone )
147
+ db_node << cltn_node
148
+ cltn_count += 1
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ root
156
+ end
100
157
 
101
158
  # Build an appropriate subtree based on requested item
102
- def build_sub_tree( path, crumbs )
103
- path_tokens = path.split( "|" )
104
- crumb_tokens = crumbs.split( "|" )
105
- parent_id = path_tokens.last
106
- db_name = crumb_tokens.last
107
-
108
- if db_request?( path_tokens )
109
- sub_tree = build_db_tree( parent_id, db_name )
159
+ def build_sub_tree( path_ids, path_names )
160
+ path_id_tokens = path_ids.split( "|" )
161
+ path_name_tokens = path_names.split( "|" )
162
+ env = path_name_tokens[1]
163
+ parent_id = path_id_tokens.last
164
+
165
+ if db_request?( path_name_tokens )
166
+ sub_tree = build_db_tree( parent_id, env )
110
167
  else
111
- env = crumb_tokens[1]
168
+ db_name = path_name_tokens.last
112
169
  sub_tree = build_cltn_tree( parent_id, env, db_name )
113
170
  end
114
171
  sub_tree.to_adjacencies
115
172
  end
116
-
117
-
173
+
118
174
  # Connects to host and spews out all available dbs
119
175
  # BOZO !! Need to deal with Auth?
120
- def build_db_tree( parent_id, env )
176
+ def build_db_tree( parent_id, env )
121
177
  sub_root = nil
122
178
  connect_for( env ) do |con|
123
- root = Node.new( "home", "home" )
179
+ root = Node.make_node( "home" )
124
180
  sub_root = Node.new( parent_id, env )
125
181
 
126
182
  root << sub_root
127
183
 
128
184
  count = 0
129
185
  data = { :dyna => true }
130
- # excludes = %w[admin local]
131
186
  con.database_names.each do |db_name|
132
- # next if excludes.include?( db_name )
133
187
  db = con.db( db_name, :strict => true )
134
188
  cltns = db.collection_names.size
135
189
  node = Node.new( "#{env}_#{count}", "#{db_name}(#{cltns})", data.clone )
@@ -145,17 +199,15 @@ module Mongo3
145
199
  sub_root = nil
146
200
  connect_for( env ) do |con|
147
201
  db = con.db( db_name )
148
- root = Node.new( "home", "home" )
149
- env_node = Node.new( env, env )
202
+ root = Node.make_node( "home" )
203
+ env_node = Node.make_node( env )
150
204
  sub_root = Node.new( parent_id, db_name )
151
205
  root << env_node
152
206
  env_node << sub_root
153
207
 
154
208
  count = 0
155
- # excludes = %w[system.indexes]
156
209
  data = { :dyna => false }
157
210
  db.collection_names.each do |cltn_name|
158
- # next if excludes.include?( cltn_name )
159
211
  size = db[cltn_name].count
160
212
  node = Node.new( "#{db_name}_#{count}", "#{cltn_name}(#{size})", data.clone )
161
213
  sub_root << node
@@ -164,9 +216,46 @@ module Mongo3
164
216
  end
165
217
  sub_root
166
218
  end
167
-
219
+
168
220
  # =========================================================================
169
221
  private
222
+
223
+ # Connects to mongo given an environment
224
+ # BOZO !! Auth...
225
+ def connect_for( env, &block )
226
+ info = landscape[env]
227
+ puts ">>> Connecting for #{env} -- #{info['host']}-#{info['port']}"
228
+ con = Mongo::Connection.new( info['host'], info['port'] )
229
+
230
+ if info['user'] and info['password']
231
+ con.db( 'admin' ).authenticate( info['user'], info['password'] )
232
+ end
233
+ yield con
234
+ con.close()
235
+ end
236
+
237
+ # db request occurs within dist 2
238
+ def db_request?( path )
239
+ path.size == 2
240
+ end
241
+
242
+ # cltn request occurs within dist 3
243
+ def cltn_request?( path )
244
+ path.size == 3
245
+ end
246
+
247
+ # Break down indexes in index + asc/desc
248
+ def format_indexes( indexes )
249
+ formatted = {}
250
+ indexes.each_pair do |key, values|
251
+ buff = []
252
+ values.each do |pair|
253
+ buff << "#{pair.first} [#{pair.last}]"
254
+ end
255
+ formatted[key] = buff
256
+ end
257
+ formatted
258
+ end
170
259
 
171
260
  # Convert size to mb
172
261
  def to_mb( val )
data/lib/mongo3/node.rb CHANGED
@@ -12,6 +12,10 @@ module Mongo3
12
12
  @parent = nil
13
13
  end
14
14
 
15
+ def self.make_node( name )
16
+ Node.new( name, name, :path_ids => name, :path_names => name )
17
+ end
18
+
15
19
  # Add a child node
16
20
  def <<( new_one )
17
21
  new_one.parent = self
@@ -20,8 +24,8 @@ module Mongo3
20
24
  end
21
25
 
22
26
  def update_paths( node )
23
- node.data[:crumbs] = node.path( :name )
24
- node.data[:path] = node.path
27
+ node.data[:path_names] = node.path( :name )
28
+ node.data[:path_ids] = node.path( :oid )
25
29
  node.children.each do |child|
26
30
  child.update_paths( child )
27
31
  end
data/lib/mongo3.rb CHANGED
@@ -2,7 +2,7 @@
2
2
  module Mongo3
3
3
 
4
4
  # :stopdoc:
5
- VERSION = '0.0.1'
5
+ VERSION = '0.0.2'
6
6
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
7
7
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
8
8
  # :startdoc: