Git Product home page Git Product logo

hypernova-ruby's Introduction

❗ Deprecation Notice
We want to express our sincere gratitude for your support and contributions to the Hypernova open source project. As we are no longer using this technology internally, we have come to the decision to archive the Hypernova repositories. While we won't be providing further updates or support, the existing code and resources will remain accessible for your reference. We encourage anyone interested to fork the repository and continue the project's legacy independently. Thank you for being a part of this journey and for your patience and understanding.

hypernova-ruby Build Status

A Ruby client for the Hypernova service

Getting Started

Add this line to your application’s Gemfile:

gem 'hypernova'

And then execute:

$ bundle

Or install it yourself as:

$ gem install hypernova

In Rails, create an initializer in config/initializers/hypernova.rb.

# Really basic configuration only consists of the host and the port
Hypernova.configure do |config|
  config.host = "localhost"
  config.port = 80
end

Add an :around_filter to your controller so you can opt into Hypernova rendering of view partials.

# In my_controller.rb
require 'hypernova'

class MyController < ApplicationController
  around_filter :hypernova_render_support
end

Use the following methods to render React components in your view/templates.

<%=
  render_react_component(
    'MyComponent.js',
    :name => 'Person',
    :color => 'Blue',
    :shape => 'Triangle'
  )
%>

Configuration

You can pass more configuration options to Hypernova.

Hypernova.configure do |config|
  config.http_adapter = :patron # Use any adapter supported by Faraday
  config.host = "localhost"
  config.port = 80
  config.open_timeout = 0.1
  config.scheme = :https # Valid schemes include :http and :https
  config.timeout = 0.6
end

If you do not want to use Faraday, you can configure Hypernova Ruby to use an HTTP client that responds to post and accepts a hash argument.

Hypernova.configure do |config|
  # Use your own HTTP client!
  config.http_client = SampleHTTPClient.new
end

You can access a lower-level interface to exactly specify the parameters that are sent to the Hypernova service.

<% things.each |thing| %>
  <li>
    <%=
      hypernova_batch_render(
        :name => 'your/component/thing.bundle.js',
        :data => thing
      )
    %>
  </li>
<% end %>

You can also use the batch interface if you want to create and submit batches yourself:

batch = Hypernova::Batch.new(service)

# each job in a hypernova render batch is identified by a token
# this allows retrieval of unordered jobs
token = batch.render(
  :name => 'some_bundle.bundle.js',
  :data => {foo: 1, bar: 2}
)
token2 = batch.render(
  :name => 'some_bundle.bundle.js',
  :data => {foo: 2, bar: 1}
)
# now we can submit the batch job and await its results
# this blocks, and takes a significant time in round trips, so try to only
# use it once per request!
result = batch.submit!

# ok now we can access our rendered strings.
foo1 = result[token].html_safe
foo2 = result[token2].html_safe

Plugins

Hypernova enables you to control and alter requests at different stages of the render lifecycle via a plugin system.

Example

All methods on a plugin are optional, and they are listed in the order that they are called.

initializers/hypernova.rb:

# initializers/hypernova.rb
require 'hypernova'

class HypernovaPlugin
  # get_view_data allows you to alter the data given to any individual
  # component being rendered.
  # component is the name of the component being rendered.
  # data is the data being given to the component.
  def get_view_data(component_name, data)
    phrase_hash = data[:phrases]
    data[:phrases].keys.each do |phrase_key|
      phrase_hash[phrase_key] = "test phrase"
    end
    data
  end

  # prepare_request allows you to alter the request object in any way that you
  # need.
  # Unless manipulated by another plugin, request takes the shape:
  # { 'component_name.js': { :name => 'component_name.js', :data => {} } }
  def prepare_request(current_request, original_request)
    current_request.keys.each do |key|
      phrase_hash = req[key][:data][:phrases]
      if phrase_hash.present?
        phrase_hash.keys.each do |phrase_key|
          phrase_hash[phrase_key] = phrase_hash[phrase_key].upcase
        end
      end
    end
    current_request
  end

  # send_request? allows you to determine whether a request should continue
  # on to the hypernova server.  Returning false prevents the request from
  # occurring, and results in the fallback html.
  def send_request?(request)
    true
  end

  # after_response gives you a chance to alter the response from hypernova.
  # This will be most useful for altering the resulting html field, and special
  # handling of any potential errors.
  # res is a Hash like { 'component_name.js': { html: String, err: Error? } }
  def after_response(current_response, original_response)
    current_response.keys.each do |key|
      hash = current_response[key]
      hash['html'] = '<div>hello</div>'
    end
    current_response
  end

  # NOTE: If an error happens in here, it won’t be caught.
  def on_error(error, jobs)
    puts "Oh no, error - #{error}, jobs - #{jobs}"
  end
