breezy 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/assets/javascript/breezy.js +6067 -0
  3. data/lib/breezy.rb +0 -7
  4. data/lib/breezy/configuration.rb +9 -3
  5. data/lib/breezy/helpers.rb +1 -1
  6. data/lib/breezy/render.rb +1 -1
  7. data/lib/breezy/version.rb +1 -1
  8. data/lib/generators/breezy/view/templates/view.js +17 -0
  9. data/lib/generators/breezy/view/templates/view.js.breezy +2 -0
  10. data/lib/generators/breezy/view/templates/view.jsx +21 -0
  11. data/lib/generators/breezy/view/view_generator.rb +40 -7
  12. data/lib/install/mobile.rb +54 -0
  13. data/lib/install/templates/mobile/app.js +84 -0
  14. data/lib/install/templates/mobile/app.json +6 -0
  15. data/lib/install/templates/mobile/package.json +32 -0
  16. data/lib/install/templates/mobile/rn-cli.config.js +4 -0
  17. data/lib/install/templates/web/application.js +62 -0
  18. data/lib/install/web.rb +72 -0
  19. data/lib/tasks/install.rake +46 -0
  20. data/test/render_test.rb +2 -2
  21. data/test/test_helper.rb +2 -0
  22. metadata +37 -48
  23. data/README.md +0 -338
  24. data/lib/assets/javascripts/breezy.coffee +0 -4
  25. data/lib/assets/javascripts/breezy/component_url.coffee +0 -61
  26. data/lib/assets/javascripts/breezy/controller.coffee +0 -197
  27. data/lib/assets/javascripts/breezy/csrf_token.coffee +0 -9
  28. data/lib/assets/javascripts/breezy/doubly_linked_list.coffee +0 -57
  29. data/lib/assets/javascripts/breezy/parallel_queue.coffee +0 -35
  30. data/lib/assets/javascripts/breezy/progress_bar.coffee +0 -139
  31. data/lib/assets/javascripts/breezy/remote.coffee +0 -136
  32. data/lib/assets/javascripts/breezy/snapshot.coffee +0 -100
  33. data/lib/assets/javascripts/breezy/start.coffee +0 -60
  34. data/lib/assets/javascripts/breezy/utils.coffee +0 -174
  35. data/lib/breezy/active_support.rb +0 -21
  36. data/lib/breezy_template.rb +0 -320
  37. data/lib/breezy_template/deferment_extension.rb +0 -48
  38. data/lib/breezy_template/dependency_tracker.rb +0 -47
  39. data/lib/breezy_template/digestor.rb +0 -30
  40. data/lib/breezy_template/handler.rb +0 -43
  41. data/lib/breezy_template/partial_extension.rb +0 -87
  42. data/lib/breezy_template/search_extension.rb +0 -108
  43. data/lib/generators/breezy/install/install_generator.rb +0 -61
  44. data/lib/generators/breezy/install/templates/Default.js.jsx +0 -7
  45. data/lib/generators/breezy/install/templates/View.js.jsx +0 -7
  46. data/lib/generators/breezy/install/templates/boot.js +0 -5
  47. data/lib/generators/breezy/view/templates/view.js.jsx +0 -8
  48. data/test/blade_helper.rb +0 -22
  49. data/test/breezy_template_test.rb +0 -1095
  50. data/test/dependency_tracker_test.rb +0 -66
