dao 4.2.1 → 4.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/README +103 -63
  2. data/Rakefile +3 -3
  3. data/dao.gemspec +27 -16
  4. data/lib/dao.rb +17 -17
  5. data/lib/dao/active_record.rb +1 -0
  6. data/lib/dao/api.rb +2 -1
  7. data/lib/dao/api/{endpoints.rb → call.rb} +1 -0
  8. data/lib/dao/api/context.rb +2 -0
  9. data/lib/dao/api/dsl.rb +1 -0
  10. data/lib/dao/api/initializers.rb +1 -0
  11. data/lib/dao/api/modes.rb +1 -0
  12. data/lib/dao/api/routes.rb +1 -0
  13. data/lib/dao/blankslate.rb +1 -0
  14. data/lib/dao/conducer.rb +315 -274
  15. data/lib/dao/conducer/active_model.rb +98 -0
  16. data/lib/dao/conducer/attributes.rb +1 -0
  17. data/lib/dao/conducer/autocrud.rb +58 -0
  18. data/lib/dao/conducer/callback_support.rb +20 -0
  19. data/lib/dao/conducer/collection.rb +45 -0
  20. data/lib/dao/conducer/controller_support.rb +104 -0
  21. data/lib/dao/conducer/nav_support.rb +9 -0
  22. data/lib/dao/conducer/view_support.rb +16 -0
  23. data/lib/dao/data.rb +2 -1
  24. data/lib/dao/db.rb +2 -0
  25. data/lib/dao/endpoint.rb +1 -0
  26. data/lib/dao/engine.rb +1 -0
  27. data/lib/dao/errors.rb +109 -99
  28. data/lib/dao/exceptions.rb +1 -0
  29. data/lib/dao/extractor.rb +1 -0
  30. data/lib/dao/form.rb +175 -20
  31. data/lib/dao/instance_exec.rb +1 -0
  32. data/lib/dao/mode.rb +1 -0
  33. data/lib/dao/mongo_mapper.rb +1 -0
  34. data/lib/dao/name.rb +1 -0
  35. data/lib/dao/params.rb +2 -1
  36. data/lib/dao/path.rb +1 -0
  37. data/lib/dao/path_map.rb +24 -0
  38. data/lib/dao/rack.rb +1 -0
  39. data/lib/dao/rack/middleware.rb +1 -0
  40. data/lib/dao/rack/middleware/params_parser.rb +1 -0
  41. data/lib/dao/rails.rb +12 -32
  42. data/lib/dao/rails/lib/generators/dao/USAGE +2 -2
  43. data/lib/dao/rails/lib/generators/dao/dao_generator.rb +8 -27
  44. data/lib/dao/rails/lib/generators/dao/templates/api.rb +2 -1
  45. data/lib/dao/rails/lib/generators/dao/templates/api_controller.rb +22 -20
  46. data/lib/dao/rails/lib/generators/dao/templates/conducer.rb +49 -43
  47. data/lib/dao/rails/lib/generators/dao/templates/dao.css +26 -25
  48. data/lib/dao/rails/lib/generators/dao/templates/dao.js +3 -0
  49. data/lib/dao/rails/lib/generators/dao/templates/dao_helper.rb +58 -45
  50. data/lib/dao/result.rb +50 -1
  51. data/lib/dao/route.rb +1 -0
  52. data/lib/dao/slug.rb +12 -36
  53. data/lib/dao/status.rb +91 -7
  54. data/lib/dao/stdext.rb +1 -0
  55. data/lib/dao/support.rb +90 -80
  56. data/lib/dao/upload.rb +396 -0
  57. data/lib/dao/validations.rb +23 -5
  58. data/lib/dao/validations/callback.rb +5 -0
  59. data/lib/dao/validations/common.rb +100 -3
  60. data/lib/dao/validations/instance.rb +17 -0
  61. data/lib/dao/validations/validator.rb +192 -91
  62. data/test/active_model_conducer_lint_test.rb +1 -0
  63. data/test/api_test.rb +15 -0
  64. data/test/conducer_test.rb +608 -90
  65. data/test/data/han-solo.jpg +0 -0
  66. data/test/form_test.rb +1 -0
  67. data/test/helper.rb +1 -0
  68. data/test/leak.rb +1 -0
  69. data/test/support_test.rb +4 -1
  70. data/test/testing.rb +1 -0
  71. data/test/validations_test.rb +176 -30
  72. metadata +120 -131
  73. data/b.rb +0 -38
  74. data/lib/dao/conducer/crud.rb +0 -70
  75. data/lib/dao/current.rb +0 -66
  76. data/lib/dao/image_cache.rb +0 -193
  77. data/lib/dao/rails/lib/generators/dao/templates/conducer_controller.rb +0 -79
  78. data/test/db.yml +0 -9
@@ -0,0 +1,98 @@
1
+ module Dao
2
+ class Conducer
3
+ include ActiveModel::Naming
4
+ include ActiveModel::Conversion
5
+ extend ActiveModel::Translation
6
+
7
+ =begin
8
+ include ActiveModel::AttributeMethods
9
+ include ActiveModel::Serialization
10
+ include ActiveModel::Dirty
11
+ include ActiveModel::MassAssignmentSecurity
12
+ include ActiveModel::Observing
13
+ include ActiveModel::Serializers::JSON
14
+ include ActiveModel::Serializers::Xml
15
+ include ActiveModel::Validations
16
+ extend ActiveModel::Callbacks
17
+ define_model_callbacks(:save, :create, :update, :destroy)
18
+ define_model_callbacks(:reset, :initialize, :find, :touch)
19
+ include ActiveModel::Validations::Callbacks
20
+ =end
21
+
22
+ class << Conducer
23
+ def model_name(*args)
24
+ return send('model_name=', args.first.to_s) unless args.empty?
25
+ @model_name ||= default_model_name
26
+ end
27
+
28
+ def model_name=(model_name)
29
+ @model_name = model_name_for(model_name)
30
+ end
31
+
32
+ def model_name_for(model_name)
33
+ ActiveModel::Name.new(Map[:name, model_name])
34
+ end
35
+
36
+ def default_model_name
37
+ return model_name_for('Conducer') if self == Dao::Conducer
38
+ model_name_for(name.to_s.sub(/Conducer$/, '').sub(/(:|_)+$/, ''))
39
+ end
40
+
41
+ def collection_name
42
+ @collection_name ||= model_name.plural.to_s
43
+ end
44
+ alias_method('table_name', 'collection_name')
45
+
46
+ def collection_name=(collection_name)
47
+ @collection_name = collection_name.to_s
48
+ end
49
+ alias_method('set_collection_name', 'collection_name=')
50
+ alias_method('table_name=', 'collection_name=')
51
+ alias_method('set_table_name', 'collection_name=')
52
+ end
53
+
54
+ def persisted
55
+ !!(defined?(@persisted) ? @persisted : @model ? @model.persisted? : !id.blank?)
56
+ end
57
+ def persisted?
58
+ persisted
59
+ end
60
+ def persisted=(value)
61
+ @persisted = !!value
62
+ end
63
+ def persisted!
64
+ self.persisted = true
65
+ end
66
+
67
+ def new_record
68
+ !!(defined?(@new_record) ? @new_record : @model ? @model.new_record? : id.blank?)
69
+ end
70
+ def new_record?
71
+ new_record
72
+ end
73
+ def new_record=(value)
74
+ @new_record = !!value
75
+ end
76
+ def new_record!
77
+ self.new_record = true
78
+ end
79
+
80
+ def destroyed
81
+ !!(defined?(@destroyed) ? @destroyed : @model ? @model.destroyed : id.blank?)
82
+ end
83
+ def destroyed?
84
+ destroyed
85
+ end
86
+ def destroyed=(value)
87
+ @destroyed = !!value
88
+ end
89
+ def destroyed!
90
+ self.destroyed = true
91
+ end
92
+
93
+ def read_attribute_for_validation(key)
94
+ get(key)
95
+ end
96
+
97
+ end
98
+ end
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Conducer
3
4
  class Attributes < ::Map
