ro 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []