acls 1.0.0

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.
Files changed (6) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +98 -0
  4. data/lib/acls.rb +93 -0
  5. data/lib/module.rb +9 -0
  6. metadata +89 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a8368c41a5c809253d8edd299e4979988e71dc6f
4
+ data.tar.gz: 3add1931cdb2b571757adf3e7fa84ae223c38eea
5
+ SHA512:
6
+ metadata.gz: af956f49b047caa81da85e43368f854dd316cf22bb8e930278226071a9e4b9230db0b431a735858f9626ee591a9b4b57bc7d7582b7cb8b70860ed7e90117dc84
7
+ data.tar.gz: 92564464ccf52966c6cd764ee13b426c946e11eb2f62e5b4b3f3ec21a9fff7f511b55317068703da641c17a8f162438cdf27e0130719808222e5128dd029bccb
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Tyler Margison
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # automatic code loading system (acls)
2
+
3
+ [![Build Status](https://semaphoreci.com/api/v1/projects/80ef69fb-3dd1-499f-9e1c-acfa08d0a7d4/638892/badge.svg)](https://semaphoreci.com/kolorahl/acls)
4
+
5
+ ## What is it?
6
+
7
+ The Automatic Code Loading System (ACLS) is a Ruby library intended to help
8
+ speed up and simplify development time by allowing developers to define pathes
9
+ and patterns of files that should be autoloaded when their application runs.
10
+
11
+ ## How does it work?
12
+
13
+ Rails does something like this. In a Rails application you would change your
14
+ autoloading paths as such:
15
+
16
+ ```ruby
17
+ config.autoload_paths += ['lib', 'other/lib', 'etc'].map { |folder| "#{config.root}/#{folder}" }
18
+ ```
19
+
20
+ Rails will then look for all Ruby files in those directory trees and load them
21
+ for immediate use into your application. However, Rails does this in a very
22
+ complex manner by taking over the flow for when a constant isn't found. ACLS
23
+ does **not** do that. I have chosen a more straight-forward solution, which
24
+ simply generates an `autoload` statement for all Ruby files in a set of paths.
25
+
26
+ As an example, assume the following directory structure:
27
+
28
+ ```
29
+ - lib
30
+ | - one.rb
31
+ | - two.rb
32
+ | - sub
33
+ | | - three.rb
34
+ - other
35
+ | - four.rb
36
+ ```
37
+
38
+ Pass in the desired directory paths into the ACLS module:
39
+
40
+ ```ruby
41
+ ACLS::Loader.auto(['lib', 'other'])
42
+ ```
43
+
44
+ That one line with ACLS is equivalent to hand-writing the following Ruby code:
45
+
46
+ ```ruby
47
+ autoload :One, 'lib/one.rb'
48
+ autoload :Two, 'lib/two.rb'
49
+ module Sub
50
+ autoload :Three, 'lib/sub/three.rb'
51
+ end
52
+ autoload :Four, 'other/four.rb'
53
+ ```
54
+
55
+ ## Using it
56
+
57
+ The simplest way is to use:
58
+
59
+ ```ruby
60
+ ACLS::Loader.auto(['path', 'to/one/or/more', 'directories'])
61
+ ```
62
+
63
+ ACLS will automatically generate new module constants if it needs to. This
64
+ method of autoloading, however, makes assumptions about the directory
65
+ structure. The top-level directory is assumed to carry no namespace but every
66
+ sub-directory under that *does* imply a namespace. To customize bits of the
67
+ behavior, an options hash can be passed in as a second argument:
68
+
69
+ ```ruby
70
+ ACLS::Loader.auto('lib', {root_ns: true})
71
+ ```
72
+
73
+ Options available:
74
+
75
+ - `root_ns`: When `true`, this will use the top-level directory name as the root
76
+ namespace for all files and folders in the tree. When a string is supplied,
77
+ this will use the string as the name of the root namespace. For all other
78
+ values, the root directory is not a namespace and everything falls under the
79
+ `Object` namespace.
80
+ - `exclude`: Must be a collection of strings and/or regexps. For each string in
81
+ the collection, files are excluded from autoloading if they match the string
82
+ exactly. For each regexp in the collection, files are excluded from
83
+ autoloading if the path results in a successful match on the regexp.
84
+ - `immediate`: Must be a collection of strings and/or regexps. Follows the same
85
+ conditional pattern as `exclude`, but on a match this will immediate load the
86
+ file via `load` instead of deferring it using `autoload`.
87
+
88
+ ## Feature List
89
+
90
+ ### Core
91
+
92
+ - [X] Generate `autoload` statements based on a set of directory paths.
93
+
94
+ ### Options/Configuration
95
+
96
+ - [X] Implement `root_ns`.
97
+ - [ ] Implement `exclude`.
98
+ - [ ] Implement `immediate`.
data/lib/acls.rb ADDED
@@ -0,0 +1,93 @@
1
+ require 'active_support/inflector'
2
+ require_relative './module'
3
+
4
+ module ACLS
5
+ class Loader
6
+ class << self
7
+ # Use one or more paths to autoload a set of Ruby source files.
8
+ def auto(paths, opts={})
9
+ if paths.respond_to?(:each)
10
+ paths.each { |path| autoload_path(path, opts) }
11
+ else
12
+ autoload_path(paths, opts)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def get_root_ns(path, opts)
19
+ root_ns = opts[:root_ns]
20
+ root = Object
21
+ if root_ns.is_a?(TrueClass)
22
+ root = root.submodule(File.basename(path).camelize)
23
+ elsif root_ns.is_a?(String)
24
+ root_ns.split('::').each { |ns| root = root.submodule(ns) }
25
+ end
26
+ root
27
+ end
28
+
29
+ def autoload_path(path, opts)
30
+ if File.directory?(path)
31
+ root_ns = get_root_ns(path, opts)
32
+ autoload_magic(root_ns, path, opts)
33
+ else
34
+ raise Errno::ENOENT.new(path)
35
+ end
36
+ end
37
+
38
+ def autoload_magic(mod, path, opts)
39
+ # TODO: Add opts usage
40
+ Dir.entries(path).each do |entry|
41
+ next if entry[0] == '.'
42
+ full_path = "#{path}/#{entry}"
43
+ name = entry.sub(".rb", "").camelize
44
+ if File.directory?(full_path)
45
+ sub_mod = mod.submodule(name)
46
+ autoload_magic(sub_mod, full_path, opts)
47
+ else
48
+ autoload_for(mod, full_path, name)
49
+ end
50
+ end
51
+ end
52
+
53
+ def autoload_for(mod, path, name)
54
+ klass = guess_classname(path, name)
55
+ code = "autoload :#{klass}, \"#{path}\""
56
+ if mod.nil?
57
+ eval(code)
58
+ else
59
+ mod.module_eval(code)
60
+ end
61
+ end
62
+
63
+ def guess_classname(file, name)
64
+ process_classname_matches( scan_classnames(file), name )
65
+ end
66
+
67
+ def scan_classnames(file)
68
+ File.read(file).scan(/(class|module)\s+([^\n\r<]+)/)
69
+ end
70
+
71
+ def process_classname_matches(matches, name)
72
+ if match = best_classname_match(matches, name)
73
+ base_classname(match[1])
74
+ else
75
+ name
76
+ end
77
+ end
78
+
79
+ def best_classname_match(matches, name)
80
+ return nil unless matches
81
+ matches.drop_while { |match| !match_classname(match[1], name) }.first
82
+ end
83
+
84
+ def match_classname(match, name)
85
+ base_classname(match).downcase == name.downcase
86
+ end
87
+
88
+ def base_classname(name)
89
+ name.split("::").last
90
+ end
91
+ end
92
+ end
93
+ end
data/lib/module.rb ADDED
@@ -0,0 +1,9 @@
1
+ code = <<EOS
2
+ def submodule(name)
3
+ const_get(name, false)
4
+ rescue NameError
5
+ const_set(name, Module.new)
6
+ end
7
+ EOS
8
+
9
+ Module.module_eval(code)
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acls
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kolo Rahl
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 4.2.5
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '4.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 4.2.5
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.4'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 3.4.0
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '3.4'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 3.4.0
53
+ description: ACLS is a library for autoloading Ruby source files in one or more directory
54
+ trees.
55
+ email: kolorahl@gmail.com
56
+ executables: []
57
+ extensions: []
58
+ extra_rdoc_files: []
59
+ files:
60
+ - LICENSE
61
+ - README.md
62
+ - lib/acls.rb
63
+ - lib/module.rb
64
+ homepage: https://github.com/kolorahl/acls
65
+ licenses:
66
+ - MIT
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 2.4.6
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: ACLS - Automatic Code Loading System
88
+ test_files: []
89
+ has_rdoc: