|
1 | | -# hypernova-ruby |
| 1 | +# hypernova-ruby [](https://travis-ci.org/airbnb/hypernova-ruby) |
| 2 | + |
| 3 | +> A Ruby client for the Hypernova service |
| 4 | +
|
| 5 | +## Getting Started |
| 6 | + |
| 7 | +Add this line to your application’s Gemfile: |
| 8 | + |
| 9 | +```ruby |
| 10 | +gem 'hypernova' |
| 11 | +``` |
| 12 | + |
| 13 | +And then execute: |
| 14 | + |
| 15 | + $ bundle |
| 16 | + |
| 17 | +Or install it yourself as: |
| 18 | + |
| 19 | + $ gem install hypernova |
| 20 | + |
| 21 | + |
| 22 | +In Rails, create an initializer in `config/initializers/hypernova.rb`. |
| 23 | + |
| 24 | +```ruby |
| 25 | +# Really basic configuration only consists of the host and the port |
| 26 | +Hypernova.configure do |config| |
| 27 | + config.host = "localhost" |
| 28 | + config.port = 80 |
| 29 | +end |
| 30 | +``` |
| 31 | + |
| 32 | +Add an `:around_filter` to your controller so you can opt into Hypernova rendering of view partials. |
| 33 | + |
| 34 | +```ruby |
| 35 | +# In my_controller.rb |
| 36 | +require 'hypernova' |
| 37 | + |
| 38 | +class MyController < ApplicationController |
| 39 | + around_filter :hypernova_render_support |
| 40 | +end |
| 41 | +``` |
| 42 | + |
| 43 | +Use the following methods to render React components in your view/templates. |
| 44 | + |
| 45 | +```erb |
| 46 | +<%= |
| 47 | + render_react_component( |
| 48 | + 'MyComponent.js', |
| 49 | + :name => 'Person', |
| 50 | + :color => 'Blue', |
| 51 | + :shape => 'Triangle' |
| 52 | + ) |
| 53 | +%> |
| 54 | +``` |
| 55 | + |
| 56 | +## Configuration |
| 57 | + |
| 58 | +You can pass more configuration options to Hypernova. |
| 59 | + |
| 60 | +```ruby |
| 61 | +Hypernova.configure do |config| |
| 62 | + config.http_adapter = :patron # Use any adapter supported by Faraday |
| 63 | + config.host = "localhost" |
| 64 | + config.port = 80 |
| 65 | + config.open_timeout = 0.1 |
| 66 | + config.scheme = :https # Valid schemes include :http and :https |
| 67 | + config.timeout = 0.6 |
| 68 | +end |
| 69 | +``` |
| 70 | + |
| 71 | +If you do not want to use `Faraday`, you can configure Hypernova Ruby to use an HTTP client that |
| 72 | +responds to `post` and accepts a hash argument. |
| 73 | + |
| 74 | +```ruby |
| 75 | +Hypernova.configure do |config| |
| 76 | + # Use your own HTTP client! |
| 77 | + config.http_client = SampleHTTPClient.new |
| 78 | +end |
| 79 | +``` |
| 80 | + |
| 81 | +You can access a lower-level interface to exactly specify the parameters that are sent to the |
| 82 | +Hypernova service. |
| 83 | + |
| 84 | +```erb |
| 85 | +<% things.each |thing| %> |
| 86 | + <li> |
| 87 | + <%= |
| 88 | + hypernova_batch_render( |
| 89 | + :name => 'your/component/thing.bundle.js', |
| 90 | + :data => thing |
| 91 | + ) |
| 92 | + %> |
| 93 | + </li> |
| 94 | +<% end %> |
| 95 | +``` |
| 96 | + |
| 97 | +You can also use the batch interface if you want to create and submit batches yourself: |
| 98 | + |
| 99 | +```ruby |
| 100 | +batch = Hypernova::Batch.new(service) |
| 101 | + |
| 102 | +# each job in a hypernova render batch is identified by a token |
| 103 | +# this allows retrieval of unordered jobs |
| 104 | +token = batch.render( |
| 105 | + :name => 'some_bundle.bundle.js', |
| 106 | + :data => {foo: 1, bar: 2} |
| 107 | +) |
| 108 | +token2 = batch.render( |
| 109 | + :name => 'some_bundle.bundle.js', |
| 110 | + :data => {foo: 2, bar: 1} |
| 111 | +) |
| 112 | +# now we can submit the batch job and await its results |
| 113 | +# this blocks, and takes a significant time in round trips, so try to only |
| 114 | +# use it once per request! |
| 115 | +result = batch.submit! |
| 116 | + |
| 117 | +# ok now we can access our rendered strings. |
| 118 | +foo1 = result[token].html_safe |
| 119 | +foo2 = result[token2].html_safe |
| 120 | +``` |
| 121 | + |
| 122 | +## Plugins |
| 123 | + |
| 124 | +Hypernova enables you to control and alter requests at different stages of |
| 125 | +the render lifecycle via a plugin system. |
| 126 | + |
| 127 | +### Example |
| 128 | + |
| 129 | +All methods on a plugin are optional, and they are listed in the order that |
| 130 | +they are called. |
| 131 | + |
| 132 | +**initializers/hypernova.rb:** |
| 133 | +```ruby |
| 134 | +# initializers/hypernova.rb |
| 135 | +require 'hypernova' |
| 136 | + |
| 137 | +class HypernovaPlugin |
| 138 | + # get_view_data allows you to alter the data given to any individual |
| 139 | + # component being rendered. |
| 140 | + # component is the name of the component being rendered. |
| 141 | + # data is the data being given to the component. |
| 142 | + def get_view_data(component_name, data) |
| 143 | + phrase_hash = data[:phrases] |
| 144 | + data[:phrases].keys.each do |phrase_key| |
| 145 | + phrase_hash[phrase_key] = "test phrase" |
| 146 | + end |
| 147 | + data |
| 148 | + end |
| 149 | + |
| 150 | + # prepare_request allows you to alter the request object in any way that you |
| 151 | + # need. |
| 152 | + # Unless manipulated by another plugin, request takes the shape: |
| 153 | + # { 'component_name.js': { :name => 'component_name.js', :data => {} } } |
| 154 | + def prepare_request(current_request, original_request) |
| 155 | + current_request.keys.each do |key| |
| 156 | + phrase_hash = req[key][:data][:phrases] |
| 157 | + if phrase_hash.present? |
| 158 | + phrase_hash.keys.each do |phrase_key| |
| 159 | + phrase_hash[phrase_key] = phrase_hash[phrase_key].upcase |
| 160 | + end |
| 161 | + end |
| 162 | + end |
| 163 | + current_request |
| 164 | + end |
| 165 | + |
| 166 | + # send_request? allows you to determine whether a request should continue |
| 167 | + # on to the hypernova server. Returning false prevents the request from |
| 168 | + # occurring, and results in the fallback html. |
| 169 | + def send_request?(request) |
| 170 | + true |
| 171 | + end |
| 172 | + |
| 173 | + # after_response gives you a chance to alter the response from hypernova. |
| 174 | + # This will be most useful for altering the resulting html field, and special |
| 175 | + # handling of any potential errors. |
| 176 | + # res is a Hash like { 'component_name.js': { html: String, err: Error? } } |
| 177 | + def after_response(current_response, original_response) |
| 178 | + current_response.keys.each do |key| |
| 179 | + hash = current_response[key] |
| 180 | + hash['html'] = '<div>hello</div>' |
| 181 | + end |
| 182 | + current_response |
| 183 | + end |
| 184 | + |
| 185 | + # NOTE: If an error happens in here, it won’t be caught. |
| 186 | + def on_error(error, jobs) |
| 187 | + puts "Oh no, error - #{error}, jobs - #{jobs}" |
| 188 | + end |
| 189 | +end |
| 190 | + |
| 191 | +Hypernova.add_plugin!(HypernovaPlugin.new) |
| 192 | +``` |
| 193 | + |
| 194 | +## Development |
| 195 | + |
| 196 | +After checking out the repo, run `bin/setup` to install dependencies. Then, run |
| 197 | +`bin/console` for an interactive prompt that will allow you to experiment. |
| 198 | + |
| 199 | +To install this gem onto your local machine, run `bundle exec rake install`. To |
| 200 | +release a new version, update the version number in `version.rb`, and then run |
| 201 | +`bundle exec rake release` to create a git tag for the version, push git |
| 202 | +commits and tags, and push the `.gem` file to |
| 203 | +[rubygems.org](https://rubygems.org). |
| 204 | + |
| 205 | +## Contributing |
| 206 | + |
| 207 | +1. Fork it ( https://github.com/[my-github-username]/hypernova/fork ) |
| 208 | +2. Create your feature branch (`git checkout -b my-new-feature`) |
| 209 | +3. Commit your changes (`git commit -am 'Add some feature'`) |
| 210 | +4. Push to the branch (`git push origin my-new-feature`) |
| 211 | +5. Create a new Pull Request |
0 commit comments