@@ -0,0 +1,58 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Dao
3
+ class << Conducer
4
+ def autocrud!
5
+ include(Conducer::AutoCRUD)
6
+ end
7
+ alias_method('crud!', 'autocrud!')
8
+ end
9
+
10
+ class Conducer
11
+ module AutoCRUD
12
+ Code = proc do
13
+ class << self
14
+ def db
15
+ @db ||= Db.instance
16
+ end
17
+
18
+ def db_collection
19
+ db.collection(collection_name)
20
+ end
21
+
22
+ def all(*args)
23
+ hashes = db_collection.all()
24
+ hashes.map{|hash| new(hash)}
25
+ end
26
+
27
+ def find(*args)
28
+ options = args.extract_options!.to_options!
29
+ id = args.shift || options[:id]
30
+ hash = db_collection.find(id)
31
+ new(hash) if hash
32
+ end
33
+ end
34
+
35
+ def save
36
+ id = self.class.db_collection.save(@attributes)
37
+ @attributes.set(:id => id)
38
+ true
39
+ end
40
+
41
+ def destroy
42
+ id = self.id
43
+ if id
44
+ self.class.db_collection.destroy(id)
45
+ @attributes.rm(:id)
46
+ end
47
+ id
48
+ end
49
+ end
50
+
51
+ def AutoCRUD.included(other)
52
+ super
53
+ ensure
54
+ other.module_eval(&Code)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Dao
3
+ class Conducer
4
+ CallbackSupport = proc do
5
+ include Wrap
6
+
7
+ class << self
8
+ def method_missing(method, *args, &block)
9
+ case method.to_s
10
+ when %r/\A(before|after)_(.*)\Z/
11
+ lifecycle, method = $1, $2
12
+ send(lifecycle, method, *args, &block)
13
+ else
14
+ super
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,45 @@
1
+ module Dao
2
+ class Conducer
3
+ class << Conducer
4
+ fattr(:collection_class)
5
+
6
+ def build_collection_class!
7
+ conducer_class = self
8
+ collection_class = const_set(:Collection, Class.new(Collection){})
9
+ collection_class.conducer_class = conducer_class
10
+ conducer_class.collection_class = collection_class
11
+ end
12
+
13
+ def collection_for(models, *args, &block)
14
+ collection_class.load(models, *args, &block)
15
+ end
16
+ end
17
+
18
+ class Collection < ::Array
19
+ class << Collection
20
+ fattr(:conducer_class)
21
+
22
+ def load(*args, &block)
23
+ new.tap{|collection| collection.load(*args, &block)}
24
+ end
25
+ end
26
+
27
+ fattr(:models)
28
+
29
+ def conducer_class
30
+ self.class.conducer_class
31
+ end
32
+
33
+ def load(models, *args, &block)
34
+ block ||= proc{|model| conducer_class.new(model, *args) }
35
+ (self.models = models).each{|model| self << block.call(model, *args)}
36
+ self
37
+ end
38
+
39
+ def method_missing(method, *args, &block)
40
+ return(models.send(method, *args, &block)) if models.respond_to?(method)
41
+ super
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,104 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Dao
3
+ class Conducer
4
+ ControllerSupport = proc do
5
+ ##
6
+ #
7
+ def controller
8
+ unless defined?(@controller)
9
+ set_controller(Conducer.controller)
10
+ end
11
+ @controller
12
+ end
13
+
14
+ def controller=(controller)
15
+ set_controller(controller)
16
+ end
17
+
18
+ def set_controller(controller)
19
+ @controller = controller
20
+ ensure
21
+ default_url_options[:protocol] = @controller.request.protocol
22
+ default_url_options[:host] = @controller.request.host
23
+ default_url_options[:port] = @controller.request.port
24
+ @action = Action.new(@controller.send(:action_name).to_s, self)
25
+ end
26
+
27
+ ##
28
+ #
29
+ class Action < ::String
30
+ fattr :conducer
31
+
32
+ def initialize(action, conducer = nil)
33
+ super(action.to_s.downcase.strip)
34
+ @conducer = conducer
35
+ end
36
+
37
+ def action
38
+ to_s
39
+ end
40
+
41
+ def ==(other)
42
+ super(other.to_s)
43
+ end
44
+
45
+ Synonyms = {
46
+ 'new' => 'create',
47
+ 'create' => 'new',
48
+
49
+ 'edit' => 'update',
50
+ 'update' => 'edit'
51
+ }
52
+
53
+ def call(method, *args, &block)
54
+ return unless conducer
55
+
56
+ action_method = "#{ method }_for_#{ action }"
57
+
58
+ return Dao.call(conducer, action_method, *args, &block) if conducer.respond_to?(action_method)
59
+
60
+ if((synonym = Synonyms[action]))
61
+ action_method = "#{ method }_for_#{ synonym }"
62
+ return Dao.call(conducer, action_method, *args, &block) if conducer.respond_to?(action_method)
63
+ end
64
+
65
+ nil
66
+ end
67
+ end
68
+
69
+ def action
70
+ unless defined?(@action)
71
+ set_action(:new)
72
+ end
73
+ @action
74
+ end
75
+
76
+ def set_action(action)
77
+ unless action.is_a?(Action)
78
+ action = Action.new(action)
79
+ end
80
+ action.conducer = self
81
+ @action = action
82
+ end
83
+
84
+ def action=(action)
85
+ set_action(action)
86
+ end
87
+
88
+ ##
89
+ #
90
+ controller_delegates = %w(
91
+ render
92
+ render_to_string
93
+ )
94
+
95
+ controller_delegates.each do |method|
96
+ module_eval <<-__, __FILE__, __LINE__
97
+ def #{ method }(*args, &block)
98
+ controller.#{ method }(*args, &block)
99
+ end
100
+ __
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,9 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Dao
3
+ class Conducer
4
+ def nav_for(name, &block)
5
+ Nav.new(name, &block).for(controller)
6
+ end
7
+ alias_method(:nav, :nav_for)
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Dao
3
+ class Conducer
4
+ ViewSupport = proc do
5
+ include Tagz.globally
6
+
7
+ class << Conducer
8
+ include Tagz.globally
9
+ end
10
+
11
+ url_helpers = Rails.application.try(:routes).try(:url_helpers)
12
+ include(url_helpers) if url_helpers
13
+ include(ActionView::Helpers) if defined?(ActionView::Helpers)
14
+ end
15
+ end
16
+ end
data/lib/dao/data.rb CHANGED
@@ -1,9 +1,10 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Data < ::Map
3
4
  # look good for inspect