end

Hypernova.add_plugin!(HypernovaPlugin.new)

Development

After checking out the repo, run bin/setup to install dependencies. Then, run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release to create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

  1. Fork it ( https://github.com/airbnb/hypernova-ruby/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

hypernova-ruby's People

Contributors

brieb avatar dlackty avatar frozenfung avatar goatslacker avatar justjake avatar ljharb avatar tommydangerous avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hypernova-ruby's Issues

Support custom tag

Hi, team

Is there any chance that we can support custom tag for wrapper here? Yeah, I have to admit that div is fascinating and able to fit more than 95% cases, but what just happen is like below:

I need to server-render an component and previously wrapped in a span tag. And I implement hypernova and its cool helper method(Ruby on Rails based), after a while it succeed without doubt. However, because of the tag being switched from div to span, my layout looks like a disaster. Finally I have to reluctantly make some adjustment with my stylesheet and html structure, well, not so much, but you know.

Can you guys give me some advices on this topic? Or just let me know that I could submit a PR for this.

thanks man.

Heroku? Rails-api?

Does this work with Heroku? According to the deploy section, I should run two servers side by side which might be tricky with Heroku unless there's a buildpack for this.

Also, does this integrate with a Rails API-only app easily? I see mention of view/erb-related code which doesn't really apply in my case. My app currently serves a bare index.html file which pulls a React codebase from S3.

I'm basically doing research to see if this or prerender would be better for my use case.

Can't use plugins when a certain component has two instances with the same name

Hey all,

First of all, this is a truly an awesome project!

In my project I want to render the same component twice with different props, it works really well :)

However, If I write a plugin that uses a hook that receives the components hash (such as prepare_request)

the hooks gets a hash which has only the last component.
I think that the problem is


since it overrides the key.

Just for clarification the batch is sent just fine since it creates the hash differently.

jobs.each_with_index { |job, idx| hash[idx.to_s] = job }

What should I do?

Thanks,
Jonathan

Testing views that render react components

When testing a view that calls render_react_component the spec throws the following error.

Failure/Error: render
ActionView::Template::Error:
called hypernova_batch_render without calling hypernova_batch_before. Check your around_filter for :hypernova_render_support

This is because view specs use ActionView::TestCase::TestController so the around_filter isn't being called. I suppose I could stub out render_react_component but this seems less than ideal. Is there a work around for this or does it need to be addressed in the gem itself?

Render component in loop

Hi, I'm testing a migration from react-rails to hypernova. And I have a problem with render components in a loop. for example:

        <% ['how_works', 'who_participe', 'pay_something'].each do |item| %>

          <%= render_react_component 'components/common/faq_item.js', {
            title: I18n.t("faq.joga_junto.#{item}_title"),
            text: I18n.t("faq.joga_junto.#{item}_text") } %>
        <% end %>

Only the first item was rendered, and the others just created a <script> tag with the props(data) of request, but the react component was not rendered. And I don't know why :D.

the render result is __hypernova_render_token[0]__?

I'm not sure, but sometime when I open a site use SSR with hypernova-ruby and hypernova-react, the site shows a __hypernova_render_token[0]__

also, I notice the node hypernova server doesn't log things about the request? Is that means the request is timeout in hypernova-ruby?

Thanks

[Question] How can I run the test?

I'm trying to create a patch but rspec fails because http://mordor.com:1337/batch does not work.

How can I run the test? I think some inevitable testing components are missing from the repo.

to_json is used on request, but JSON.generate is used on blank_renderer which produces inconsistent results

When a request is made to https://github.com/airbnb/hypernova the to_json method is used:

request.body = payload[:body].to_json

but when the service does not respond, the data is serialized with JSON.generate
JSON.generate(data).gsub(/&/, '&amp;').gsub(/>/, '&gt;')

Theoretically this should produce an identical result, but we have seen that this does not.

Could the latter instance be updated to use to_json as well?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.