jasonette-rails 0.1.2 → 0.2.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/Rakefile +0 -1
  4. data/lib/jasonette-rails.rb +1 -0
  5. data/lib/jasonette.rb +26 -11
  6. data/lib/jasonette/action_view_extensions.rb +15 -0
  7. data/lib/jasonette/core/action.rb +34 -0
  8. data/lib/jasonette/core/base.rb +177 -60
  9. data/lib/jasonette/core/body.rb +14 -0
  10. data/lib/jasonette/core/body/footer.rb +7 -0
  11. data/lib/jasonette/core/body/footer/input.rb +24 -0
  12. data/lib/jasonette/core/body/footer/tabs.rb +11 -0
  13. data/lib/jasonette/core/body/header.rb +21 -0
  14. data/lib/jasonette/core/body/header/search.rb +6 -0
  15. data/lib/jasonette/core/body/layers.rb +4 -0
  16. data/lib/jasonette/core/body/sections.rb +5 -0
  17. data/lib/jasonette/core/components.rb +0 -9
  18. data/lib/jasonette/core/data.rb +4 -0
  19. data/lib/jasonette/core/item.rb +21 -0
  20. data/lib/jasonette/core/items.rb +99 -14
  21. data/lib/jasonette/core/layout.rb +2 -5
  22. data/lib/jasonette/core/map.rb +6 -0
  23. data/lib/jasonette/core/options.rb +9 -0
  24. data/lib/jasonette/{jason/body/header.rb → core/pins.rb} +1 -1
  25. data/lib/jasonette/core/properties.rb +151 -22
  26. data/lib/jasonette/engine.rb +10 -0
  27. data/lib/jasonette/handler.rb +14 -0
  28. data/lib/jasonette/helpers.rb +38 -0
  29. data/lib/jasonette/jason/body.rb +2 -9
  30. data/lib/jasonette/jason/head.rb +22 -2
  31. data/lib/jasonette/jason/head/actions.rb +5 -0
  32. data/lib/jasonette/jason/head/templates.rb +5 -0
  33. data/lib/jasonette/railtie.rb +30 -0
  34. data/lib/jasonette/template.rb +201 -0
  35. data/lib/jasonette/version.rb +1 -1
  36. metadata +55 -23
  37. data/lib/jasonette/core/sections.rb +0 -9
  38. data/lib/jasonette/jason/body/header/search.rb +0 -5
  39. data/lib/jasonette/jbuilder_extensions.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 39794fe45086a5290dc3abf8c29b6f5cd5ae1732
4
- data.tar.gz: 1605bc7f687b06e1f334a9a8ebd93184c37da87b
3
+ metadata.gz: 89ec6352c3bb86dd49af440b735535264434176d
4
+ data.tar.gz: ed9f0f8ed31dca762ef2d576f240a3a57221b299
5
5
  SHA512:
6
- metadata.gz: f6c7f19ecbd1e78f7c8aa02a58b3b21f7a131aa36600559d23a7b8e45d8a1ba5a0106f29c5a881accf32352f78db524e234a7f63a397369c412248bb2629278c
7
- data.tar.gz: 8e6470e787e737536b47427027464feb7d0a0f79c1d8f25182b88a88ac1a3f1c3db3a82c9bdff0abb70be1d11bbc64a46278dae73cb5488b4a06be3e283764ee
6
+ metadata.gz: f248d2b865dffc64cdfabd1d32e558f8aa54661a2b71faed45ec0fb762db51642feb98f016d6615246657817f132d502f43e697f7ff96c28402b16c5e8073482
7
+ data.tar.gz: dd6ff575d3beb33b39a04cf6bba7282423f6c4c6ea7fa668302d74f44445e95e27e94968d80769f9d86bdc3feff0ce337baed15cb7fb5ddfd1cdf6c7f8e9bded
data/README.md CHANGED
@@ -4,7 +4,8 @@ flavored JSON in Rails.
4
4
 
5
5
  ## ALPHA code!
6
6
 
7
- Warning: This project is **alpha** code and still in highly experimental stage and subjected to
7
+ Warning: Work in progress. Proceed with caution. Testers and contributions are welcome.
8
+ This project is **alpha** code and still in highly experimental stage and subjected to
8
9
  drastic changes to the DSL. It is also quite full of bugs despite the unit tests you may find herein!
9
10
 
10
11
  Note: Almost nothing about this gem is documented, however, you can find ample examples in the project's
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  begin
2
2
  require 'bundler/setup'
3
- require 'bundler/gem_tasks'
4
3
  Bundler::GemHelper.install_tasks
5
4
  rescue LoadError
6
5
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
@@ -1 +1,2 @@
1
1
  require_relative 'jasonette'
2
+ require_relative 'jasonette/railtie'
@@ -1,24 +1,39 @@
1
- require 'rails/railtie'
2
- require 'jbuilder/jbuilder_template'
3
-
4
- module Jasonette
5
- end
6
-
7
1
  # Core components for library
8
2
  require_relative 'jasonette/core/properties'
9
3
  require_relative 'jasonette/core/base'
10
4
  require_relative 'jasonette/core/style'
11
- require_relative 'jasonette/core/sections'
5
+ require_relative 'jasonette/core/item'
12
6
  require_relative 'jasonette/core/items'
13
7
  require_relative 'jasonette/core/layout'
8
+ require_relative 'jasonette/core/map'
9
+ require_relative 'jasonette/core/pins'
14
10
  require_relative 'jasonette/core/components'
11
+ require_relative 'jasonette/core/options'
12
+ require_relative 'jasonette/core/action'
13
+ require_relative 'jasonette/core/data'
14
+ require_relative 'jasonette/core/body'
15
+ require_relative 'jasonette/core/body/header'
16
+ require_relative 'jasonette/core/body/header/search'
17
+ require_relative 'jasonette/core/body/footer'
18
+ require_relative 'jasonette/core/body/footer/input'
19
+ require_relative 'jasonette/core/body/footer/tabs'
20
+ require_relative 'jasonette/core/body/sections'
21
+ require_relative 'jasonette/core/body/layers'
15
22
 
16
23
  # Structural components
17
24
  require_relative 'jasonette/jason'
18
25
  require_relative 'jasonette/jason/head'
26
+ require_relative 'jasonette/jason/head/actions'
27
+ require_relative 'jasonette/jason/head/templates'
19
28
  require_relative 'jasonette/jason/body'
20
- require_relative 'jasonette/jason/body/header'
21
- require_relative 'jasonette/jason/body/header/search'
22
29
 
23
- # Inject Jasonette into Jbuilder
24
- require_relative 'jasonette/jbuilder_extensions'
30
+ module Jasonette
31
+ def self.setup
32
+ yield self
33
+ end
34
+
35
+ # :dump_options, :load_options
36
+ def self.multi_json
37
+ yield ::MultiJson
38
+ end
39
+ end
@@ -0,0 +1,15 @@
1
+ module Jasonette
2
+ module TemplateRendererExtensions
3
+ def render(context, options)
4
+ @details = extract_details(options)
5
+ path, locals = options[:layout], options[:locals] || {}
6
+ layout = path && find_layout(path, locals.keys, [formats.first])
7
+ if !layout.try(:virtual_path).nil?
8
+ JasonSingleton.fetch(context).__layout = layout
9
+ JasonSingleton.fetch(context).__locals = locals
10
+ end
11
+ super
12
+ end
13
+ end
14
+ ::ActionView::TemplateRenderer.send(:prepend, TemplateRendererExtensions)
15
+ end
@@ -0,0 +1,34 @@
1
+ module Jasonette
2
+ class Action < Jasonette::Base
3
+ property :options
4
+ property :success
5
+ property :error
6
+
7
+ def trigger name, &block
8
+ with_attributes do
9
+ set! "trigger", name
10
+ encode(&block) if block_given?
11
+ end
12
+ end
13
+
14
+ def render!
15
+ set! "type", "$render"
16
+ end
17
+
18
+ def reload!
19
+ set! "type", "$reload"
20
+ end
21
+
22
+ def success &block
23
+ @success = Jasonette::Action.new(context) do
24
+ block_given? ? encode(&block) : render!
25
+ end
26
+ self
27
+ end
28
+
29
+ def error &block
30
+ @error = Jasonette::Action.new(context, &block)
31
+ self
32
+ end
33
+ end
34
+ end
@@ -1,20 +1,17 @@
1
1
  module Jasonette
2
2
  class Base
3
3
  include Properties
4
- include ActionView::Helpers
5
4
 
6
5
  def implicit_set! name, *args, &block
7
- with_attributes do
8
- if properties.include? name
9
- property_set! name, *args, &block
10
- else
11
- json.set!(name) { instance_eval(&block) }
12
- end
6
+ if property_names.include? name
7
+ with_attributes { property_set! name, *args, &block }
8
+ else
9
+ set!(name) { encode(&block) }
13
10
  end
14
11
  end
15
12
 
16
13
  def attr_value name
17
- if properties.include? name
14
+ if property_names.include? name
18
15
  instance_variable_get :"@#{name}"
19
16
  else
20
17
  @attributes[name.to_s]
