ro 1.4.6 → 4.4.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 (157) hide show
  1. checksums.yaml +6 -14
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +64 -0
  4. data/LICENSE +1 -0
  5. data/README.md +276 -105
  6. data/README.md.erb +159 -0
  7. data/Rakefile +129 -78
  8. data/bin/ro +241 -68
  9. data/lib/ro/_lib.rb +107 -0
  10. data/lib/ro/asset.rb +55 -0
  11. data/lib/ro/collection/list.rb +23 -0
  12. data/lib/ro/collection.rb +211 -0
  13. data/lib/ro/config.rb +72 -0
  14. data/lib/ro/error.rb +11 -0
  15. data/lib/ro/html.rb +23 -0
  16. data/lib/ro/html_safe.rb +143 -0
  17. data/lib/ro/klass.rb +25 -0
  18. data/lib/ro/methods.rb +295 -0
  19. data/lib/ro/model.rb +83 -114
  20. data/lib/ro/node.rb +209 -349
  21. data/lib/ro/pagination.rb +7 -4
  22. data/lib/ro/path.rb +229 -0
  23. data/lib/ro/root.rb +52 -31
  24. data/lib/ro/script/builder.rb +221 -0
  25. data/lib/ro/script/console.rb +47 -0
  26. data/lib/ro/script/server.rb +76 -0
  27. data/lib/ro/script.rb +189 -0
  28. data/lib/ro/slug.rb +19 -18
  29. data/lib/ro/template/rouge_formatter.rb +42 -0
  30. data/lib/ro/template.rb +145 -51
  31. data/lib/ro/text.rb +120 -0
  32. data/lib/ro.rb +89 -317
  33. data/public/api/ro/index-1.json +1065 -0
  34. data/public/api/ro/index.json +1055 -0
  35. data/public/api/ro/nerd/fastest-possible-embeddings/index.json +90 -0
  36. data/public/api/ro/nerd/ima/index.json +49 -0
  37. data/public/api/ro/nerd/index/index.json +74 -0
  38. data/public/api/ro/nerd/index-1.json +204 -0
  39. data/public/api/ro/nerd/index.json +194 -0
  40. data/public/api/ro/pages/about/index.json +60 -0
  41. data/public/api/ro/pages/contact/index.json +50 -0
  42. data/public/api/ro/pages/cv/index.json +49 -0
  43. data/public/api/ro/pages/disco/index.json +117 -0
  44. data/public/api/ro/pages/index/index.json +30 -0
  45. data/public/api/ro/pages/index-1.json +366 -0
  46. data/public/api/ro/pages/index.json +356 -0
  47. data/public/api/ro/pages/jess/index.json +62 -0
  48. data/public/api/ro/pages/now/index.json +43 -0
  49. data/public/api/ro/posts/almost-died-in-an-ice-cave/index.json +265 -0
  50. data/public/api/ro/posts/facebook-and-global-extremism/index.json +90 -0
  51. data/public/api/ro/posts/index-1.json +527 -0
  52. data/public/api/ro/posts/index.json +517 -0
  53. data/public/api/ro/posts/lemmings-considered-harmful/index.json +49 -0
  54. data/public/api/ro/posts/lost-in-the-desert/index.json +49 -0
  55. data/public/api/ro/posts/mission/index.json +49 -0
  56. data/public/api/ro/posts/return-your-laptop/index.json +61 -0
  57. data/public/ro/nerd/fastest-possible-embeddings/assets/giraffe.jpeg +0 -0
  58. data/public/ro/nerd/fastest-possible-embeddings/assets/let-me-in.jpg +0 -0
  59. data/public/ro/nerd/fastest-possible-embeddings/assets/src/fastembed.js +70 -0
  60. data/public/ro/nerd/fastest-possible-embeddings/assets/src/fastembed.rs +68 -0
  61. data/public/ro/nerd/fastest-possible-embeddings/assets/terminal.jpg +0 -0
  62. data/public/ro/nerd/fastest-possible-embeddings/attributes.yml +7 -0
  63. data/public/ro/nerd/fastest-possible-embeddings/body.md +266 -0
  64. data/public/ro/nerd/ima/assets/og.jpeg +0 -0
  65. data/public/ro/nerd/ima/attributes.yml +8 -0
  66. data/public/ro/nerd/ima/body.md +22 -0
  67. data/public/ro/nerd/index/assets/giraffe.jpeg +0 -0
  68. data/public/ro/nerd/index/assets/let-me-in.jpg +0 -0
  69. data/public/ro/nerd/index/assets/terminal.jpg +0 -0
  70. data/public/ro/nerd/index/attributes.yml +7 -0
  71. data/public/ro/nerd/index/body.md +130 -0
  72. data/public/ro/pages/about/assets/og.jpeg +0 -0
  73. data/public/ro/pages/about/assets/speak-english-pulp-fiction.gif +0 -0
  74. data/public/ro/pages/about/body.md +40 -0
  75. data/public/ro/pages/contact/assets/giraffe.jpeg +0 -0
  76. data/public/ro/pages/contact/attributes.yml +7 -0
  77. data/public/ro/pages/contact/body.md +9 -0
  78. data/public/ro/pages/cv/assets/ara.jpg +0 -0
  79. data/public/ro/pages/cv/attributes.yml +6 -0
  80. data/public/ro/pages/cv/body.md +122 -0
  81. data/public/ro/pages/disco/assets/disco.jpg +0 -0
  82. data/public/ro/pages/disco/assets/disco.png +0 -0
  83. data/public/ro/pages/disco/assets/speak-english-pulp-fiction.gif +0 -0
  84. data/public/ro/pages/disco/assets/src/environment.md +2354 -0
  85. data/public/ro/pages/disco/assets/src/fortune-500.md +2518 -0
  86. data/public/ro/pages/disco/assets/src/greed.md +2703 -0
  87. data/public/ro/pages/disco/assets/src/up-at-night.md +2337 -0
  88. data/public/ro/pages/disco/attributes.yml +9 -0
  89. data/public/ro/pages/disco/body.md +99 -0
  90. data/public/ro/pages/disco/samples/environment.md +2354 -0
  91. data/public/ro/pages/disco/samples/fortune-500.md +2518 -0
  92. data/public/ro/pages/disco/samples/greed.md +2703 -0
  93. data/public/ro/pages/disco/samples/up-at-night.md +2337 -0
  94. data/public/ro/pages/index/attributes.yml +1 -0
  95. data/public/ro/pages/index/body.md +15 -0
  96. data/public/ro/pages/jess/assets/og.jpg +0 -0
  97. data/public/ro/pages/jess/assets/speak-english-pulp-fiction.gif +0 -0
  98. data/public/ro/pages/jess/attributes.yml +7 -0
  99. data/public/ro/pages/jess/body.md +3 -0
  100. data/public/ro/pages/now/assets/speak-english-pulp-fiction.gif +0 -0
  101. data/public/ro/pages/now/attributes.yml +1 -0
  102. data/public/ro/pages/now/body.md +24 -0
  103. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image1.png +0 -0
  104. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image10.png +0 -0
  105. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image11.png +0 -0
  106. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image12.png +0 -0
  107. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image13.png +0 -0
  108. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image14.png +0 -0
  109. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image15.png +0 -0
  110. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image2.png +0 -0
  111. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image3.png +0 -0
  112. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image4.png +0 -0
  113. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image5.png +0 -0
  114. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image6.png +0 -0
  115. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image7.png +0 -0
  116. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image8.png +0 -0
  117. data/public/ro/posts/almost-died-in-an-ice-cave/assets/image9.png +0 -0
  118. data/public/ro/posts/almost-died-in-an-ice-cave/assets/josh-pointing.jpg +0 -0
  119. data/public/ro/posts/almost-died-in-an-ice-cave/assets/levi-rawr.png +0 -0
  120. data/public/ro/posts/almost-died-in-an-ice-cave/assets/og.jpg +0 -0
  121. data/public/ro/posts/almost-died-in-an-ice-cave/assets/purple-heart.jpg +0 -0
  122. data/public/ro/posts/almost-died-in-an-ice-cave/attributes.yml +6 -0
  123. data/public/ro/posts/almost-died-in-an-ice-cave/body.md +419 -0
  124. data/public/ro/posts/facebook-and-global-extremism/assets/background.html +125 -0
  125. data/public/ro/posts/facebook-and-global-extremism/assets/background.md +95 -0
  126. data/public/ro/posts/facebook-and-global-extremism/assets/og.jpg +0 -0
  127. data/public/ro/posts/facebook-and-global-extremism/assets/prompt.txt +122 -0
  128. data/public/ro/posts/facebook-and-global-extremism/assets/results.md +183 -0
  129. data/public/ro/posts/facebook-and-global-extremism/assets/survey.txt +190 -0
  130. data/public/ro/posts/facebook-and-global-extremism/attributes.yml +7 -0
  131. data/public/ro/posts/facebook-and-global-extremism/body.md +393 -0
  132. data/public/ro/posts/lemmings-considered-harmful/assets/lemming.jpeg +0 -0
  133. data/public/ro/posts/lemmings-considered-harmful/attributes.yml +6 -0
  134. data/public/ro/posts/lemmings-considered-harmful/body.md +43 -0
  135. data/public/ro/posts/lost-in-the-desert/assets/og.jpg +0 -0
  136. data/public/ro/posts/lost-in-the-desert/attributes.yml +6 -0
  137. data/public/ro/posts/lost-in-the-desert/body.md +7 -0
  138. data/public/ro/posts/mission/assets/og.jpg +0 -0
  139. data/public/ro/posts/mission/attributes.yml +6 -0
  140. data/public/ro/posts/mission/body.md +4 -0
  141. data/public/ro/posts/return-your-laptop/assets/og.jpg +0 -0
  142. data/public/ro/posts/return-your-laptop/assets/return-your-laptop.png +0 -0
  143. data/public/ro/posts/return-your-laptop/attributes.yml +6 -0
  144. data/public/ro/posts/return-your-laptop/body.md +58 -0
  145. data/ro.gemspec +217 -28
  146. data/scripts/speedtest.rb +324 -0
  147. data/tmp/gem-details.oe +0 -0
  148. metadata +214 -74
  149. data/TODO.md +0 -50
  150. data/lib/ro/blankslate.rb +0 -7
  151. data/lib/ro/cache.rb +0 -26
  152. data/lib/ro/git.rb +0 -374
  153. data/lib/ro/initializers/env.rb +0 -5
  154. data/lib/ro/initializers/tilt.rb +0 -104
  155. data/lib/ro/lock.rb +0 -53
  156. data/lib/ro/node/list.rb +0 -142
  157. data/notes/ara.txt +0 -215