4
5
  #
5
6
  def inspect
6
- ::JSON.pretty_generate(self, :max_nesting => 0)
7
+ Dao.json_for(self)
7
8
  end
8
9
 
9
10
  # support updates with dao-ish objects
data/lib/dao/db.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # -*- encoding : utf-8 -*-
2
+
1
3
  require 'yaml'
2
4
  require 'yaml/store'
3
5
  require 'fileutils'
data/lib/dao/endpoint.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Endpoint
3
4
  Attrs = %w( api path route block doc )
data/lib/dao/engine.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  if(defined?(Rails) && Rails::VERSION::MAJOR == 3)
3
4
  class Engine < Rails::Engine
data/lib/dao/errors.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- encoding : utf-8 -*-
1
2
  module Dao
2
3
  class Errors < ::Map
3
4
  # for html generation
@@ -18,23 +19,18 @@ module Dao
18
19
  # you can tweak these if you want
19
20
  #
20
21
  Global = '*' unless defined?(Global)
21
- #Separator = "\342\207\222" unless defined?(Separator) ### this is an "Open-outlined rightward arrow"
22
- Separator = ":" unless defined?(Separator)
22
+ Separator = "\342\207\222" unless defined?(Separator) ### this is an "Open-outlined rightward arrow"
23
+ #Separator = ":" unless defined?(Separator)
23
24
 
24
25
  # messages know when they're sticky
25
26
  #
26
27
  class Message < ::String
27
- attr_accessor :sticky
28
+ attr_accessor :source
28
29
 
29
30
  def initialize(*args)
30
31
  options = Map.options_for!(args)
31
32
  replace(args.join(' '))
32
- @sticky = options[:sticky]
33
- end
34
-
35
- def sticky?
36
- @sticky ||= nil
37
- !!@sticky
33
+ self.source = options[:source]
38
34
  end
39
35
 
40
36
  def to_s
@@ -58,94 +54,114 @@ module Dao
58
54
  @object = args.shift
59
55
  end
60
56
 
61
- def errors
62
- self
63
- end
64
-
65
57
  def [](key)
66
- self[key] = Array.new unless has_key?(key)
58
+ return [] unless has_key?(key)
67
59
  super
68
60
  end
69
61
 
62
+ def errors
63
+ self
64
+ end
65
+
70
66
  def size
71
67
  size = 0
72
- depth_first_each{|key, val| size += Array(val).size}
68
+ depth_first_each do |keys, value|
69
+ size += Array(value).size
70
+ end
73
71
  size
74
72
  end
75
73
  alias_method('count', 'size')
76
74
  alias_method('length', 'size')
77
75
 
76
+ def empty?
77
+ size == 0
78
+ end
79
+
78
80
  def add(*args)
81
+ return relay(args.first) if args.size == 1 and relay?(args.first)
79
82
  options = Map.options_for!(args)
80
- sticky = options[:sticky]
83
+
81
84
  clear = options[:clear]
85
+ source = options[:source]
82
86
 
83
87
  args.flatten!
84
- message = args.pop
85
- keys = args
86
- keys = [Global] if keys.empty?
87
- errors = Hash.new
88
88
 
89
- if Array(keys) == [Global]
90
- sticky = true unless options.has_key?(:sticky)
91
- end
89
+ message = args.pop or raise(ArgumentError, 'no message!')
90
+ key = args.empty? ? [Global] : args
92
91
 
93
- sticky = true if(message.respond_to?(:sticky?) and message.sticky?)
94
-
95
- if message
96
- if message.respond_to?(:full_messages)
97
- message.depth_first_each do |keys, msg|
98
- errors[keys] = Message.new(msg, :sticky => sticky)
92
+ if message.is_a?(Hash) or message.respond_to?(:full_messages)
93
+ message.each do |k, v|
94
+ Array(v).each do |msg|
95
+ add(key + [k], msg)
99
96
  end
100
- else
101
- errors[keys] = Message.new(message, :sticky => sticky)
102
97
  end
103
- else
104
- raise(ArgumentError, 'no message!')
98
+ return(self)
105
99
  end
106
100
 
107
- message = Message.new(message) unless message.is_a?(Message)
101
+ message = message.is_a?(Message) ? message : Message.new(message)
102
+ message.source = source
108
103
 
109
- result = []
104
+ set(key => []) unless has?(key)
105
+ list = get(key)
106
+ list.clear if clear
107
+ list.push(message)
108
+ list.uniq!
109
+ list
110
+ self
111
+ end
112
+ alias_method('add!', 'add')
113
+ alias_method('add_to_base', 'add')
114
+ alias_method('add_to_base!', 'add!')
110
115
 
111
- errors.each do |keys, message|
112
- list = get(keys)
113
- unless has?(keys)
114
- set(keys => [])
115
- list = get(keys)
116
- end
117
- list.clear if clear
118
- list.push(message)
119
- result = list
116
+ def relay(other, options = {})
117
+ case
118
+ when other.respond_to?(:each)
119
+ other.each do |key, messages|
120
+ Array(messages).each do |message|
121
+ add(key, message, options = {})
122
+ end
123
+ end
124
+ when other.respond_to?(:each_pair)
125
+ other.each_pair do |key, messages|
126
+ Array(messages).each do |message|
127
+ add(key, message, options = {})
128
+ end
129
+ end
130
+
131
+ when other.respond_to?(:each_slice)
132
+ Array(other).flatten.each_slice(2) do |key, messages|
133
+ Array(messages).each do |message|
134
+ add(key, message, options = {})
135
+ end
136
+ end
137
+
138
+ else
139
+ raise(ArgumentError, other.class.name)
120
140
  end