@@ -25,104 +22,224 @@ module Jasonette
25
22
  if ::Kernel.block_given?
26
23
  implicit_set! name, *args, &block
27
24
  else
28
- if properties.include? name
25
+ if property_names.include? name
29
26
  return property_get! name
30
27
  else
31
- with_attributes { json.set! name, *args }
28
+ set! name, *args if args.present?
32
29
  end
33
30
  end
34
- self
35
31
  end
36
32
 
37
33
  attr_reader :context
38
34
  attr_reader :attributes
39
- attr_reader :json
40
35
 
41
36
  def initialize context
42
37
  @context = context
43
38
  @attributes = {}
44
- instance_eval(&::Proc.new) if ::Kernel.block_given?
39
+
40
+ encode(&::Proc.new) if ::Kernel.block_given?
45
41
  end
46
42
 
47
- def trigger name, &block
48
- with_attributes do
49
- json.trigger name
50
- instance_eval(&block) if block_given?
43
+ # Fixed for below error :
44
+ # IOError - not opened for reading:
45
+ # activesupport (5.0.1) lib/active_support/core_ext/object/json.rb:130:in `as_json'
46
+ # Eventually called by multi_json/adapter.rb:25:in `dump'
47
+ def as_json(options = nil)
48
+ attributes!
49
+ end
50
+
51
+ def encode
52
+ binding = eval "self", ::Proc.new.binding
53
+ if (binding.method(:encode).parameters.first.include?(:req) rescue false)
54
+ binding.encode(self, &::Proc.new)
55
+ else
56
+ instance_eval(&::Proc.new)
51
57
  end
58
+ self
52
59
  end
53
60
 
54
- def action name="action", &block
55
- with_attributes do
56
- json.set! name do
57
- block_given? ? instance_eval(&block) : success { type "$render" }
58
- end
61
+ def empty?
62
+ properties_empty? && @attributes.empty?
63
+ end
64
+
65
+ def klass name
66
+ set! "class", name
67
+ end
68
+ alias :css_class :klass
69
+
70
+ def _method name = nil
71
+ if block_given?
72
+ set! 'method', _scope { yield }
73
+ else
74
+ set! 'method', name
59
75
  end
60
76
  end
77
+ alias :action_method :_method
78
+
79
+ def with_attributes
80
+ @attributes.merge! _scope { yield self }
81
+ self
82
+ end
61
83
 
62
- def render!
63
- with_attributes { json.type "$render" }
84
+ def inline json
85
+ @attributes.merge! JSON.parse(json)
86
+ self
64
87
  end
65
88
 
66
- def reload!
67
- with_attributes { json.type "$reload" }
89
+ def attributes!
90
+ merge_properties
91
+ @attributes
68
92
  end
69
93
 
70
- def success &block
71
- with_attributes do
72
- if block_given?
73
- json.success { instance_eval(&block) }
94
+ def set! key, value=nil, *args
95
+ result = if ::Kernel.block_given?
96
+ if !_blank?(value)
97
+ # comments @post.comments { |comment| ... }
98
+ # { "comments": [ { ... }, { ... } ] }
99
+ _scope{ array! value, &::Proc.new }
100
+ else
101
+ # comments { ... }
102
+ # { "comments": ... }
103
+ _merge_block(key){ yield self }
104
+ end
105
+ elsif args.empty?
106
+ if _is_collection?(value) || Jasonette::Base === value
107
+ # person another_jasonette
108
+ # { "person": { ... } }
109
+ # comments [ { content: "...", created_at: "..." } ]
110
+ # { "comments": [ { "content": "hello", "created_at": "..." } ] }
111
+ # comments { content: "...", created_at: "..." }
112
+ # { "comments": [ { "content": "hello", "created_at": "..." } ] }
113
+ _scope{ merge! value }
74
114
  else
75
- json.success { json.type "$render" }
115
+ _key(value)
76
116
  end
117
+ elsif _is_collection?(value)
118
+ # comments @post.comments, :content, :created_at
119
+ # { "comments": [ { "content": "hello", "created_at": "..." }, { "content": "world", "created_at": "..." } ] }
120
+ _scope{ array! value, *args }
121
+ else
122
+ # author @post.creator, :name, :email_address
123
+ # { "author": { "name": "David", "email_address": "david@loudthinking.com" } }
124
+ _merge_block(key){ extract! value, *args }
77
125
  end
78
- end
79
126
 
80
- def target!
81
- attributes!.to_json
127
+ _set_key_value key, result
128
+ self
82
129
  end
83
130
 