data/lib/ro/methods.rb ADDED
@@ -0,0 +1,295 @@
1
+ module Ro
2
+ module Methods
3
+ # cast methods
4
+ # |
5
+ # v
6
+ def cast(which, arg, *args)
7
+ which = which.to_s
8
+ values = [arg, *args].join(',').scan(/[^,\s]+/)
9
+
10
+ list_of = which.match(/^list_of_(.+)$/)
11
+ which = list_of[1] if list_of
12
+
13
+ cast = casts.fetch(which.to_s.to_sym)
14
+
15
+ if list_of
16
+ values.map { |value| cast[value] }
17
+ else
18
+ raise ArgumentError, "too many values in #{values.inspect}" if values.size > 1
19
+
20
+ value = values.first
21
+ cast[value]
22
+ end
23
+ end
24
+
25
+ def casts
26
+ {
27
+ :string => proc { |value| String(value) },
28
+ :int => proc { |value| Integer(value.to_s) },
29
+ :string_or_nil => proc { |value| String(value).empty? ? nil : String(value) },
30
+ :url => proc { |value| Ro.normalize_url(value) },
31
+ :array => proc { |value| String(value).scan(/[^,:]+/) },
32
+ :bool => proc { |value| String(value) !~ /^\s*(f|false|off|no|0){0,1}\s*$/ },
33
+ :path => proc { |value| Path.for(value) },
34
+ :path_or_nil => proc { |value| String(value).empty? ? nil : Path.for(value) },
35
+ :root => proc { |value| Root.for(value) },
36
+ :time => proc { |value| Time.parse(value.to_s) },
37
+ :date => proc { |value| Date.parse(value.to_s) },
38
+ }
39
+ end
40
+
41
+ def mapify(pod)
42
+ Map.for(:pod => pod)[:pod]
43
+ end
44
+
45
+ def pod(object)
46
+ JSON.parse(object.to_json)
47
+ end
48
+
49
+ # url methods
50
+ # |
51
+ # v
52
+ def url_for(path, *args)
53
+ options = Map.extract_options!(args)
54
+
55
+ base = (options.delete(:base) || options.delete(:url))
56
+
57
+ path = Path.for(path, *args)
58
+
59
+ base ||= (
60
+ if Ro.is_image?(path)
61
+ Ro.config.img_url
62
+ else
63
+ Ro.config.url
64
+ end
65
+ )
66
+
67
+ fragment = options.delete(:fragment)
68
+ query = options.delete(:query) || options
69
+
70
+ uri = URI.parse(base.to_s)
71
+ uri.path = Path.for(uri.path, path).absolute
72
+ uri.path = '' if uri.path == '/'
73
+
74
+ uri.query = query_string_for(query) unless query.empty?
75
+ uri.fragment = fragment unless fragment.nil?
76
+
77
+ uri.to_s
78
+ end
79
+
80
+ def query_string_for(hash, options = {})
81
+ options = Map.for(options)
82
+ escape = options.has_key?(:escape) ? options[:escape] : true
83
+ pairs = []
84
+ esc = escape ? proc { |v| CGI.escape(v.to_s) } : proc { |v| v.to_s }
85
+ hash.each do |key, values|
86
+ key = key.to_s
87
+ values = [values].flatten
88
+ values.each do |value|
89
+ value = value.to_s
90
+ pairs << if value.empty?
91
+ [esc[key]]
92
+ else
93
+ [esc[key], esc[value]].join('=')
94
+ end
95
+ end
96
+ end
97
+ pairs.replace(pairs.sort_by { |pair| pair.size })
98
+ pairs.join('&')
99
+ end
100
+
101
+ def normalize_url(url)
102
+ uri = URI.parse(url.to_s).normalize
103
+ uri.path = Path.for(uri.path).absolute
104
+ uri.to_s
105
+ end
106
+
107
+ # log methods
108
+ # |
109
+ # v
110
+ attr_accessor :logger
111
+
112
+ def log(*args, &block)
113
+ level = nil
114
+
115
+ level = if args.size == 0 || args.size == 1
116
+ :info
117
+ else
118
+ args.shift.to_s.to_sym
119
+ end
120
+
121
+ @logger && @logger.send(level, *args, &block)
122
+ end
123
+
124
+ def log!
125
+ Ro.logger =
126
+ ::Logger.new(STDERR).tap do |logger|
127
+ logger.level = ::Logger::INFO
128
+ end
129
+ end
130
+
131
+ def debug!
132
+ Ro.logger =
133
+ ::Logger.new(STDERR).tap do |logger|
134
+ logger.level = ::Logger::DEBUG
135
+ end
136
+ end
137
+
138
+ def error!(message, **context)
139
+ error = Error.new(message, **context)
140
+
141
+ begin
142
+ raise error
143
+ rescue Error
144
+ backtrace = error.backtrace || []
145
+ error.set_backtrace(backtrace[1..-1])
146
+ raise
147
+ end
148
+ end
149
+
150
+ def emsg(e)
151
+ if e.is_a?(Exception)
152
+ "#{ e.message } (#{ e.class.name })\n#{ Array(e.backtrace).join(10.chr) }"
153
+ else
154
+ e.to_s
155
+ end
156
+ end
157
+
158
+ # template methods
159
+ # |
160
+ # v
161
+ def template(method = :tap, *args, &block)
162
+ Template.send(method, *args, &(block || proc {}))
163
+ end
164
+
165
+ def render(path, context = nil)
166
+ Template.render(path, context:)
167
+ end
168
+
169
+ def render_src(path, context = nil)
170
+ Template.render_src(path, context:)
171
+ end
172
+
173
+ # asset expansion methods
174
+ # |
175
+ # v
176
+ EXPAND_ASSET_URL_STRATEGIES = %i[
177
+ accurate_expand_asset_urls
178
+ sloppy_expand_asset_urls
179
+ ]
180
+
181
+ def expand_asset_url_strategies
182
+ @expand_asset_url_strategies ||= EXPAND_ASSET_URL_STRATEGIES.dup
183
+ end
184
+
185
+ def expand_asset_urls(html, node)
186
+ strategies = expand_asset_url_strategies
187
+ error = nil
188
+
189
+ strategies.each do |strategy|
190
+ return send(strategy, html, node)
191
+ rescue Object => e
192
+ error = e
193
+ Ro.log(:error, emsg(error))
194
+ Ro.log(:error, "failed to expand assets via #{ strategy }")
195
+ end
196
+
197
+ raise error
198
+ end
199
+
200
+ def accurate_expand_asset_urls(html, node)
201
+ doc = Nokogiri::HTML.fragment(html.to_str)
202
+
203
+ doc.traverse do |element|
204
+ if element.respond_to?(:attributes)
205
+ attributes = element.attributes
206
+ expand_asset_values!(attributes) unless attributes.empty?
207
+ end
208
+ end
209
+
210
+ expanded = doc.to_s.strip
211
+
212
+ HTML.new(expanded)
213
+ end
214
+
215
+ def sloppy_expand_asset_urls(html, node)
216
+ re = %r`\s*=\s*['"](?:[.]/)?(assets/[^'"\s]+)['"]`
217
+
218
+ expanded =
219
+ html.to_str.gsub(re) do |match|
220
+ path = match[%r`assets/[^'"\s]+`]
221
+
222
+ if node.path_for(path).exist?
223
+ url = node.url_for(path)
224
+ "='#{url}'"
225
+ else
226
+ match
227
+ end
228
+ end
229
+
230
+ HTML.new(expanded)
231
+ end
232
+
233
+ def expand_asset_values(hash, node)
234
+ src = Map.for(hash)
235
+ dst = Map.new(hash)
236
+
237
+ return dst if src.empty?
238
+
239
+ re = %r{\A(?:[.]/)?(assets/[^\s]+)\s*\z}
240
+
241
+ src.depth_first_each do |key, value|
242
+ next unless value.is_a?(String)
243
+
244
+ if (match = re.match(value.strip))
245
+ path = match[1].strip
246
+ url = node.url_for(path)
247
+ value = url
248
+ end
249
+
250
+ dst.set(key, value)
251
+ end
252
+
253
+ dst.to_hash
254
+ end
255
+
256
+ def expand_asset_values!(hash, node)
257
+ expand_asset_values(hash, node).each do |key, value|
258
+ hash[key] = value
259
+ end
260
+ end
261
+
262
+ #
263
+ DEFAULT_IMAGE_EXTENSIONS = %i[
264
+ webp jpg jpeg png gif tif tiff svg
265
+ ]
266
+
267
+ DEFAULT_IMAGE_PATTERNS = [
268
+ /[.](#{ DEFAULT_IMAGE_EXTENSIONS.join('|') })$/i
269
+ ]
270
+
271
+ def image_patterns
272
+ @image_patterns ||= DEFAULT_IMAGE_PATTERNS.dup
273
+ end
274
+
275
+ def image_pattern
276
+ Regexp.union(Ro.image_patterns)
277
+ end
278
+
279
+ def is_image?(path)
280
+ !!(URI.parse(path.to_s).path =~ Ro.image_pattern)
281
+ end
282
+
283
+ def image_info(path)
284
+ is = ImageSize.path(path)
285
+ format, width, height = is.format.to_s, is.width, is.height
286
+ {format:, width:, height:}
287
+ end
288
+
289
+ def uuid
290
+ SecureRandom.uuid_v7.to_s
291
+ end
292
+ end
293
+
294
+ extend Methods
295
+ end
data/lib/ro/model.rb CHANGED
@@ -1,97 +1,113 @@
1
1
  begin
2
2
  require 'active_model'
3
3
  require 'active_support'
4
- require 'active_support/core_ext/string/inflections.rb'
4
+ require 'active_support/core_ext/string/inflections'
5
5
  rescue LoadError => e
6
6
  abort "you need to add the 'active_model' and 'active_support' gems to use Ro::Model"
7
7
  end
8
8
 
9
+ require_relative '../ro' unless defined?(Ro)
10
+
9
11
  module Ro
10
12
  class Model
11
- #
13
+ require_relative 'pagination'
14
+
12
15
  extend ActiveModel::Naming
13
16
  extend ActiveModel::Translation
14
17
  include ActiveModel::Validations
15
18
  include ActiveModel::Conversion
16
19
 
17
- #
18
- Fattr(:collection){ default_collection_name }
19
- Fattr(:default_collection_name){ self.name.to_s.split(/::/).last.underscore.pluralize }
20
- Fattr(:root){ Ro.root }
21
- Fattr(:prefix){ File.join(root, collection) }
20
+ class << Model
21
+ def root
22
+ @root ||= Ro.root
23
+ end
22
24
 
23
- def Model.nodes(*args, &block)
24
- root.nodes.send(collection)
25
- end
25
+ def root=(root)
26
+ @root = Ro::Root.for(root)
27
+ end
26
28
 
27
- def Model.all(*args, &block)
28
- models_for(nodes)
29
- end
29
+ def default_collection_name
30
+ name.to_s.split(/::/).last.underscore.pluralize
31
+ end
30
32
 
31
- def Model.select(*args, &block)
32
- all.select(*args, &block)
33
- end
33
+ def collection_name(collection_name = nil)
34
+ @collection_name = collection_name.to_s if collection_name
34
35
 
35
- def Model.detect(*args, &block)
36
- all.detect(*args, &block)
37
- end
36
+ @collection_name || default_collection_name
37
+ end
38
38
 
39
- def Model.count(*args, &block)
40
- if args.empty? and block.nil?
41
- all.size
42
- else
43
- where(*args, &block).size
39
+ def collection
40
+ root.collections[collection_name]
44
41
  end
45
- end
46
42
 
47
- def Model.where(*args, &block)
48
- all.select do |model|
49
- !!model.instance_eval(&block)
43
+ def nodes
44
+ collection.to_a
50
45
  end
51
- end
52
46
 
53
- def Model.first
54
- all.first
55
- end
47
+ def all
48
+ models_for(nodes)
49
+ end
56
50
 
57
- def Model.last
58
- all.last
59
- end
51
+ def select(*args, &block)
52
+ all.select(*args, &block)
53
+ end
60
54
 
61
- def Model.find(id)
62
- re = %r/#{ id.to_s.gsub(/[-_]/, '[-_]') }/i
63
- all.detect{|model| model.id.to_s == id.to_s}
64
- end
55
+ def detect(*args, &block)
56
+ all.detect(*args, &block)
57
+ end
65
58
 
66
- def Model.[](id)
67
- find(id)
68
- end
59
+ def count(*args, &block)
60
+ if args.empty? and block.nil?
61
+ all.size
62
+ else
63
+ where(*args, &block).size
64
+ end
65
+ end
69
66
 
70
- def Model.method_missing(method, *args, &block)
71
- id = method
72
- model = find(id)
73
- return model if model
74
- super
75
- end
67
+ def where(*_args, &block)
68
+ all.select do |model|
69
+ !!model.instance_eval(&block)
70
+ end
71
+ end
72
+
73
+ def first
74
+ all.first
75
+ end
76
+
77
+ def last
78
+ all.last
79
+ end
76
80
 
77
- def Model.models_for(result)
78
- case result
81
+ def find(id)
82
+ slug = Slug.for(id)
83
+ all.detect { |model| Slug.for(model.id) == slug }
84
+ end
85
+
86
+ def [](id)
87
+ find(id)
88
+ end
89
+
90
+ def models_for(result)
91
+ case result
79
92
  when Array
80
- List.for(Array(result).flatten.compact.map{|element| new(element)})
93
+ List.for(Array(result).flatten.compact.map { |element| new(element) })
81
94
  else
82
95
  new(result)
96
+ end
83
97
  end
84
- end
85
98
 
86
- def Model.paginate(*args, &block)
87
- all.paginate(*args, &block)
99
+ def paginate(*args, &block)
100
+ all.paginate(*args, &block)
101
+ end
88
102
  end
89
103
 
90
104
  class List < ::Array
91
105
  include Pagination
92
106
 
93
- def List.for(*args, &block)
94
- new(*args, &block)
107
+ class << List
108
+ def for(*args, &block)
109
+ new(*args, &block)
110
+ end
95
111
  end
96
112
 
97
113
  def select(*args, &block)
@@ -107,26 +123,17 @@ module Ro
107
123
  List.new(*args, &block)
108
124
  end
109
125
 
110
- #
111
126
  attr_accessor(:node)
112
127
 
113
- def initialize(*args, &block)
128
+ def initialize(*args)
114
129
  attributes = Map.options_for!(args)
115
130
 
116
- node = args.detect{|arg| arg.is_a?(Node)}
117
- model = args.detect{|arg| arg.is_a?(Model)}
131
+ node = args.detect { |arg| arg.is_a?(Node) }
132
+ model = args.detect { |arg| arg.is_a?(Model) }
118
133
 
119
- if node.nil? and not model.nil?
120
- node = model.node
121
- end
134
+ node = model.node if node.nil? and !model.nil?
122
135
 
123
- if node
124
- @node = node
125
- else
126
- path = File.join(prefix, ':new')
127
- node = Node.new(path)
128
- @node = node
129
- end
136
+ @node = node
130
137
  end
131
138
 
132
139
  def attributes
@@ -137,54 +144,16 @@ module Ro
137
144
  true
138
145
  end
139
146
 
140
- #
141
- def prefix
142
- self.class.prefix
143
- end
144
-
145
- def directory
146
- File.join(prefix, id)
147
- end
148
-
149
- #
150
147
  def method_missing(method, *args, &block)
151
- node.send(method, *args, &block)
148
+ begin
149
+ node.send(method, *args, &block)
150
+ rescue
151
+ super
152
+ end
152
153
  end
153
154
 
154
- def respond_to?(method)
155
+ def respond_to?(method, *args, &block)
155
156
  super || node.respond_to?(method)
156
157
  end
157
158
  end
158
159
  end
159
-
160
-
161
-
162
-
163
- if __FILE__ == $0
164
-
165
- ENV['RO_ROOT'] = '../sample_ro_data'
166
-
167
- class Person < Ro::Model
168
-
169
- #field(:first_name, :type => :string)
170
-
171
- end
172
-
173
- p Person.collection
174
- p Person.all
175
- p Person.find(:ara).attributes
176
- ara = Person.find(:ara)
177
-
178
- p ara.url_for(:ara_glacier)
179
-
180
- p Person.paginate(:per => 2, :page => 1)
181
- p Person.name
182
-
183
- p Person.prefix
184
- p ara.id
185
- p ara.first_name
186
-
187
- require 'pry'
188
- binding.pry
189
-
190
- end