ro 0.0.1 → 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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2M5NmE2YmY3ZDgyYWFhNzZhMzE3MzFmOTgzNmJkNGE4YmM1M2U3Ng==
5
+ data.tar.gz: !binary |-
6
+ ZWMxMzRkMWJhNmZlYmJkMTk4ODAzNjRhOTgxZGIxNWZhMjFkNjE0NQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MTgyNDczMDY4ZjY1YTE0Nzg2MmZjN2RlYzU1NzdhNjVjNzY1YzE0NjA1ZGNl
10
+ OTNlMjQyODc1MGQyZGViMDA4MWFkN2ViNzRiM2ViODdiODYwY2ZiNTZhN2Vh
11
+ ZGUxOTU0YzZkMGUxNWFmNmY2ZTBiOWY3YWQxODg5OWFmZWE1NmE=
12
+ data.tar.gz: !binary |-
13
+ N2JlYmYwOGJhYTlhYzY2YWI4ZDJkNzQ4MWY2OWE1NmE0YWVlMjllODZiNjEx
14
+ ZTI0OTQyNjkxNDVjMTBiZjc3ZmFhZDYyMjllMzkwYmU4OTQzNTY3NDVkMjQ4
15
+ MTJmNjM4ZThiOTQ4Mzk5MTliNTdmOGUxN2E5OTcxMzBiOTgyODQ=
data/: ADDED
@@ -0,0 +1,9 @@
1
+ module Ro
2
+ class Template
3
+ fattr :path
4
+
5
+ def initialize(path)
6
+ @path = Ro.realpath(path)
7
+ end
8
+ end
9
+ end
data/:w ADDED
@@ -0,0 +1,29 @@
1
+ module Ro
2
+ class Db
3
+ fattr :root
4
+
5
+ def initialize(*args, &block)
6
+ options = Map.options_for!(args)
7
+
8
+ @root = String(args.shift || options[:root] || Ro.root)
9
+ end
10
+
11
+ def collections
12
+ end
13
+
14
+ def glob
15
+ end
16
+
17
+ def nodes
18
+ 42
19
+ end
20
+
21
+ class Collection
22
+ fattr :basename
23
+
24
+ def initialize(basename)
25
+ @basename = basename.to_s
26
+ end
27
+ end
28
+ end
29
+ end
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ NAME
2
+ ----
3
+
4
+ ro
5
+
6
+
7
+ SYNOPSIS
8
+ --------
9
+
10
+ RTFC
11
+
12
+
13
+ DESCRIPTION
14
+ -----------
15
+
16
+ ro is library for managing your site's content in git, as god intended.
17
+
18
+ more details coming soon...
19
+
20
+
21
+ INSTALL
22
+ -------
23
+
24
+ gem install ro (coming soon)
25
+
26
+
27
+ DOCS
28
+ ----
29
+
30
+ RTFC
data/Rakefile CHANGED
@@ -59,8 +59,8 @@ end
59
59
 
60
60
  task :gemspec do
61
61
  ignore_extensions = ['git', 'svn', 'tmp', /sw./, 'bak', 'gem']
62
- ignore_directories = ['pkg']
63
- ignore_files = ['test/log', 'a.rb'] + Dir['db/*'] + %w'db'
62
+ ignore_directories = ['pkg', 'db']
63
+ ignore_files = ['test/log', 'test/db.yml', 'a.rb', 'b.rb'] + Dir['db/*'] + %w'db'
64
64
 
65
65
  shiteless =
66
66
  lambda do |list|
@@ -90,6 +90,16 @@ task :gemspec do
90
90
  test_files = test(?e, "test/#{ lib }.rb") ? "test/#{ lib }.rb" : nil
91
91
  summary = object.respond_to?(:summary) ? object.summary : "summary: #{ lib } kicks the ass"
92
92
  description = object.respond_to?(:description) ? object.description : "description: #{ lib } kicks the ass"
93
+ license = object.respond_to?(:license) ? object.license : nil
94
+
95
+ if license.nil?
96
+ license =
97
+ begin
98
+ IO.binread('LICENSE')
99
+ rescue
100
+ "Same As Ruby's"
101
+ end
102
+ end
93
103
 
94
104
  if This.extensions.nil?
95
105
  This.extensions = []
@@ -127,6 +137,7 @@ task :gemspec do
127
137
  spec.platform = Gem::Platform::RUBY
128
138
  spec.summary = <%= lib.inspect %>
129
139
  spec.description = <%= description.inspect %>
140
+ spec.license = <%= license.inspect %>
130
141
 
131
142
  spec.files =\n<%= files.sort.pretty_inspect %>
132
143
  spec.executables = <%= executables.inspect %>
@@ -293,7 +304,7 @@ BEGIN {
293
304
 
294
305
  # discover full path to this ruby executable
295
306
  #
296
- c = RbConfig::CONFIG
307
+ c = Config::CONFIG
297
308
  bindir = c["bindir"] || c['BINDIR']
298
309
  ruby_install_name = c['ruby_install_name'] || c['RUBY_INSTALL_NAME'] || 'ruby'
299
310
  ruby_ext = c['EXEEXT'] || ''
data/lib/co/db.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Co
2
+ class Db
3
+ end
4
+ end
data/lib/co/node.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Co
2
+ class Node
3
+ end
4
+ end
@@ -0,0 +1,16 @@
1
+ module Co
2
+ class Node
3
+ class List < ::Array
4
+ def method_missing(method, *args, &block)
5
+ end
6
+
7
+ def [](*args)
8
+ case args.first
9
+ when Symbol, String
10
+ else
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
data/lib/co/util.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Co
2
+ module Util
3
+ extend(Util)
4
+ end
5
+ end
data/lib/ro.rb CHANGED
@@ -1,5 +1,184 @@
1
- module Ro
2
- def Ro.version
3
- '0.0.1'
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'fileutils'
4
+ require 'pathname'
5
+ require 'yaml'
6
+ require 'digest/md5'
7
+ require 'logger'
8
+
9
+ #
10
+ module Ro
11
+ Version = '1.0.0' unless defined?(Version)
12
+
13
+ def version
14
+ Ro::Version
15
+ end
16
+
17
+ def dependencies
18
+ {
19
+ 'map' => [ 'map' , ' >= 6.5.1' ] ,
20
+ 'fattr' => [ 'fattr' , ' >= 2.2.1' ] ,
21
+ 'tilt' => [ 'tilt' , ' >= 1.4.1' ] ,
22
+ 'pygments' => [ 'pygments.rb' , ' >= 0.5.0' ] ,
23
+ 'coerce' => [ 'coerce' , ' >= 0.0.4' ] ,
24
+ 'stringex' => [ 'stringex' , ' >= 2.1.0' ] ,
25
+ # 'rails' => [ 'rails' , ' >= 3.1' ] ,
26
+ # 'tagz' => [ 'tagz' , ' >= 9.9.2' ] ,
27
+ # 'multi_json' => [ 'multi_json' , ' >= 1.0.3' ] ,
28
+ # 'uuidtools' => [ 'uuidtools' , ' >= 2.1.2' ] ,
29
+ # 'wrap' => [ 'wrap' , ' >= 1.5.0' ] ,
30
+ # 'rails_current' => [ 'rails_current' , ' >= 1.8.0' ] ,
31
+ # 'rails_errors2html' => [ 'rails_errors2html' , ' >= 1.3.0' ] ,
32
+ }
33
+ end
34
+
35
+ def libdir(*args, &block)
36
+ @libdir ||= File.expand_path(__FILE__).sub(/\.rb$/,'')
37
+ args.empty? ? @libdir : File.join(@libdir, *args)
38
+ ensure
39
+ if block
40
+ begin
41
+ $LOAD_PATH.unshift(@libdir)
42
+ block.call()
43
+ ensure
44
+ $LOAD_PATH.shift()
45
+ end
46
+ end
47
+ end
48
+
49
+ def load(*libs)
50
+ libs = libs.join(' ').scan(/[^\s+]+/)
51
+ Ro.libdir{ libs.each{|lib| Kernel.load(lib) } }
52
+ end
53
+
54
+ extend(Ro)
4
55
  end
5
- end
56
+
57
+ #
58
+ begin
59
+ require 'rubygems'
60
+ rescue LoadError
61
+ nil
62
+ end
63
+
64
+ if defined?(gem)
65
+ Ro.dependencies.each do |lib, dependency|
66
+ gem(*dependency)
67
+ require(lib)
68
+ end
69
+ end
70
+
71
+ %w[
72
+ fileutils
73
+ yaml
74
+ ].each do |lib|
75
+ require lib
76
+ end
77
+
78
+ #
79
+
80
+ module Ro
81
+ Fattr(:root){
82
+ Root.new(
83
+ case
84
+ when defined?(Rails.root)
85
+ Rails.root.to_s
86
+
87
+ when defined?(Middleman::Application)
88
+ Middleman::Application.server.root.to_s
89
+
90
+ else
91
+ "./ro"
92
+ end
93
+ )
94
+ }
95
+
96
+ Fattr(:cache){
97
+ Cache.new
98
+ }
99
+
100
+ Fattr(:logger){
101
+ nil
102
+ }
103
+
104
+ def Ro.nodes(*args, &block)
105
+ root.nodes(*args, &block)
106
+ end
107
+
108
+ def Ro.relative_path(path, *args)
109
+ options = Map.options_for!(args)
110
+ path = File.expand_path(String(path))
111
+ relative = File.expand_path(String(args.shift || options[:relative] || options[:to]))
112
+ Pathname.new(path).relative_path_from(Pathname.new(relative)).to_s
113
+ end
114
+
115
+ def Ro.realpath(path)
116
+ Pathname.new(path.to_s).realpath
117
+ end
118
+
119
+ def Ro.md5(string)
120
+ Digest::MD5.hexdigest(string)
121
+ end
122
+
123
+ def Ro.debug!
124
+ @logger ||= (
125
+ logger = ::Logger.new(STDERR)
126
+ logger.level = ::Logger::DEBUG
127
+ logger
128
+ )
129
+ end
130
+
131
+ def Ro.log(*args, &block)
132
+ return if @logger.nil?
133
+
134
+ level =
135
+ if args.size == 1
136
+ :debug
137
+ else
138
+ args.shift
139
+ end
140
+
141
+ @logger.send(level, *args, &block)
142
+ end
143
+
144
+ def Ro.slug_for(*args, &block)
145
+ options = Map.options_for!(args)
146
+ options[:join] = '-'
147
+ args.push(options)
148
+ Slug.for(*args, &block)
149
+ end
150
+
151
+ def Ro.name_for(*args, &block)
152
+ options = Map.options_for!(args)
153
+ options[:join] = '_'
154
+ args.push(options)
155
+ Slug.for(*args, &block)
156
+ end
157
+ end
158
+
159
+ #
160
+ module Kernel
161
+ def ro(*args, &block)
162
+ Ro.nodes(*args, &block)
163
+ end
164
+ end
165
+
166
+ #
167
+ Ro.load %w[
168
+
169
+ initializers/tilt.rb
170
+ initializers/env.rb
171
+
172
+ slug.rb
173
+ blankslate.rb
174
+ util.rb
175
+
176
+ root.rb
177
+
178
+ cache.rb
179
+
180
+ template.rb
181
+ node.rb
182
+ node/list.rb
183
+
184
+ ]
@@ -0,0 +1,7 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module Ro
4
+ class BlankSlate
5
+ instance_methods.each{|m| undef_method(m) unless m.to_s =~ /(^__)|object_id/}
6
+ end
7
+ end
data/lib/ro/cache.rb ADDED
@@ -0,0 +1,20 @@
1
+ module Ro
2
+ class Cache < ::Hash
3
+ def write(key, value)
4
+ self[key] = value
5
+ end
6
+
7
+ def read(key, &block)
8
+ if has_key?(key)
9
+ self[key]
10
+ else
11
+ if block
12
+ value = block.call
13
+ write(key, value)
14
+ else
15
+ nil
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
data/lib/ro/db.rb ADDED
@@ -0,0 +1,29 @@
1
+ module Ro
2
+ class Db
3
+ fattr :root
4
+
5
+ def initialize(*args, &block)
6
+ options = Map.options_for!(args)
7
+
8
+ @root = String(args.shift || options[:root] || Ro.root)
9
+ end
10
+
11
+ def collections
12
+ @collections ||= Collection::List.new
13
+
14
+ Dir.glob(glob){|path| @collections.add(path)}
15
+
16
+ @collections
17
+ end
18
+
19
+ def glob
20
+ File.join(root, '*')
21
+ end
22
+
23
+ def nodes(*args, &block)
24
+ collections.map do |collection|
25
+ collection.nodes(*args, &block)
26
+ end.flatten
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ module Ro
2
+ class Db
3
+ class Collection
4
+ class List < ::Array
5
+ def add(path)
6
+ name = File.basename(path.to_s)
7
+
8
+ unless any?{|c| c.name == name }
9
+ collection = Collection.new(path)
10
+ push(collection)
11
+ sort!{|a,b| a.name <=> b.name}
12
+ end
13
+ end
14
+ end
15
+
16
+ fattr :path
17
+
18
+ def initialize(path)
19
+ @path = Util.realpath(path)
20
+ end
21
+
22
+ def basename
23
+ File.basename(@path)
24
+ end
25
+
26
+ def name
27
+ basename
28
+ end
29
+
30
+ def dirname
31
+ File.dirname(@path)
32
+ end
33
+
34
+ def glob
35
+ File.join(@path, '*')
36
+ end
37
+
38
+ def nodes
39
+ Dir.glob(glob).map do |path|
40
+ next unless test(?d, path)
41
+ Ro::Node.new(path)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ module Ro
2
+ if ENV['RO_DEBUG']
3
+ Ro.debug!
4
+ end
5
+ end
@@ -0,0 +1,97 @@
1
+ require 'tilt'
2
+
3
+ module Tilt
4
+ class SyntaxHighlightingRedcarpetTemplate < Template
5
+ self.default_mime_type = 'text/html'
6
+
7
+ def self.engine_initialized?
8
+ defined?(::Redcarpet) && defined?(::Pygments) && defined?(::ERB)
9
+ end
10
+
11
+ def initialize_engine
12
+ require_template_library('redcarpet')
13
+ require_template_library('pygments')
14
+ require_template_library('erb')
15
+ end
16
+
17
+ def prepare
18
+ @engine =
19
+ Redcarpet::Markdown.new(
20
+ syntax_highlighting_renderer,
21
+
22
+ :no_intra_emphasis => true,
23
+ :tables => true,
24
+ :fenced_code_blocks => true,
25
+ :autolink => true,
26
+ :strikethrough => true,
27
+ :lax_html_blocks => true,
28
+ :space_after_headers => true,
29
+ :superscript => true
30
+ )
31
+
32
+ @output = nil
33
+ end
34
+
35
+ def syntax_highlighting_renderer
36
+ Class.new(Redcarpet::Render::HTML) do
37
+ def block_code(code, language)
38
+ language = 'ruby' if language.to_s.strip.empty?
39
+ ::Pygments.highlight(code, :lexer => language, :options => {:encoding => 'utf-8'})
40
+ end
41
+ end
42
+ end
43
+
44
+ def evaluate(scope, locals, &block)
45
+ binding =
46
+ if scope.is_a?(::Binding)
47
+ scope
48
+ else
49
+ scope.instance_eval{ ::Kernel.binding }
50
+ end
51
+
52
+ @engine.render(erb(data, binding))
53
+ end
54
+
55
+ def erb(string, binding)
56
+ string
57
+ end
58
+
59
+ def allows_script?
60
+ true
61
+ end
62
+ end
63
+
64
+ class ERBSyntaxHighlightingRedcarpetTemplate < SyntaxHighlightingRedcarpetTemplate
65
+ def erb(string, binding)
66
+ ::ERB.new(string).result(binding)
67
+ end
68
+ end
69
+ end
70
+
71
+ Tilt.prefer(Tilt::SyntaxHighlightingRedcarpetTemplate, 'md')
72
+ Tilt.prefer(Tilt::SyntaxHighlightingRedcarpetTemplate, 'markdown')
73
+ Tilt.prefer(Tilt::ERBSyntaxHighlightingRedcarpetTemplate, 'md.erb')
74
+ Tilt.prefer(Tilt::ERBSyntaxHighlightingRedcarpetTemplate, 'markdown.erb')
75
+
76
+
77
+ if $0 == __FILE__
78
+
79
+ markdown = <<-__
80
+ * one
81
+ * two
82
+ * <%= :three %>
83
+ * <%= @x %>
84
+
85
+ ```rb
86
+ @a = 42
87
+ yield
88
+ ```
89
+ __
90
+
91
+ template = Tilt['md.erb'].new{ markdown }
92
+
93
+ object = Object.new.instance_eval{ @x = :four; self }
94
+
95
+ puts template.render(object)
96
+
97
+ end
data/lib/ro/node.rb ADDED
@@ -0,0 +1,215 @@
1
+ module Ro
2
+ class Node
3
+ fattr :root
4
+ fattr :path
5
+ fattr :name
6
+ fattr :type
7
+ fattr :loaded
8
+
9
+ def initialize(path)
10
+ @path = Ro.realpath(path.to_s)
11
+ @name = File.basename(@path)
12
+ @type = File.basename(File.dirname(@path))
13
+ @root = Ro::Root.new(File.dirname(File.dirname(@path)))
14
+ @loaded = false
15
+ @attributes = nil
16
+ @in_method_missing = false
17
+ end
18
+
19
+ def id
20
+ @name
21
+ end
22
+
23
+ def identifier
24
+ "#{ type }/#{ name }"
25
+ end
26
+
27
+ def inspect
28
+ #"#{ self.class.name }(#{ type }/#{ name })"
29
+ identifier
30
+ end
31
+
32
+ def to_s
33
+ inpsect
34
+ end
35
+
36
+ def basename
37
+ name
38
+ end
39
+
40
+ def method_missing(method, *args, &block)
41
+ Ro.log "Ro::Node(#{ identifier })#method_missing(#{ method.inspect }, #{ args.inspect })"
42
+
43
+ in_method_missing = !!@in_method_missing
44
+
45
+ return super if in_method_missing
46
+
47
+ @in_method_missing = true
48
+
49
+ _load do
50
+ key = method.to_s
51
+
52
+ return(
53
+ if @attributes.has_key?(key)
54
+ @attributes[key]
55
+ else
56
+ super
57
+ end
58
+ )
59
+ end
60
+ ensure
61
+ @in_method_missing = in_method_missing
62
+ end
63
+
64
+ def attributes
65
+ _load{ @attributes }
66
+ end
67
+
68
+ def instance_eval(*args, &block)
69
+ _load{ super }
70
+ end
71
+
72
+ def related(*args, &block)
73
+ _load{
74
+ related = @attributes.get(:related) || Map.new
75
+ nodes = List.new(root)
76
+ list = root.nodes
77
+ which = Coerce.list_of_strings(args)
78
+
79
+ related.each do |relationship, value|
80
+ unless which.empty?
81
+ next unless which.include?(relationship.to_s)
82
+ end
83
+
84
+ type, names =
85
+ case value
86
+ when Hash
87
+ value.to_a.first
88
+ else
89
+ [relationship, value]
90
+ end
91
+
92
+ names = Coerce.list_of_strings(names)
93
+
94
+ names.each do |name|
95
+ identifier = "#{ type }/#{ name }"
96
+ node = list.index[identifier]
97
+ node._load{ nodes.add(node) }
98
+ end
99
+ end
100
+
101
+ case
102
+ when block.nil?
103
+ nodes
104
+
105
+ when block
106
+ nodes.where(&block)
107
+ end
108
+ }
109
+ end
110
+
111
+ class Related
112
+ fattr :attributes
113
+
114
+ def initialize(attributes)
115
+ @attributes = attributes
116
+ end
117
+
118
+ def all
119
+ related = @attributes.get(:related) || Map.new
120
+ names = related.keys
121
+ self[names]
122
+ end
123
+
124
+ def [](name)
125
+ name = File.basename(name.to_s)
126
+
127
+ value = @attributes.get(:related, name)
128
+
129
+ type, names =
130
+ case value
131
+ when Hash
132
+ value.to_a.first
133
+ else
134
+ [name, value]
135
+ end
136
+
137
+ names = Array(names).flatten.compact.uniq
138
+
139
+ list = ro[type]
140
+
141
+ list.where(*names)
142
+ end
143
+ end
144
+
145
+ def _load(&block)
146
+ unless @loaded
147
+ @loaded = _load_from_cache_or_disk
148
+ end
149
+
150
+ block ? block.call : @loaded
151
+ end
152
+
153
+ def _load_from_cache_or_disk
154
+ cache_key = _cache_key
155
+
156
+ cached = Ro.cache.read(cache_key)
157
+
158
+ if cached
159
+ Ro.log "loading #{ identifier } from cache"
160
+ @attributes = Map.new.update(cached)
161
+ :cache
162
+ else
163
+ Ro.log "loading #{ identifier } from disk"
164
+ @attributes = Map.new
165
+ _load_attributes_yml
166
+ #_load_attribute_templates
167
+ #_load_sources
168
+ Ro.cache.write(cache_key, @attributes)
169
+ :disk
170
+ end
171
+ end
172
+
173
+ def _load_attributes_yml
174
+ if test(?s, _attributes_yml)
175
+ buf = IO.binread(_attributes_yml)
176
+ data = YAML.load(buf)
177
+ data = data.is_a?(Hash) ? data : {'_' => data}
178
+ @attributes.update(data)
179
+ end
180
+ end
181
+
182
+ def _cache_key
183
+ glob = File.join(@path, '**/**')
184
+
185
+ entries = []
186
+
187
+ Dir.glob(glob) do |entry|
188
+ stat =
189
+ begin
190
+ File.stat(entry)
191
+ rescue
192
+ next
193
+ end
194
+
195
+ timestamp = [stat.ctime, stat.mtime].max
196
+ relative_path = Ro.relative_path(entry, :to => @path)
197
+ entries.push([relative_path, timestamp.iso8601(2)])
198
+ end
199
+
200
+ signature = entries.map{|pair| pair.join('@')}.join(', ')
201
+
202
+ md5 = Ro.md5(signature)
203
+
204
+ "#{ @path }-#{ md5 }"
205
+ end
206
+
207
+ def _load_from_cache
208
+ false
209
+ end
210
+
211
+ def _attributes_yml
212
+ File.join(@path, 'attributes.yml')
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,130 @@
1
+ module Ro
2
+ class Node
3
+ class List < ::Array
4
+ fattr :root
5
+ fattr :type
6
+ fattr :index
7
+
8
+ def initialize(*args, &block)
9
+ options = Map.options_for!(args)
10
+
11
+ root = args.shift || options[:root]
12
+ type = args.shift || options[:type]
13
+
14
+ @root = Root.new(root)
15
+ @type = type.nil? ? nil : String(type)
16
+ @index = {}
17
+
18
+ block.call(self) if block
19
+ end
20
+
21
+ def load(path)
22
+ add( node = Node.new(path) )
23
+ end
24
+
25
+ def add(node)
26
+ return nil if node.nil?
27
+
28
+ unless index.has_key?(node.identifier)
29
+ push(node)
30
+ index[node.identifier] = node
31
+ node
32
+ else
33
+ false
34
+ end
35
+ end
36
+
37
+ def related(*args, &block)
38
+ related = List.new(root)
39
+
40
+ each do |node|
41
+ node.related(*args, &block).each do |related_node|
42
+ related.add(related_node)
43
+ end
44
+ end
45
+
46
+ related
47
+ end
48
+
49
+ def [](key)
50
+ if @type.nil?
51
+ type = key.to_s
52
+ list = select{|node| type == node.type}
53
+ list.type = type
54
+ list
55
+ else
56
+ name = key.to_s
57
+ detect{|node| name == node.name}
58
+ end
59
+ end
60
+
61
+ def select(*args, &block)
62
+ List.new(root){|list| list.replace(super)}
63
+ end
64
+
65
+ def where(*args, &block)
66
+ case
67
+ when !args.empty? && block
68
+ raise ArgumentError.new
69
+
70
+ when args.empty? && block
71
+ select{|node| node.instance_eval(&block)}
72
+
73
+ when !args.empty?
74
+ names = args.flatten.compact.uniq.map{|arg| arg.to_s}
75
+ index = names.inject(Hash.new){|h,name| h.update(name => name)}
76
+ select{|node| index[node.name]}
77
+
78
+ else
79
+ raise ArgumentError.new
80
+ end
81
+ end
82
+
83
+ def find(*args, &block)
84
+ case
85
+ when !args.empty? && block
86
+ raise ArgumentError.new
87
+ when args.empty? && block
88
+ detect{|node| node.instance_eval(&block)}
89
+
90
+ when args.size == 1
91
+ name = args.first.to_s
92
+ detect{|node| node.name == name}
93
+
94
+ when args.size > 1
95
+ where(*args, &block)
96
+
97
+ else
98
+ raise ArgumentError.new
99
+ end
100
+ end
101
+
102
+ def identifier
103
+ [root, type].compact.join('/')
104
+ end
105
+
106
+ def method_missing(method, *args, &block)
107
+ Ro.log "Ro::List(#{ identifier })#method_missing(#{ method.inspect }, #{ args.inspect })"
108
+
109
+ in_method_missing = !!@in_method_missing
110
+
111
+ return super if in_method_missing
112
+
113
+ @in_method_missing = true
114
+
115
+ if @scope.nil?
116
+ type = method.to_s
117
+ list = self[type]
118
+ super unless list
119
+ list.empty? ? super : list
120
+ else
121
+ name = Ro.slug_for(method)
122
+ node = self[name]
123
+ node.nil? ? super : node
124
+ end
125
+ ensure
126
+ @in_method_missing = in_method_missing
127
+ end
128
+ end
129
+ end
130
+ end
data/lib/ro/root.rb ADDED
@@ -0,0 +1,30 @@
1
+ module Ro
2
+ class Root < ::String
3
+ def initialize(root)
4
+ super(Util.realpath(root.to_s))
5
+ ensure
6
+ raise ArgumentError.new("root=#{ root.inspect }") if root.nil?
7
+ raise ArgumentError.new("root=#{ root.inpsect }") unless test(?d, root)
8
+ end
9
+
10
+ def root
11
+ self
12
+ end
13
+
14
+ def nodes
15
+ Node::List.new(root) do |list|
16
+ node_directories do |path|
17
+ list.load(path)
18
+ end
19
+ end
20
+ end
21
+
22
+ def directories(&block)
23
+ Dir.glob(File.join(root, '*/'), &block)
24
+ end
25
+
26
+ def node_directories(&block)
27
+ Dir.glob(File.join(root, '*/*/'), &block)
28
+ end
29
+ end
30
+ end
data/lib/ro/slug.rb ADDED
@@ -0,0 +1,26 @@
1
+ module Ro
2
+ class Slug < ::String
3
+ Join = '-'
4
+
5
+ def Slug.for(*args)
6
+ options = args.last.is_a?(Hash) ? args.pop : {}
7
+ join = (options[:join]||options['join']||Join).to_s
8
+ string = args.flatten.compact.join(join)
9
+ string = unidecode(string)
10
+ words = string.to_s.scan(%r|[/\w]+|)
11
+ words.map!{|word| word.gsub %r|[^/0-9a-zA-Z_-]|, ''}
12
+ words.delete_if{|word| word.nil? or word.strip.empty?}
13
+ new(words.join(join).downcase.gsub('/', (join * 2)))
14
+ end
15
+
16
+ unless defined?(Stringex::Unidecoder)
17
+ def Slug.unidecode(string)
18
+ string
19
+ end
20
+ else
21
+ def Slug.unidecode(string)
22
+ Stringex::Unidecoder.decode(string)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ module Ro
2
+ class Template
3
+ fattr :path
4
+
5
+ def initialize(path)
6
+ @path = Ro.realpath(path)
7
+ end
8
+ end
9
+ end
data/lib/ro/util.rb ADDED
@@ -0,0 +1,13 @@
1
+ module Ro
2
+ module Util
3
+ def realpath(path)
4
+ begin
5
+ Pathname.new(path.to_s).expand_path.realpath.to_s
6
+ rescue Object
7
+ File.expand_path(path.to_s)
8
+ end
9
+ end
10
+
11
+ extend(self)
12
+ end
13
+ end
data/notes/ara.txt ADDED
@@ -0,0 +1,84 @@
1
+ todo:
2
+ - need source file loading
3
+
4
+ - need asset/url_for management
5
+
6
+ - ./bin/ro shell
7
+ - binding of all nodes?
8
+
9
+ - a real live test suite
10
+
11
+
12
+
13
+
14
+ done:
15
+ - need relationships
16
+ - ro.posts.related
17
+ - ro.posts.related.tags
18
+ - ro.posts.related[:tags]
19
+ - ro.posts.first.related.tags
20
+ - ro.posts.first.related[:tags]
21
+ - to_ary should not cause loading to fire
22
+ - node_sets
23
+ - ro -> node_set
24
+ - ro.posts -> node_set
25
+ - ro.posts
26
+ - should rollection be 'directory.ls'
27
+ - basic lib structure
28
+ - awesome tilt methods
29
+ - an extremely clever cache
30
+ - instrument logging/debugging
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+ ro # all nodes
42
+
43
+ ro.posts #=> set of all post nodes
44
+
45
+ ro.posts.tags #=> set of all tags related to any post
46
+
47
+ ro.tags.posts #=> set of all posts related to any tag
48
+
49
+ ro.posts{ name == 'foobar' }
50
+
51
+ ro.posts.first.tags
52
+
53
+ ro.posts.page(10, :per => 10)
54
+
55
+ ro.posts.first.url_for(:foobar)
56
+
57
+ ro/people/foo-bar/attributes.yaml
58
+ ro/people/foo-bar/attributes.yml
59
+ ro/people/foo-bar/bio.md
60
+ ro/people/foo-bar/source/a.rb
61
+ ro/people/foo-bar/assets/mugshot.png
62
+
63
+
64
+
65
+
66
+
67
+ require 'ro/model'
68
+
69
+
70
+
71
+
72
+ ----
73
+
74
+ class People < Ro::Model
75
+ root :people
76
+ end
77
+
78
+ Ro.root
79
+
80
+ Ro.nodes
81
+
82
+ def ro(*args, &block)
83
+ Ro.nodes(*args, &block)
84
+ end
data/ro.gemspec CHANGED
@@ -3,13 +3,55 @@
3
3
 
4
4
  Gem::Specification::new do |spec|
5
5
  spec.name = "ro"
6
- spec.version = "0.0.1"
6
+ spec.version = "1.0.0"
7
7
  spec.platform = Gem::Platform::RUBY
8
8
  spec.summary = "ro"
9
9
  spec.description = "description: ro kicks the ass"
10
+ spec.license = "Same As Ruby's"
10
11
 
11
12
  spec.files =
12
- ["Rakefile", "lib", "lib/ro.rb", "ro.gemspec"]
13
+ [":",
14
+ ":w",
15
+ "=p",
16
+ "README.md",
17
+ "Rakefile",
18
+ "lib",
19
+ "lib/co",
20
+ "lib/co/db.rb",
21
+ "lib/co/node",
22
+ "lib/co/node.rb",
23
+ "lib/co/node/list.rb",
24
+ "lib/co/util.rb",
25
+ "lib/lib",
26
+ "lib/ro",
27
+ "lib/ro.rb",
28
+ "lib/ro/blankslate.rb",
29
+ "lib/ro/cache.rb",
30
+ "lib/ro/db",
31
+ "lib/ro/db.rb",
32
+ "lib/ro/db/collection",
33
+ "lib/ro/db/collection.rb",
34
+ "lib/ro/initializers",
35
+ "lib/ro/initializers/env.rb",
36
+ "lib/ro/initializers/tilt.rb",
37
+ "lib/ro/node",
38
+ "lib/ro/node.rb",
39
+ "lib/ro/node/list.rb",
40
+ "lib/ro/root.rb",
41
+ "lib/ro/slug.rb",
42
+ "lib/ro/template.rb",
43
+ "lib/ro/util.rb",
44
+ "notes",
45
+ "notes/ara.txt",
46
+ "ro",
47
+ "ro.gemspec",
48
+ "ro/people",
49
+ "ro/people/ara",
50
+ "ro/people/ara/attributes.yml",
51
+ "ro/posts",
52
+ "ro/posts/foobar",
53
+ "ro/posts/hello-world",
54
+ "ro/posts/hello-world/attributes.yml"]
13
55
 
14
56
  spec.executables = []
15
57
 
@@ -18,6 +60,18 @@ Gem::Specification::new do |spec|
18
60
  spec.test_files = nil
19
61
 
20
62
 
63
+ spec.add_dependency(*["map", " >= 6.5.1"])
64
+
65
+ spec.add_dependency(*["fattr", " >= 2.2.1"])
66
+
67
+ spec.add_dependency(*["tilt", " >= 1.4.1"])
68
+
69
+ spec.add_dependency(*["pygments.rb", " >= 0.5.0"])
70
+
71
+ spec.add_dependency(*["coerce", " >= 0.0.4"])
72
+
73
+ spec.add_dependency(*["stringex", " >= 2.1.0"])
74
+
21
75
 
22
76
  spec.extensions.push(*[])
23
77
 
@@ -0,0 +1,11 @@
1
+ first_name: Ara
2
+
3
+ last_name: Howard
4
+
5
+ related:
6
+ posts:
7
+ - hello-world
8
+
9
+ sample_posts:
10
+ posts:
11
+ - hello-world
data/ro/posts/foobar ADDED
File without changes
@@ -0,0 +1,3 @@
1
+ title: Hello World
2
+
3
+ published_at: 2013-10-31T00:00:00
metadata CHANGED
@@ -1,47 +1,153 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ara T. Howard
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-02-07 00:00:00.000000000 Z
13
- dependencies: []
11
+ date: 2013-10-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: map
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 6.5.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 6.5.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: fattr
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.2.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.2.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: tilt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: 1.4.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 1.4.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: pygments.rb
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.5.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.5.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: coerce
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: 0.0.4
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: 0.0.4
83
+ - !ruby/object:Gem::Dependency
84
+ name: stringex
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: 2.1.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: 2.1.0
14
97
  description: ! 'description: ro kicks the ass'
15
98
  email: ara.t.howard@gmail.com
16
99
  executables: []
17
100
  extensions: []
18
101
  extra_rdoc_files: []
19
102
  files:
103
+ - ! ':'
104
+ - ':w'
105
+ - README.md
20
106
  - Rakefile
107
+ - lib/co/db.rb
108
+ - lib/co/node.rb
109
+ - lib/co/node/list.rb
110
+ - lib/co/util.rb
21
111
  - lib/ro.rb
112
+ - lib/ro/blankslate.rb
113
+ - lib/ro/cache.rb
114
+ - lib/ro/db.rb
115
+ - lib/ro/db/collection.rb
116
+ - lib/ro/initializers/env.rb
117
+ - lib/ro/initializers/tilt.rb
118
+ - lib/ro/node.rb
119
+ - lib/ro/node/list.rb
120
+ - lib/ro/root.rb
121
+ - lib/ro/slug.rb
122
+ - lib/ro/template.rb
123
+ - lib/ro/util.rb
124
+ - notes/ara.txt
22
125
  - ro.gemspec
126
+ - ro/people/ara/attributes.yml
127
+ - ro/posts/foobar
128
+ - ro/posts/hello-world/attributes.yml
23
129
  homepage: https://github.com/ahoward/ro
24
- licenses: []
130
+ licenses:
131
+ - Same As Ruby's
132
+ metadata: {}
25
133
  post_install_message:
26
134
  rdoc_options: []
27
135
  require_paths:
28
136
  - lib
29
137
  required_ruby_version: !ruby/object:Gem::Requirement
30
- none: false
31
138
  requirements:
32
139
  - - ! '>='
33
140
  - !ruby/object:Gem::Version
34
141
  version: '0'
35
142
  required_rubygems_version: !ruby/object:Gem::Requirement
36
- none: false
37
143
  requirements:
38
144
  - - ! '>='
39
145
  - !ruby/object:Gem::Version
40
146
  version: '0'
41
147
  requirements: []
42
148
  rubyforge_project: codeforpeople
43
- rubygems_version: 1.8.11
149
+ rubygems_version: 2.0.3
44
150
  signing_key:
45
- specification_version: 3
151
+ specification_version: 4
46
152
  summary: ro
47
153
  test_files: []