121
-
122
- result
141
+ self
123
142
  end
124
143
 
125
- alias_method('add_to_base', 'add')
126
-
127
- def add!(*args)
128
- options = Map.new(args.last.is_a?(Hash) ? args.last : {})
129
- options[:sticky] = true
130
- args.push(options)
131
- add(*args)
144
+ def relay?(arg)
145
+ [:each, :each_pair, :each_slice].any?{|method| arg.respond_to?(method)}
132
146
  end
133
147
 
134
- alias_method('add_to_base!', 'add!')
148
+ def add_from_source(keys, callback, message)
149
+ add(keys, message, :source => callback)
150
+ self
151
+ end
135
152
 
136
- alias_method('clear!', 'clear')
153
+ def delete_from_source(keys, callback)
154
+ if((messages = errors.on(keys)))
155
+ messages.delete_if{|m| m.respond_to?(:source) and m.source==callback}
156
+ rm(*keys) if messages.empty?
157
+ end
158
+ self
159
+ end
137
160
 
138
161
  def clear
139
- keep = []
140
- depth_first_each do |keys, message|
141
- index = keys.pop
142
- args = [keys, message].flatten
143
- keep.push(args) if message.sticky?
144
- end
145
- clear!
146
- ensure
147
- keep.each{|args| add!(*args)}
162
+ super
148
163
  end
164
+ alias_method('clear!', 'clear')
149
165
 
150
166
  def invalid?(*keys)
151
167
  has?(keys) and !get(keys).nil?
@@ -164,7 +180,6 @@ module Dao
164
180
  depth_first_each do |keys, value|
165
181
  index = keys.pop
166
182
  key = keys
167
- #key = keys.join('.')
168
183
  value = value.to_s
169
184
  next if value.strip.empty?
170
185
  if key == Global
@@ -217,41 +232,36 @@ module Dao
217
232
  errors = [error, *args].flatten.compact
218
233
 
219
234
  at_least_one_error = false
220
- css_class = options[:class] || 'errors dao'
221
-
222
- to_html =
223
- div_(:class => css_class){
224
- __
225
-
226
- div_(:class => :caption){ "We're so sorry, but can you please fix the following errors?" }
227
- __
228
-
229
- ul_{
230
- __
231
- errors.each do |e|
232
- e.full_messages.each do |key, message|
233
- at_least_one_error = true
234
- title = Array(key).join(' ').titleize
235
-
236
- error_class = Array(key)==Array(Global) ? "global-error" : "field-error"
237
- title_class = "title"
238
- separator_class = "separator"
239
- message_class = "message"
240
-
241
- li_(:class => error_class){
242
- span_(:class => title_class){ title }
243
- span_(:class => separator_class){ " #{ Separator } " }
244
- span_(:class => message_class){ message }
245
- }
246
- __
247
- end
248
- end
249
- __
250
- }
251
- __
252
- }
253
235
 
254
- at_least_one_error ? to_html : ''
236
+ emap = Map.new
237
+
238
+ errors.each do |e|
239
+ e.full_messages.each do |key, message|
240
+ at_least_one_error = true
241
+ emap[key] ||= message
242
+ end
243
+ end
244
+
245
+ return "" unless at_least_one_error
246
+
247
+ div_(:class => "dao errors summary"){
248
+ __
249
+
250
+ h3_(:class => "caption"){ "We're so sorry, but can you please fix the following errors?" }
251
+ __
252
+
253
+ dl_(:class => "list"){
254
+ emap.each do |key, message|
255
+ title = Array(key).join(" ").titleize
256
+
257
+ type = Array(key) == Array(Global) ? "global" : "field"
258
+
259
+ dt_(:class => "title #{ type }"){ title }
260
+ dd_(:class => "message #{ type }"){ message }
261
+ end
262
+ }
263
+ __
264
+ }
255
265
  end
256
266
 
257
267
  def to_s(*args, &block)