@@ -0,0 +1,46 @@
1
+ namespace :breezy do
2
+ desc "Verifies if any version of Yarn is installed"
3
+ task :verify_yarn do
4
+ begin
5
+ yarn_version = `yarn --version`
6
+ raise Errno::ENOENT if yarn_version.blank?
7
+ rescue Errno::ENOENT
8
+ $stderr.puts "Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/"
9
+ $stderr.puts "Exiting!" && exit!
10
+ end
11
+ end
12
+
13
+ desc "Verifies webpacker has been installed"
14
+ task "verify_webpacker" do
15
+ begin
16
+ require "webpacker/configuration"
17
+ rescue LoadError
18
+ $stderr.puts "Breezy's web install requires webpacker!"
19
+ $stderr.puts "https://github.com/rails/webpacker#installation"
20
+ $stderr.puts "Exiting!" && exit!
21
+ end
22
+ end
23
+
24
+ namespace :install do
25
+ desc "Install everything needed for breezy web"
26
+ task 'web' => ["breezy:verify_webpacker", "webpacker:verify_install"] do
27
+ template = File.expand_path("../install/web.rb", __dir__)
28
+ if Rails::VERSION::MAJOR >= 5
29
+ exec "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{template}"
30
+ else
31
+ exec "#{RbConfig.ruby} ./bin/rake rails:template LOCATION=#{template}"
32
+ end
33
+ end
34
+
35
+ desc "Install everything needed for breezy mobile"
36
+ task 'mobile' => ["breezy:verify_yarn"] do
37
+ template = File.expand_path("../install/mobile.rb", __dir__)
38
+ if Rails::VERSION::MAJOR >= 5
39
+ exec "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{template}"
40
+ else
41
+ exec "#{RbConfig.ruby} ./bin/rake rails:template LOCATION=#{template}"
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -100,13 +100,13 @@ class RenderTest < ActionController::TestCase
100
100
  def assert_breezy_html(content)
101
101
  assert_response 200
102
102
  view = @response.request.params['action'].camelcase
103
- assert_equal "<html><head><script type='text/javascript'>Breezy.replace((function(){return ({\"data\":#{content.to_json},\"view\":\"Render#{view}\",\"csrf_token\":\"secret\",\"assets\":[\"/app.js\"]});})());</script></head><body></body></html>", @response.body
103
+ assert_equal "<html><head><script type='text/javascript'>Breezy.replace((function(){var joints={};var cache={};var defers=[];return ({\"data\":#{content.to_json},\"screen\":\"Render#{view}\",\"csrf_token\":\"secret\",\"assets\":[\"/app.js\"],\"joints\":joints,\"defers\":defers});})());</script></head><body></body></html>", @response.body
104
104
  assert_equal 'text/html', @response.content_type
105
105
  end
106
106
 
107
107
  def assert_breezy_js(content)
108
108
  assert_response 200
109
- assert_equal '(function(){return ({"data":' + content.to_json + ',"view":"RenderSimpleRenderWithBreezy","csrf_token":"secret","assets":["/app.js"]});})()', @response.body
109
+ assert_equal '(function(){var joints={};var cache={};var defers=[];return ({"data":' + content.to_json + ',"screen":"RenderSimpleRenderWithBreezy","csrf_token":"secret","assets":["/app.js"],"joints":joints,"defers":defers});})()', @response.body
110
110
  assert_equal 'text/javascript', @response.content_type
111
111
  end
112
112
 
@@ -8,6 +8,8 @@ require 'active_record'
8
8
  require 'active_support/testing/autorun' if Rails.version >= '4'
9
9
  require 'active_support/test_case'
10
10
 
11
+ require 'breezy_template'
12
+
11
13
  ActiveSupport::TestCase.test_order = :random if ActiveSupport::TestCase.respond_to?(:test_order=)
12
14
  ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
13
15
  Rails.cache = ActiveSupport::Cache::MemoryStore.new
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: breezy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johny Ho
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-09 00:00:00.000000000 Z
11
+ date: 2017-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coffee-rails
@@ -25,45 +25,53 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: jbuilder
28
+ name: actionpack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
- version: '3.0'
33
+ version: '6.0'
34
34
  - - ">="
35
35
  - !ruby/object:Gem::Version
36
- version: '1.5'
36
+ version: '4.0'
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - "<"
42
42
  - !ruby/object:Gem::Version
43
- version: '3.0'
43
+ version: '6.0'
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: '1.5'
46
+ version: '4.0'
47
47
  - !ruby/object:Gem::Dependency
