jasonette-rails 0.1.2 → 0.2.0

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