84
- def encode
85
- instance_eval(&::Proc.new)
86
- self
131
+
132
+ def array! collection = [], *args
133
+ array = if collection.nil?
134
+ []
135
+ elsif ::Kernel.block_given?
136
+ _map_collection(collection, &::Proc.new)
137
+ else
138
+ _map_collection(collection) { |element| extract! element, *args }
139
+ end
140
+
141
+ merge! array
87
142
  end
88
143
 
89
- def empty?
90
- properties_empty? && @attributes.empty?
144
+ def extract! object, *attributes
145
+ if ::Hash === object
146
+ _extract_hash_values(object, attributes)
147
+ elsif Jasonette::Base === object
148
+ _extract_hash_values(object.attributes!, attributes)
149
+ else
150
+ _extract_method_values(object, attributes)
151
+ end
91
152
  end
92
153
 
93
- def klass name
94
- json.set! "class", name
154
+ def merge! key
155
+ case key
156
+ when Jasonette::Base
157
+ merge! key.attributes!
158
+ when Hash
159
+ key.each{ |key, value| set! _key(key), value }
160
+ when Array
161
+ _set_value key
162
+ end
163
+ @attributes
95
164
  end
96
- alias :css_class :klass
97
165
 
98
- def with_attributes
99
- if json
100
- instance_eval(&::Proc.new)
101
- return self
166
+ private
167
+
168
+ def _extract_hash_values(object, attributes)
169
+ if attributes.blank?
170
+ object.each{ |key, value| _set_key_value key, value }
171
+ else
172
+ attributes.each{ |key| _set_key_value key, object.fetch(key) }
102
173
  end
103
- template = JbuilderTemplate.new(context) do |json|
104
- @json = json
105
- instance_eval(&::Proc.new)
106
- @json = nil
174
+ end
175
+
176
+ def _extract_method_values(object, attributes)
177
+ if attributes.blank?
178
+ _set_value object
179
+ else
180
+ attributes.each{ |key| _set_key_value key, object.public_send(key) }
107
181
  end
108
- @attributes.merge! template.attributes!
109
- self
110
182
  end
111
183
 
112
- def inline json
113
- @attributes.merge! JSON.parse(json)
114
- self
184
+ def _merge_block(key)
185
+ current_value = @attributes.fetch(_key(key), {})
186
+ new_value = _scope{ yield self }
187
+ _merge_values(current_value, new_value)
115
188
  end
116
189
 
117
- def inline! name, *args
118
- with_attributes do
119
- json.partial! name, *args
190
+ def _merge_values(current_value, updates)
191
+ if _blank?(updates)
192
+ current_value
193
+ elsif _blank?(current_value) || updates.nil? || current_value.empty? && ::Array === updates
194
+ updates
195
+ elsif ::Array === current_value && ::Array === updates
196
+ current_value + updates
197
+ elsif ::Hash === current_value && ::Hash === updates
198
+ current_value.merge(updates)
199
+ else
200
+ raise "MergeError"
120
201
  end
121
202
  end
122
203
 
123
- def attributes!
124
- merge_properties
204
+ def _key(key)
205
+ key.to_s
206
+ end
207
+
208
+ def _set_key_value(key, value)
209
+ raise "ArrayError" if ::Array === @attributes
210
+ @attributes[_key(key)] = value unless _blank?(value)
211
+ end
212
+
213
+ def _set_value(value)
214
+ raise "HashError" if ::Hash === @attributes && !_blank?
215
+ @attributes = value unless _blank?(value)
216
+ end
217
+
218
+ def _map_collection(collection)
219
+ collection.map do |element|
220
+ _scope{ yield element }
221
+ end # - [BLANK]
222
+ end
223
+
224
+ def _scope
225
+ parent_attributes = @attributes
226
+ @attributes = {}
227
+ yield
125
228
  @attributes
229
+ ensure
230
+ @attributes = parent_attributes
231
+ end
232
+
233
+ def _is_collection?(object)
234
+ _object_respond_to?(object, :map, :count) # && NON_ENUMERABLES.none?{ |klass| klass === object }
235
+ end
236
+
237
+ def _blank?(value=@attributes)
238
+ value.nil? ? true : value.blank?
239
+ end
240
+
241
+ def _object_respond_to?(object, *methods)
242
+ methods.all?{ |m| object.respond_to?(m) }
126
243
  end
127
244
  end
128
245
  end
@@ -0,0 +1,14 @@
1
+ module Jasonette
2
+ class Body < Jasonette::Base
3
+ property :header
4
+ property :footer
5
+ property :sections, :is_many
6
+ property :layers
7
+ property :style
8
+
9
+ def attributes!
10
+ super
11
+ @attributes.merge! layers.attributes!
12
+ end
13
+ end
14
+ end