48
- name: actionpack
48
+ name: breezy_template
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - "<"
52
- - !ruby/object:Gem::Version
53
- version: '6.0'
54
51
  - - ">="
55
52
  - !ruby/object:Gem::Version
56
- version: '4.0'
53
+ version: '0'
57
54
  type: :runtime
58
55
  prerelease: false
59
56
  version_requirements: !ruby/object:Gem::Requirement
60
57
  requirements:
61
- - - "<"
62
- - !ruby/object:Gem::Version
63
- version: '6.0'
64
58
  - - ">="
65
59
  - !ruby/object:Gem::Version
66
- version: '4.0'
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: webpacker
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.0'
67
75
  - !ruby/object:Gem::Dependency
68
76
  name: rake
69
77
  requirement: !ruby/object:Gem::Requirement
@@ -112,21 +120,9 @@ executables: []
112
120
  extensions: []
113
121
  extra_rdoc_files: []
114
122
  files:
115
- - README.md
116
123
  - app/views/breezy/response.html.erb
117
- - lib/assets/javascripts/breezy.coffee
118
- - lib/assets/javascripts/breezy/component_url.coffee
119
- - lib/assets/javascripts/breezy/controller.coffee
120
- - lib/assets/javascripts/breezy/csrf_token.coffee
121
- - lib/assets/javascripts/breezy/doubly_linked_list.coffee
122
- - lib/assets/javascripts/breezy/parallel_queue.coffee
123
- - lib/assets/javascripts/breezy/progress_bar.coffee
124
- - lib/assets/javascripts/breezy/remote.coffee
125
- - lib/assets/javascripts/breezy/snapshot.coffee
126
- - lib/assets/javascripts/breezy/start.coffee
127
- - lib/assets/javascripts/breezy/utils.coffee
124
+ - lib/assets/javascript/breezy.js
128
125
  - lib/breezy.rb
129
- - lib/breezy/active_support.rb
130
126
  - lib/breezy/configuration.rb
131
127
  - lib/breezy/cookies.rb
132
128
  - lib/breezy/helpers.rb
@@ -136,25 +132,20 @@ files:
136
132
  - lib/breezy/xhr_headers.rb
137
133
  - lib/breezy/xhr_redirect.rb
138
134
  - lib/breezy/xhr_url_for.rb
139
- - lib/breezy_template.rb
140
- - lib/breezy_template/deferment_extension.rb
141
- - lib/breezy_template/dependency_tracker.rb
142
- - lib/breezy_template/digestor.rb
143
- - lib/breezy_template/handler.rb
144
- - lib/breezy_template/partial_extension.rb
145
- - lib/breezy_template/search_extension.rb
146
- - lib/generators/breezy/install/install_generator.rb
147
- - lib/generators/breezy/install/templates/Default.js.jsx
148
- - lib/generators/breezy/install/templates/View.js.jsx
149
- - lib/generators/breezy/install/templates/boot.js
135
+ - lib/generators/breezy/view/templates/view.js
150
136
  - lib/generators/breezy/view/templates/view.js.breezy
151
- - lib/generators/breezy/view/templates/view.js.jsx
137
+ - lib/generators/breezy/view/templates/view.jsx
152
138
  - lib/generators/breezy/view/view_generator.rb
153
- - test/blade_helper.rb
154
- - test/breezy_template_test.rb
139
+ - lib/install/mobile.rb
140
+ - lib/install/templates/mobile/app.js
141
+ - lib/install/templates/mobile/app.json
142
+ - lib/install/templates/mobile/package.json
143
+ - lib/install/templates/mobile/rn-cli.config.js
144
+ - lib/install/templates/web/application.js
145
+ - lib/install/web.rb
146
+ - lib/tasks/install.rake
155
147
  - test/breezy_test.rb
156
148
  - test/configuration_test.rb
157
- - test/dependency_tracker_test.rb
158
149
  - test/engine_test.rb
159
150
  - test/render_test.rb
160
151
  - test/test_helper.rb
@@ -181,13 +172,11 @@ rubyforge_project:
181
172
  rubygems_version: 2.4.5.1
182
173
  signing_key:
183
174
  specification_version: 4
184
- summary: Turbolinks for react and rails
175
+ summary: Rails integration for BreezyJS
185
176
  test_files:
186
- - test/blade_helper.rb
187
- - test/breezy_template_test.rb
188
177
  - test/breezy_test.rb
189
178
  - test/configuration_test.rb
190
- - test/dependency_tracker_test.rb
191
179
  - test/engine_test.rb
192
180
  - test/render_test.rb
193
181
  - test/test_helper.rb
182
+ has_rdoc:
data/README.md DELETED
@@ -1,338 +0,0 @@
1
- # Breezy
2
- Breezy makes it easy (even boring) to create single-page, multi-page, and sometimes-single-page applications with ReactJS and classic Rails.
3
-
4
- [![Sauce Test Status](https://saucelabs.com/browser-matrix/jho406-bensonhurst.svg)](https://saucelabs.com/u/jho406-bensonhurst)
5
-
6
- ## What you can do:
7
-
8
- 1. Page to page transitions without reloading
9
- 2. Russian Doll cache aware JS content with structural sharing that makes implementing `shouldComponentUpdate` as easy as extending ReactJS's `PureComponent`
10
- 3. Defered rendering of slow loading parts of your page without API endpoints (e.g. dashboards that load later on direct visits)
11
- 4. Async actions that load different parts of your page without API endpoints (e.g. pagination, infinite scroll)
12
-
13
-
14
- Breezy is the lovechild of Turbolinks (also a hard fork), Server Generated Javascript Responses (created with BreezyTemplates), and ReactJS that bring you all of the above features while keeping complexity low.
15
-
16
- Unlike Turbolink's view-over-the-wire approach, a Breezy app is content-over-the-wire to your ReactJS frontend. Each controller gets two views, one for your content that you write using the included BreezyTemplates, and the other for your markup which you write in ReactJS. Breezy features are achieved with `XMLHTTPRequest`s for the next page's content (or a branch of it via key paths) before firing a `breezy:load` event that you can use with `ReactDOM.render`.
17
-
18
- ## Quick Peek
19
- Starting with a Rails project with Breezy [installed](#installation), ReactJS in your asset pipeline, and [something](https://github.com/reactjs/react-rails) [to](https://github.com/Shopify/sprockets-commoner) transform JSX to JS.
20
-
21
- Add a route and controller as you normally would.
22
- ```ruby
23
- # config/routes.rb
24
- resources :posts
25
-
26
- # app/controllers/posts_controller.rb
27
- class PostsController < ApplicationController
28
- # Allow breezy to take over HTML requests
29
- before_action :use_breezy_html
30
-
31
- def index
32
- @greeting = 'hello'
33
- end
34
-
35
- def new
36
- ....some stuff here...
37
- end
38
- end
39
- ```
40
-
41
- Use the included BreezyTemplates to create your content.
42
-
43
- ```ruby
44
- #app/views/posts/index.js.breezy
45
-
46
- json.heading @greeting
47
-
48
- # `defer: :auto` will no-op the following block on a direct
49
- # visit, use null as a standin value, and append additional
50
- # javascript in the response to fetch only this content node
51
- # (no-oping other sibiling blocks) and graft it in the right
52
- # place on the client side.
53
- json.dashboard(defer: :auto) do
54
- sleep 10
55
- json.num_of_views 100
56
- end
57
-
58
- # Go ahead, use your rails helpers, including i18n.
59
- json.new_post_path new_post_path
60
-
61
- json.footer 'something'
62
- ```
63
-
64
- Then write your remaining view in JSX. The content you wrote earlier gets passed here.
65
-
66
- ```ruby
67
- # app/assets/javascripts/views/PostIndex.js.jsx
68
-
69
- App.Views.PostsIndex = function(json) {
70
- // Deferment will use `null` as the standin value.
71
- // Hence the need for `json.dashboard || {}`.
72
- // Breezy will then fetch the missing node
73
- // and call `ReactDOM.render` a second time
74
-
75
- var dashboard = json.dashboard || {};
76
-
77
- return (
78
- <h1> {json.heading}</h1>
79
- <div> {dashboard.num_of_views} </div>
80
-
81
- # Page to page without reloading
82
- <a href={json.new_post_path} data-bz-remote> Create </a>
83
-
84
- <div>{json.footer}</div>
85
- )
86
- }
87
- ```
88
-
89
- ## Installation
90
- Breezy does not include ReactJS, you'll have to download it seperately and include it in your path. Or just include [react-rails](https://github.com/reactjs/react-rails).
91
-
92
- ```
93
- gem 'breezy'
94
- ```
95
-
96
- Then use the provided installation generator:
97
- ```
98
- rails g breezy:install
99
- ```
100
-
101
- If you need to add breezy and JSX views:
102
- ```
103
- rails g breezy:view Posts new index
104
- ```
105
-
106
- # Navigation and Forms
107
- Breezy intercepts all clicks on `<a>` and all submits on `<form>` elements enabled with `data-bz-remote`. Breezy will `preventDefault` then make the same request using XMLHttpRequest with a content type of `.js`. If there's an existing request, Breezy will cancel it unless the `data-bz-remote-async` option is used.
108
-
109
- Once the response loads, a `breezy:load` event will be fired with the JS object that you created with BreezyTemplates. If you used the installation generator, the event will be set for you in the `<head>` element of your layout:
110
-
111
- ```javascript
112
- document.addEventListener('breezy:load', function(event){
113
- var props = {
114
- view: event.data.view,
115
- data: event.data.data
116
- }
117
- ReactDOM.render(React.createElement(window.App.Components.View, props), document.getElementById('app'));
118
- });
119
- ```
120
-
121
- ## The data-bz-* attribute API
122
-
123
- Attribute | default value | description
124
- -------------------|--------------------------|------------
125
- `data-bz-remote` | For `<a>` the default is `get`. For forms, the default is `post` if a method is not specified. | Use this to create seamless page to page transitions. Works for both links and forms. You can specify the request method by giving it a value, e.g `<a href='foobar' data-bz-remote=post>`. For forms, the request method of the form is used. `<form action=foobar method='post' data-bz-remote>`.
126
- `data-bz-remote-async` | `false` | Fires off an async request. Responses are pushed into a queue will be evaluated in order of click or submit.
127
- `data-bz-push-state` | `true` | Captures the element's URL in the browsers history. Normally used with `data-bz-remote-async`.
128
- `data-bz-silent` | false | To be used with the `breezy_silent?` ruby helper. Useful if you don't want to perform a redirect or render. Just return a 204, and Breezy will not fire a `breezy:load` event.
129
-
130
-
131
- # Events
132
- Event | Argument `originalEvent.data` | Notes
133
- ----------------------|--------------------------------|-------
134
- `breezy:load` | {data} | Triggered on document, when Breezy has succesfully loaded content, to be used with `ReactDOM.render`. Yes the key is a bit weird. You have to access it like so `event.data.data`.
135
- `breezy:click` | {url} | Triggered on the element when a form or a link enabled with data-bz-remote is clicked. Cancellable with event.preventDefault().
136
- `breezy:request-error` | null or {xhr} | Triggered on the element when on XHR onError (network issues) or when async option is used and recieves an error response.
137
- `breezy:request-start` | {url} | Triggered on the element just before a XHR request is made.
138
- `breezy:request-end` | {url} | Triggered on the element, when a XHR request is finished.
139
- `breezy:restore` | null | Triggered on document, when a page cached is loaded, just before `breezy:load`
140
-
141
- ## JS API Reference
142
-
143
- ### Breezy.visit
144
-
145
- Usage:
146
- ```javascript
147
- Breezy.visit(location)
148
- Breezy.visit(location, { pushState, silent, async })
149
- ```
150
- Performs an Application Visit to the given _location_ (a string containing a URL or path).
151
-
152
- - If the pushState option is specified, Breezy will determine wheather to add the visitation to the browsers history. The default value is `true`.
153
- - If async is specified, Breezy will make an async request and add the onload callback to a queue to be evaluated (calling `breezy:load`) in order of fire. The default value is `false`, this means if there's an existing request or a queue of async requests, Breezy will cancel all of them and give priority to the most recent call.
154
- - If silent is specified, a request header X-SILENT will be set. use in tadem with the `breezy_silent?` ruby method for when you want to perform an action but return a 204 instead of a redirect or render. Breezy will ignore 204s and will not attempt to fire `breezy:load`.
155
-
156
-
157
- ### Breezy.graftByKeypath
158
-
159
- Usage:
160
- ```javascript
161
- Breezy.graftByKeypath(keyPath, object, {type});
162
- ```
163
- Place a new object at the specified keypath of Breezy's content tree on the current page and across other pages in its cache. Parent objects are clone and `breezy:load` is finally called.
164
-
165
- When referencing an array of objects, you have the option of providing an id instead of an index. For example:
166
-
167
- ```
168
- a.b.some_array_element_id_of_your_choice=1.c.d
169
- ```
170
-
171
- If type is specified as `add`. Breezy will push the object at the keyPath (assuming its an array) instead of of replacing.
172
-
173
-
174
- ### Breezy.replace
175
- Usage:
176
- ```javascript
177
- Breezy.replace({data, title, csrf_token, assets})
178
- ```
179
- Replaces the current page content and triggers a `reload:load`. Normally used to inject content to Breezy on a direct visit. Breezy's generators will set this up for you.
180
-
181
- ## Ruby Helpers
182
-
183
-
184
- ### use_breezy_html
185
- Usage:
186
- ```ruby
187
- class PostController < ApplicationController
188
- before_action :use_breezy_html
189
- end
190
- ```
191
-
192
- On direct visits, Breezy will render an empty page. If you used the installation generator, Breezy will also inject your content view created by BreezyTemplates into a script header, then fire a `breezy:load` event that you can use with `ReactDOM.render`.
193
-
194
- ### breezy_silient?
195
- Usage:
196
-
197
- ```
198
- class PostController < ApplicationController
199
- def create
200
- ...
201
- if breezy_silent?
202
- ...
203
- end
204
- end
205
- end
206
- ```
207
-
208
- Used in conjuction with `data-bz-silent` for `204` responses. Great for when you want to run a job and don't want to render anything back to the client.
209
-
210
- ## BreezyTemplate Templates, your content view
211
- BreezyTemplates is a sibling of JBuilderTemplates, both inheriting from the same [parent](https://github.com/rails/jbuilder/blob/master/lib/jbuilder.rb). Unlike Jbuilder, BreezyTemplate generates Server Generated Javascript and has a few differences listed below.
212
-
213
- ###Partials
214
- Partials are only supported as an option on attribute or array! `set!`s.
215
- Usage:
216
-
217
- ```ruby
218
- # We use a `nil` because of the last argument hash. The contents of the partial is what becomes the value.
219
- json.post nil, partial: "blog_post"
220
-
221
- or
222
-
223
- # Set @post as a local `article` within the `blog_post` partial.
224
- json.post @post, partial: "blog_post", as: 'article'
225
-
226
- or
227
- # Add more locals
228
- json.post @big_post, partial: "blog_post", locals: {email: 'tests@test.com'}
229
-
230
- or
231
-
232
- # Use a partial for each element in an array
233
- json.array! @posts, partial: "blog_post", as: :blog_post
234
- ```
235
-
236
- ### Caching
237
- Caching is only available as an option on an attribute and can be used in tandem with partials.
238
-
239
- Usage:
240
-
241
- ```ruby
242
- json.author(cache: ["some_cache_key"]) do
243
- json.first_name "tommy"
244
- end
245
-
246
- or
247
-
248
- json.profile "hello", cache: "cachekey"
249
-
250
- or
251
-
252
- json.profile nil, cache: "cachekey", partial: "profile", locals: {email: "test@test.com"}
253
- ```
254
-
255
-
256
- ### No merge of duplicate `set!`s
257
- Unlike Jbuilder, BreezyTemplates will not merge duplicate `set!`s. Instead, the last duplicate will override the first.
258
-
259
- Usage:
260
- ```ruby
261
- json.address do
262
- json.street '123 road'
263
- end
264
-
265
- json.address do
266
- json.zip 10002
267
- end
268
- ```
269
-
270
- would become
271
-
272
- ```json
273
- {address: {zip:10002}}
274
- ```
275
-
276
- ### Deferment
277
- You can defer rendering of expensive content using the `defer: :auto` option available in blocks. Behind the scenes BreezyTemplates will no-op the block entirely, replace the value with a `null` as a standin, and append a `Breezy.visit(/somepath?_breezy_filter=keypath.to.node)` to the response. When the client recieves the payload, `breezy:load` will be fired, then the appended `Breezy.visit` will be called to fetch and graft the missing node before firing `breezy:load` a second time.
278
-
279
- Usage:
280
- ```ruby
281
- json.dashboard(defer: :auto) do
282
- sleep 10
283
- json.some_fancy_metric 42
284
- end
285
- ```
286
-
287
- A manual option is also available:
288
-
289
- ```ruby
290
- json.dashboard(defer: :manual) do
291
- sleep 10
292
- json.some_fancy_metric 42
293
- end
294
- ```
295
- If `:manual` is used, Breezy will no-op the block and not append `Breezy.visit` to the payload. Its up to you to use [node filtering](#filtering_nodes) to fetch the node seperately. A common usecase would be tab content that does not load until you click the tab.
296
-
297
-
298
-
299
- #### Working with arrays
300
- If you want to defer elements in an array, you should add a key as an option on `array!` to help breezy generate a more specific keypath, otherwise it'll just use the index.
301
-
302
- ```ruby
303
- data = [{id: 1, name: 'foo'}, {id: 2, name: 'bar'}]
304
-
305
- json.array! data, key: :id do
306
- json.greeting defer: :auto do
307
- json.greet 'hi'
308
- end
309
- end
310
- ```
311
-
312
- ### Filtering nodes
313
- As seen previously, Breezy can filter your content tree for a specific node. This is done by adding a `_breezy_filter=keypath.to.node` in your URL param and setting the content type to `.js`. BreezyTemplates will no-op all node blocks that are not in the keypath, ignore deferment and caching (if an `ActiveRecord::Relation` is encountered, it will append a where clause with your provided id) while traversing, and return the node. Breezy will then graft that node back onto its tree on the client side and call `breezy:onload` with the new tree. This is done automatically when using deferment, but you can use this param separately in tandem with `data-bz-remote`.
314
-
315
- For example, to create seamless ajaxy pagination for a specific part of your page, just create a link like the following:
316
-
317
- ```html
318
- <a href="posts?page_num=2&_breezy_filter=key.path.to.posts" data-bz-remote> Next Page </a>
319
- ```
320
-
321
- Filtering works off your existing route and content tree, so no additional API necessary.
322
-
323
-
324
- ##Running the tests
325
-
326
- Ruby:
327
-
328
- ```
329
- BUNDLE_GEMFILE=Gemfile.rails50 bundle
330
- BUNDLE_GEMFILE=Gemfile.rails50 rake test
331
- ```
332
-
333
- JavaScript:
334
-
335
- ```
336
- bundle install
337
- bundle exec blade runner
338
- ```