Giter VIP home page Giter VIP logo

barriehadfield / heart-cards Goto Github PK

View Code? Open in Web Editor NEW
4.0 3.0 0.0 890 KB

This Heat Cards application provides a digital platform to track and manage a HEART process. Heart Cards is also a fully featured Hyperloop application which demonstrates all aspects of the Hyperloop Isomorphic COMPS architecture.

Home Page: http://www.ruby-hyperloop.io

License: MIT License

Ruby 69.40% JavaScript 5.10% CoffeeScript 0.17% CSS 11.59% HTML 13.56% Roff 0.18%
hyperloop hyperloop-component heart react-libraries hyperloop-comps-architecture tutorial

heart-cards's Introduction

Heart Cards Application and Tutorial

WIP: This tutorial is not complete yet

What is HEART?

Google invented the HEART process, which stands for Happiness, Engagement, Adoption, Retention and Task Success.

The HEART process takes a more holistic approach and recognizes the need to gather quantitive as well as qualitative feedback when assessing the success of a software initiative.

You can read more about HEART here: https://www.interaction-design.org/literature/article/google-s-heart-framework-for-measuring-ux

If you are on a journey of continuous improvement, HEART can help you stay true to a build-measure-learn software development lifecycle and can unite designers, developers, product managers, and testers.

The Heart Cards Application

This Heat Cards application provides a digital platform to track and manage a HEART process.

Heart Cards is also a fully featured Hyperloop application which demonstrates all aspects of the Hyperloop Isomorphic COMPS architecture.

This tutorial

This tutorial assumes a working knowledge of Rails and Hyperloop. The detailed Rails Hello World or ToDo tutorials are good precursors if starting out with Hyperloop.

Technology covered

Heart Cards is an Isomorphic Ruby application showcasing Hyperloop's COMPS architecture.

The following technologies are covered:

  • Hyperloop Isomorphic Components, Operations, Models, Policies and Stores
  • Hyper-Router which is a DSL wrapping React Router
  • Rails 5.1 with ActionCable for pushing changes between connected clients
  • Opel Hot Reloader for developer bliss with no page reloads while coding
  • Yarn and Webpacker for managing JavaScript libraries
  • The Devise Gem for authentication (connected to Hyperloop)
  • React for the interactive UI (used by Hyperloop)
  • The React-Semantic-UI for integrating React and Semantic UI

Setup

Ensure Ruby, Rails 5.1.x, Yarn and Postgres SQL are installed first.

Note: This application uses Postgres SQL so that it is deployable to Heroku. If you do not want to use Postgres then you will need to swap it out for MYSQL, but please do not use SQLite as it is not capable of providing the concurrency Hyperloop requires. There are detailed Postgres installation instructions here: https://wiki.postgresql.org/wiki/Detailed_installation_guides

Thereafter, run the following console commands:

git clone https://github.com/barriehadfield/heart-cards.git
cd heart-cards
bundle
gem install foreman
rails db:create
rails db:migrate
yarn
bin/webpack

Start the server:

foreman start

Navigate to:

http://localhost:5000/

And you should be rewarded with a running application, but if it is not working, then there is something not right in the setup. If you cannot resolve this, then please reach out to us in the Gitter Hyperloop room: https://gitter.im/ruby-hyperloop/chat and we will be happy to help you.

Single Page Application Routing

The AppRouter Component

The first Component we launch is the Router. Its job is to read the incoming route and render the appropriate Component. Simple as that! We have SPA using React Router to route incoming requests in just a few lines of Ruby code.

# app/hyperloop/components/shared/app_router.rb
class AppRouter < Hyperloop::Router
  history :browser

  route do
    DIV {
      Switch do
        Route('/', exact: true, mounts: Home)
        Route('/members', exact: true, mounts: Members)
      end
    }
  end
end

As you can see from the code above, there are just two routes in this application. / which will render a Component called Home and /members which will render a Component called Members. As our routing needs in this application are so simple, we will not go into routing further, but you can learn more about this Hyper Router here: https://github.com/ruby-hyperloop/hyper-router

Where are the Controllers and Views?

You might be wondering where the controllers and views are for our application. There are none, we have replaced all of these parts of the Rails stack with Isomorphic Hyperloop code. If you have a look at routes.rb you will see that we have an automagical route root 'hyperloop#AppRouter' which Hyperloop uses to render our root Component AppRouter.

There are other ways to work with Hyperloop, you could have had a traditional Controller and View and launched the root Hyperloop Component either from the Controller or from within a View, but for now, we just don't need all that.

While we are looking at routes.rb pay attention to this line at the end of the file. It's important that it remains at the end of the file as this is our catch all route match '*all', to: 'hyperloop#AppRouter', via: [:get]

That last line tells our Rails server to route all requests to our Hyperloop Component so we can deal with them there. We will discuss SPA (single page application) routing later.

Reactive Components

The Home Component

The Home Component generates the primary user interface for this application. We will spend a little time going through this line by line as there might be several new concepts here.

Note on coding style: There are two coding conventions used here which are purely a matter of coding style. You will notice that the HTML elements (DIV) are in caps which would indicate a constant. We are using caps as we believe it makes the code easier to read. If you do not like this then div will work just as well. Secondly (and perhaps more controversially) you will notice the misuse of { } curly braces extending over more than one line whereas the Ruby norm is to use do end blocks if the block extends over more than one line and { } if it just one line. Personally, I like curly braces for Component and HTML element blocks and do end for conditional or looping logic. I find this easier to read and work with, but if it hurts your eyes, you can use do end instead.

# app/hyperloop/components/home.rb
class Home < Hyperloop::Router::Component

  render(DIV) do
    MainAppBar()
    Sem.Container(style: { marginTop: '2em' }) {
      Sem.Grid {
        Sem.GridRow {
          Sem.GridColumn {
            new_heart
          }
        }
        heart_cards
      }
    }
  end

  def new_heart
    HeartModal(heart: Heart.new, mode: :new)
  end

  def heart_cards
    Heart.reverse.each do |heart|
      Sem.GridRow {
        Sem.GridColumn {
          HeartCard(heart: heart)
        }
      }
    end
  end
end

Hyperloop calls the render macro to render a Component. I always like to keep this method near the top of the class so you can quickly see what the Component does.

In this case, the first thing our Home Component does is render another Component - MainAppBar. That is the key to Component oriented architecture - Components render other Components, so your user interface is composed of increasingly smaller contained Components. You will get very used to this pattern.

You might also notice that 'Home' is not an entirely standard Hyperloop Component, as it is derived from Hyperloop::Router::Component whereas typical Hyperloop components are classes derived from Hyperloop::Component. We are doing this because we need to pass information routing down into out MainAppBar Component. The reason for this is well covered in Chapter 6 of the ToDo tutorial. If you go off and read that now do make sure you come back here as there are still many interesting topics we are about to get into!

Using JavaScript based React libraries

Let's look at the render macro of our MainAppBar Component and then discuss this mysterious Sem object.

Semantic UI React is a React library which we are accessing from within our Ruby code. Semantic UI React is a React based DSL wrapper for the great Semantic UI style sheet.

There is a quick tutorial on the Hyperloop site which explains how to setup Yarn and Webpacker and import libraries like semantic-ui-react or react-bootstrap(or any React of JavaScript library): http://ruby-hyperloop.io/tutorials/hyperlooprails/webpacker/

Sem.Menu is this Component: https://react.semantic-ui.com/collections/menu Lets have a look at the documentation with examples is JSX and write a Ruby version.

For the Menu Component, if we were writing it in JSX syntax it would look like this:

// if this were in JSX
return (
  <Menu inverted color='pink' size='huge'>
    <Container>
      <Menu.Item name='home' active={activeItem === 'home'} onClick={this.handleItemClick} > HOME </Menu.Item>
      <Menu.Item name='members' active={activeItem === 'members'} onClick={this.handleItemClick} > MEMBERS </Menu.Item>
    </Container>
  </Menu>
)

And here is our Ruby version:

# app/hyperloop/components/shared/main_app_bar.rb
render(DIV) do
  Sem.Menu(inverted: true, color: :pink, size: :huge) {
    Sem.Container {
      Sem.MenuItem { heart_cards }
      Sem.MenuItem { members }
    }
  }
end

There are a few simple things you need to understand, and after that, you will find it very easy to translate any JSX example into Ruby and work with any JavaScript or React library.

Firstly, notice that we are accessing the semantic-ui-react library through an object called Sem.

If you are wondering where the Sem object came from, its as simple as using Yarn and Webpack to package the library then creating a JavaScript object called Sem through a require of the library.

// app/javascript/packs/application.js
Sem = require('semantic-ui-react');

The other thing to notice is that we do not use the dot notation in exactly the same way the JSX example does. Menu.Item becomes MenuItem and so-forth. Menu.Item is actually an assignment of the MenuItem object within the Menu object. The fact that Menu.Item is not imported as something to do with the way Webpack is importing it and beyond the scope of this tutorial.

Finally notice how the JSX paramaters inverted color='pink' size='huge' become a hash inverted: true, color: :pink, size: :huge in the Ruby version.

The information in this chapter should equip you with most of what you need to work with any JavaScript or React library. The only things we have not discussed is how to create and pass a React object to another object and how to handle JavaScript callbacks. We will address both these topics later in this tutorial.

Models and Modals

The HeartModal Component

HeartModal is a self-contained, DRY, multi-functional component. It renders itself as Button (in an Edit or New state) and then morphs into a Modal when clicked. It handles editing or creating of Heart objects and it achieves all of that in roughly 50 lines of code.

  • Multi-functional - this Component handles editing or creating of Heart objects using the same rendering code and when the Modal is not open, the Component knows if it should render as a New or Edit Button (or as a Modal if it opened).
  • Self-contained - all of the functionality is contained within the Component, we do not need to worry about its rendering state (Button or Modal) or even if the Modal should be shown or hidden. There are also no call-backs to worry about.
  • DRY - It uses the same Components as the Card Component to render the Heart object data. The rendering is slightly different, so it does depart in part but were there is no need for difference the code is completely DRY.

Interface

In our Home Component code, you will notice that we invoke the HeartModal Component passing in an empty Heart object and a mode param.

HeartModal(heart: Heart.new, mode: :new)

And then again in the Card Component we use it again:

HeartModal(heart: params.heart, mode: :edit)

We could simplify the interface and just pass the Heart object we would like to operate on and let the HeartModal Component figure out if it is a new or existing object and then render itself as a New or Edit Button but that would be a little to pithy for my liking. The interface to this Component (passing the Heart object we want to operate on, and a mode param) makes for clear understandable code.

Implementation

Firstly, lets have a look at the render macro:

render(DIV) do
  if state.open
    render_modal
  else
    edit_or_new_button.on(:click) { mutate.open true }
  end
end

Herein lies the beauty of React. These 7 lines of code tell us everything we need to know about how this Component works:

If its internal (reactive) state open is true then it will render (and add to the DOM of the page) a Modal, otherwise it will render itself as a Button (either an Edit or New Button) that' if clicked, will mutate its open state so that it then renders as a Modal.

Our render_modal method does exactly what it describes; it renders a Semantic UI Modal and sets the open state of the Modal to the same reactive state open. This is key - our reactive state variable open does three things - firstly it governs if the Component should present itself as a Button or a Modal, secondly it governs if the Modal CSS is added to the DOM and thirdly it governs if this particular Modal (which is now rendered to the DOM) is visible or not.

There is a subtly yet important point here - the Modal will only be rendered to the DOM if it is to be displayed. This is important as we will be adding many of these HeartModal Components to our page (one per HeartCard which we will see later) and we do not want them to render unless necessary as the rendering code will be expensive.

def render_modal
  Sem.Modal(open: state.open) {
    Sem.ModalHeader {
      params.heart.name.nil? || params.heart.name.length == 0 ? "New Heart Card" : params.heart.name
    }
    Sem.ModalContent {
      content
    }
    Sem.ModalActions {
      actions
    }
  }
end

Lets consider the second part of the render macro - rendering itself as a Button if the Modal is closed.

edit_or_new_button.on(:click) { mutate.open true }

Herein lies the beauty of Ruby. We render a method edit_or_new_button which will return a Button and we add an event handler to whichever Button is returned.

def edit_or_new_button
  if params.mode == :new
    Sem.Button(icon: true, labelPosition: 'left', primary: true) {
      Sem.Icon(name: :heart)
      "New Heart Card"
    }
  else
    Sem.Button(circular: true, icon: :setting)
  end
end

Methods or Components

Its worth taking a moment to discuss the choice of using methods in a Component class or creating new Components. One could argue that each of the methods above could be a Component in its own right and if one were following the React coding guidelines where you create ever smaller Components.

My own rule of thumb is to use methods to simplify the code and I create Components whenever I imagine the Component being re-used somewhere else in my code. Often code starts life as a method and turns into a Component.

For example, in this HeartModal Component we use methods throughout other than one Component which we render in the body of the Modal Categories(heart: params.heart, edit: true). We will discuss this Component in a later chapter as it has some of its own magic. For now all we need to know is that a Component called Categories will be rendered in the body of our Modal (if the Modal itself is rendered).

Creating and Updating Heart Objects

You might have noticed that our Modal has two action buttons:

def actions
  Sem.Button(primary: true) { "Save" }.on(:click) { save } if params.heart.changed?
  Sem.Button { "Cancel" }.on(:click) { cancel }
end

Our 'save' action is implemented here:

def save
  params.heart.save.then do |result|
    if result[:success]
      mutate.open false
    else
      alert "Unable to save Heart Card"
    end
  end
end

Herein lies the beauty of Hyperloop. The code above is the only code we write to handle the saving or creating of modified Heart objects.

Under the covers Hyperloop does all of the following tasks:

  • Serialies our Heart object into JSON
  • POSTSs it to the server (expecting a promise to be returned at some time)
  • Saves it to the database (depending on the current_users access rights)
  • Uses ActionCable to push a notification to a channel (again, depending on the current_users Policy)
  • De-serilizes the response and updates the client-side Models with any changes
  • Re-renders any Component which is currently displaying data from a modified Model or collection of Models
  • Executes the code which was waiting for the promise to be returned, which in this case changes the state of the Modal to not be shown or alerts an error

In a non-isomorphic, single page application (most likely with the frontend in JavaScript and the backend in Ruby) all of the tasks above would have to have been considered and coded by the developer. Howevere, with Hyperloop, the simple fact that Models are shared between the client and server makes all of the above possible and designates those mundane, repetitive, complicated, and fragile tasks to plumbing.

THE END - this tutorial has not been finished. Please feel free to adopt it and complete it!

heart-cards's People

Contributors

barriehadfield avatar fzingg avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

heart-cards's Issues

Production mode

Hi @barriehadfield, when I try to tun in production

  1. RAILS_ENV=production rails assets:precompile
  2. RAILS_ENV=production rails s

The compiled application.js files includes wrong code <div data-react-class="React.TopLevelRailsComponent"

Do you have any idea what's wrong?

heyper-console anabled

Hi @barriehadfield, I enabled the hyper-console but when it opens I got response from cable that is unauthorized. Is somehow possible to set the sessions (Member) for the console?

the error is
POST http://localhost:3000/hyperloop/hyperloop-action-cable-auth/c98462ff-07f9-4350-8e10-ba45f6d81597-09fb572a26cb53ef96b3a4161f881834/private-synchromesh-Hyperloop::Session-09fb572a26cb53ef96b3a4161f881834 401 (Unauthorized)

deploy to heroku with latest Hyperloop lap4

remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Ruby app detected
remote: -----> Compiling Ruby/Rails
remote: -----> Using Ruby version: ruby-2.4.1
remote: -----> Installing dependencies using bundler 1.15.2
remote: Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
remote: Warning: the running version of Bundler (1.15.2) is older than the version that created the lockfile (1.16.0.pre.3). We suggest you upgrade to the latest version of Bundler by running gem install bundler --pre.
remote: Fetching gem metadata from http://demo.kursator.com:9292/...
remote: Fetching gem metadata from https://rubygems.org/...........
remote: Fetching version metadata from http://demo.kursator.com:9292/...
remote: Fetching version metadata from https://rubygems.org/..
remote: Fetching dependency metadata from http://demo.kursator.com:9292/..
remote: Fetching dependency metadata from https://rubygems.org/.
remote: Using rake 12.3.0
remote: Using concurrent-ruby 1.0.5
remote: Using minitest 5.10.3
remote: Using thread_safe 0.3.6
remote: Using builder 3.2.3
remote: Using erubi 1.7.0
remote: Using mini_portile2 2.3.0
remote: Using crass 1.0.3
remote: Using rack 2.0.3
remote: Using nio4r 2.1.0
remote: Using websocket-extensions 0.1.3
remote: Using mini_mime 1.0.0
remote: Using arel 8.0.0
remote: Using babel-source 5.8.35
remote: Using execjs 2.7.0
remote: Using bcrypt 3.1.11
remote: Using bundler 1.15.2
remote: Using coffee-script-source 1.12.2
remote: Using method_source 0.9.0
remote: Using thor 0.20.0
remote: Using connection_pool 2.2.1
remote: Using orm_adapter 0.5.0
remote: Using ffi 1.9.18
remote: Using gravtastic 3.2.6
remote: Using hike 1.2.3
remote: Fetching httpclient 2.8.3
remote: Using sourcemap 0.1.1
remote: Using tilt 2.0.8
remote: Using paggio 0.2.6
remote: Fetching libv8 5.9.211.38.1 (x86_64-linux)
remote: Using multi_json 1.12.2
remote: Using rb-fsevent 0.10.2
remote: Using ruby_dep 1.5.0
remote: Using websocket 1.2.5
remote: Using pg 0.21.0
remote: Using puma 3.10.0
remote: Fetching pusher-signature 0.1.8
remote: Installing pusher-signature 0.1.8
remote: Using statesman 3.1.0
remote: Using i18n 0.9.1
remote: Using tzinfo 1.2.4
remote: Using nokogiri 1.8.1
remote: Using mail 2.7.0
remote: Using websocket-driver 0.6.5
remote: Using rack-test 0.7.0
remote: Using warden 1.2.7
remote: Using sprockets 3.7.1
remote: Using rack-proxy 0.6.2
remote: Using babel-transpiler 0.7.0
remote: Using uglifier 3.2.0
remote: Using coffee-script 2.4.1
remote: Using rb-inotify 0.9.10
remote: Using activesupport 5.1.4
remote: Using loofah 2.1.1
remote: Using opal 0.10.5
remote: Using listen 3.1.5
remote: Using sass-listen 4.0.0
remote: Using rails-dom-testing 2.0.3
remote: Using globalid 0.4.1
remote: Using activemodel 5.1.4
remote: Using mutations 0.8.1
remote: Using jbuilder 2.7.0
remote: Using rails-html-sanitizer 1.0.3
remote: Using opal-browser 0.2.0
remote: Using opal-activesupport 0.3.0
remote: Using opal-jquery 0.4.2
remote: Using opal-sprockets 0.4.1.0.10.4.3.1.0
remote: Using opal_hot_reloader 0.1.4
remote: Using sass 3.5.3
remote: Using activejob 5.1.4
remote: Using activerecord 5.1.4
remote: Using actionview 5.1.4
remote: Fetching hyperloop-config 0.15.0.pre.sachsenring.pre.lap4
remote: Installing httpclient 2.8.3
remote: Using actionpack 5.1.4
remote: Fetching pusher 1.3.1
remote: Installing pusher 1.3.1
remote: Using actioncable 5.1.4
remote: Using actionmailer 5.1.4
remote: Using railties 5.1.4
remote: Using sprockets-rails 3.2.1
remote: Using coffee-rails 4.2.2
remote: Using responders 2.4.0
remote: Using jquery-rails 4.3.1
remote: Fetching react-rails 2.4.2
remote: Installing react-rails 2.4.2
remote: Using webpacker 3.0.2
remote: Using rails 5.1.4
remote: Using sass-rails 5.0.7
remote: Using devise 4.3.0
remote: Using opal-rails 0.9.3
remote: Installing hyperloop-config 0.15.0.pre.sachsenring.pre.lap4
remote: Fetching hyper-store 0.15.0.pre.sachsenring.pre.lap4
remote: Installing libv8 5.9.211.38.1 (x86_64-linux)
remote: Installing hyper-store 0.15.0.pre.sachsenring.pre.lap4
remote: Fetching hyper-react 0.15.0.pre.sachsenring.pre.lap4
remote: Fetching mini_racer 0.1.14
remote: Installing mini_racer 0.1.14 with native extensions
remote: Installing hyper-react 0.15.0.pre.sachsenring.pre.lap4
remote: Fetching hyper-component 0.15.0.pre.sachsenring.pre.lap4
remote: Installing hyper-component 0.15.0.pre.sachsenring.pre.lap4
remote: Fetching hyper-operation 0.15.0.pre.sachsenring.pre.lap4
remote: Fetching hyper-router 4.2.6.pre.sachsenring.pre.lap4
remote: Installing hyper-router 4.2.6.pre.sachsenring.pre.lap4
remote: Installing hyper-operation 0.15.0.pre.sachsenring.pre.lap4
remote: Fetching hyper-mesh 0.15.0.pre.sachsenring.pre.lap4
remote: Installing hyper-mesh 0.15.0.pre.sachsenring.pre.lap4
remote: Fetching hyper-model 0.15.0.pre.sachsenring.pre.lap4
remote: Installing hyper-model 0.15.0.pre.sachsenring.pre.lap4
remote: Fetching hyperloop 0.15.0.pre.sachsenring.pre.lap4
remote: Installing hyperloop 0.15.0.pre.sachsenring.pre.lap4
remote: Bundle complete! 24 Gemfile dependencies, 96 gems now installed.
remote: Gems in the groups development and test were not installed.
remote: Bundled gems are installed into ./vendor/bundle.
remote: Warning: the gem 'hyperloop-config' was found in multiple sources.
remote: Installed from: http://demo.kursator.com:9292/
remote: Also found in:
remote: * https://rubygems.org/
remote: You should add a source requirement to restrict this gem to your preferred source.
remote: For example:
remote: gem 'hyperloop-config', :source => 'http://demo.kursator.com:9292/'
remote: Then uninstall the gem 'hyperloop-config' (or delete all bundled gems) and then install again.
remote: Warning: the gem 'hyper-store' was found in multiple sources.
remote: Installed from: http://demo.kursator.com:9292/
remote: Also found in:
remote: * https://rubygems.org/
remote: You should add a source requirement to restrict this gem to your preferred source.
remote: For example:
remote: gem 'hyper-store', :source => 'http://demo.kursator.com:9292/'
remote: Then uninstall the gem 'hyper-store' (or delete all bundled gems) and then install again.
remote: Warning: the gem 'hyper-react' was found in multiple sources.
remote: Installed from: http://demo.kursator.com:9292/
remote: Also found in:
remote: * https://rubygems.org/
remote: You should add a source requirement to restrict this gem to your preferred source.
remote: For example:
remote: gem 'hyper-react', :source => 'http://demo.kursator.com:9292/'
remote: Then uninstall the gem 'hyper-react' (or delete all bundled gems) and then install again.
remote: Warning: the gem 'hyper-component' was found in multiple sources.
remote: Installed from: http://demo.kursator.com:9292/
remote: Also found in:
remote: * https://rubygems.org/
remote: You should add a source requirement to restrict this gem to your preferred source.
remote: For example:
remote: gem 'hyper-component', :source => 'http://demo.kursator.com:9292/'
remote: Then uninstall the gem 'hyper-component' (or delete all bundled gems) and then install again.
remote: Warning: the gem 'hyper-operation' was found in multiple sources.
remote: Installed from: http://demo.kursator.com:9292/
remote: Also found in:
remote: * https://rubygems.org/
remote: You should add a source requirement to restrict this gem to your preferred source.
remote: For example:
remote: gem 'hyper-operation', :source => 'http://demo.kursator.com:9292/'
remote: Then uninstall the gem 'hyper-operation' (or delete all bundled gems) and then install again.
remote: Warning: the gem 'hyper-router' was found in multiple sources.
remote: Installed from: http://demo.kursator.com:9292/
remote: Also found in:
remote: * https://rubygems.org/
remote: You should add a source requirement to restrict this gem to your preferred source.
remote: For example:
remote: gem 'hyper-router', :source => 'http://demo.kursator.com:9292/'
remote: Then uninstall the gem 'hyper-router' (or delete all bundled gems) and then install again.
remote: Warning: the gem 'hyper-mesh' was found in multiple sources.
remote: Installed from: http://demo.kursator.com:9292/
remote: Also found in:
remote: * https://rubygems.org/
remote: You should add a source requirement to restrict this gem to your preferred source.
remote: For example:
remote: gem 'hyper-mesh', :source => 'http://demo.kursator.com:9292/'
remote: Then uninstall the gem 'hyper-mesh' (or delete all bundled gems) and then install again.
remote: Warning: the gem 'hyperloop' was found in multiple sources.
remote: Installed from: http://demo.kursator.com:9292/
remote: Also found in:
remote: * https://rubygems.org/
remote: You should add a source requirement to restrict this gem to your preferred source.
remote: For example:
remote: gem 'hyperloop', :source => 'http://demo.kursator.com:9292/'
remote: Then uninstall the gem 'hyperloop' (or delete all bundled gems) and then install again.
remote: The latest bundler is 1.16.0, but you are currently running 1.15.2.
remote: To update, run gem install bundler
remote: Bundle completed (23.57s)
remote: Cleaning up the bundler cache.
remote: Warning: the running version of Bundler (1.15.2) is older than the version that created the lockfile (1.16.0.pre.3). We suggest you upgrade to the latest version of Bundler by running gem install bundler --pre.
remote: Removing hyperloop (0.5.8)
remote: Removing hyper-router (4.1.1)
remote: Removing therubyracer (0.12.3)
remote: Removing hyperloop-config (0.9.11)
remote: Removing hyper-operation (0.5.12)
remote: Removing hyper-react (0.12.7)
remote: Removing hyper-model (0.6.0)
remote: Removing react-rails (1.9.0)
remote: Removing hyper-component (0.12.3)
remote: Removing hyper-mesh (0.6.0)
remote: Removing libv8-3.16.14.19-x86_64 (linux)
remote: Removing ref (2.0.0)
remote: Removing hyper-store (0.2.3)
remote: The latest bundler is 1.16.0, but you are currently running 1.15.2.
remote: To update, run gem install bundler
remote: -----> Installing node-v6.11.1-linux-x64
remote: -----> Installing yarn-v1.0.2
remote: -----> Detecting rake tasks
remote: -----> Preparing app for Rails asset pipeline
remote: Running: rake assets:precompile
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/hyper-react-0.15.0.pre.sachsenring.pre.lap4/lib/reactive-ruby/serializers.rb:1: warning: constant ::Bignum is deprecated
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/hyper-react-0.15.0.pre.sachsenring.pre.lap4/lib/reactive-ruby/serializers.rb:1: warning: constant ::Fixnum is deprecated
remote: INFO: The configuration option 'compress_system_assets' is no longer used.
remote: D, [2017-11-18T08:32:57.464583 #494] DEBUG -- : Hyperloop::Connection::QueuedMessage Load (1.4ms) SELECT "hyperloop_queued_messages".* FROM "hyperloop_queued_messages" WHERE "hyperloop_queued_messages"."connection_id" = $1 LIMIT $2 [["connection_id", 0], ["LIMIT", 1]]
remote: D, [2017-11-18T08:32:57.474767 #494] DEBUG -- : (1.0ms) BEGIN
remote: D, [2017-11-18T08:32:57.476816 #494] DEBUG -- : SQL (1.3ms) INSERT INTO "hyperloop_queued_messages" ("connection_id") VALUES ($1) RETURNING "id" [["connection_id", 0]]
remote: D, [2017-11-18T08:32:57.479093 #494] DEBUG -- : (1.9ms) COMMIT
remote: D, [2017-11-18T08:32:57.488260 #494] DEBUG -- : (8.6ms) DROP TABLE IF EXISTS "hyperloop_connections" CASCADE
remote: D, [2017-11-18T08:32:57.497189 #494] DEBUG -- : (8.5ms) CREATE TABLE "hyperloop_connections" ("id" bigserial primary key, "channel" character varying, "session" character varying, "created_at" timestamp, "expires_at" timestamp, "refresh_at" timestamp)
remote: D, [2017-11-18T08:32:57.500298 #494] DEBUG -- : Hyperloop::Connection::QueuedMessage Load (1.1ms) SELECT "hyperloop_queued_messages".* FROM "hyperloop_queued_messages" WHERE "hyperloop_queued_messages"."connection_id" = $1 LIMIT $2 [["connection_id", 0], ["LIMIT", 1]]
remote: D, [2017-11-18T08:32:57.507918 #494] DEBUG -- : (6.3ms) DROP TABLE IF EXISTS "hyperloop_queued_messages" CASCADE
remote: D, [2017-11-18T08:32:57.638003 #494] DEBUG -- : (129.8ms) CREATE TABLE "hyperloop_queued_messages" ("id" bigserial primary key, "data" text, "connection_id" integer)
remote: yarn install v1.0.2
remote: [1/4] Resolving packages...
remote: [2/4] Fetching packages...
remote: info [email protected]: The platform "linux" is incompatible with this module.
remote: info "[email protected]" is an optional dependency and failed compatibility check. Excluding it from installation.
remote: [3/4] Linking dependencies...
remote: warning "[email protected]" has incorrect peer dependency "ajv@>=5.0.0".
remote: [4/4] Building fresh packages...
remote: Done in 31.94s.
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/opal-0.10.5/lib/opal/nodes/iter.rb:118: warning: constant ::Fixnum is deprecated
remote: rake aborted!
remote: ExecJS::ProgramError: SyntaxError: Unexpected token name «extends», expected punc «,»
remote: JS_Parse_Error.get ((execjs):3538:621)
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:180:in eval_unsafe' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:180:in block (2 levels) in eval'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:239:in timeout' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:179:in block in eval'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:69:in block in with_lock' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:69:in synchronize'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:69:in with_lock' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:177:in eval'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/execjs-2.7.0/lib/execjs/mini_racer_runtime.rb:27:in block in eval' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/execjs-2.7.0/lib/execjs/mini_racer_runtime.rb:66:in translate'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/execjs-2.7.0/lib/execjs/mini_racer_runtime.rb:26:in eval' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/execjs-2.7.0/lib/execjs/mini_racer_runtime.rb:34:in call'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/uglifier-3.2.0/lib/uglifier.rb:195:in run_uglifyjs' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/uglifier-3.2.0/lib/uglifier.rb:157:in compile'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/uglifier_compressor.rb:53:in call' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/uglifier_compressor.rb:28:in call'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:75:in call_processor' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:57:in block in call_processors'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:56:in reverse_each' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:56:in call_processors'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/loader.rb:134:in load_from_unloaded' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/loader.rb:60:in block in load'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/loader.rb:317:in fetch_asset_from_dependency_cache' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/loader.rb:44:in load'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/cached_environment.rb:20:in block in initialize' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/cached_environment.rb:47:in load'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/base.rb:66:in find_asset' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/base.rb:73:in find_all_linked_assets'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:134:in block in find' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:133:in each'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:133:in find' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:185:in compile'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-rails-3.2.1/lib/sprockets/rails/task.rb:68:in block (3 levels) in define' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/rake/sprocketstask.rb:147:in with_logger'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-rails-3.2.1/lib/sprockets/rails/task.rb:67:in block (2 levels) in define' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/rake-12.3.0/exe/rake:27:in <top (required)>'
remote: Caused by:
remote: MiniRacer::RuntimeError: SyntaxError: Unexpected token name «extends», expected punc «,»
remote: JavaScript at JS_Parse_Error.get (:3538:621)
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:180:in eval_unsafe' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:180:in block (2 levels) in eval'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:239:in timeout' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:179:in block in eval'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:69:in block in with_lock' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:69:in synchronize'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:69:in with_lock' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/mini_racer-0.1.14/lib/mini_racer.rb:177:in eval'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/execjs-2.7.0/lib/execjs/mini_racer_runtime.rb:27:in block in eval' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/execjs-2.7.0/lib/execjs/mini_racer_runtime.rb:66:in translate'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/execjs-2.7.0/lib/execjs/mini_racer_runtime.rb:26:in eval' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/execjs-2.7.0/lib/execjs/mini_racer_runtime.rb:34:in call'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/uglifier-3.2.0/lib/uglifier.rb:195:in run_uglifyjs' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/uglifier-3.2.0/lib/uglifier.rb:157:in compile'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/uglifier_compressor.rb:53:in call' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/uglifier_compressor.rb:28:in call'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:75:in call_processor' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:57:in block in call_processors'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:56:in reverse_each' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:56:in call_processors'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/loader.rb:134:in load_from_unloaded' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/loader.rb:60:in block in load'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/loader.rb:317:in fetch_asset_from_dependency_cache' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/loader.rb:44:in load'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/cached_environment.rb:20:in block in initialize' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/cached_environment.rb:47:in load'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/base.rb:66:in find_asset' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/base.rb:73:in find_all_linked_assets'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:134:in block in find' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:133:in each'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:133:in find' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:185:in compile'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-rails-3.2.1/lib/sprockets/rails/task.rb:68:in block (3 levels) in define' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-3.7.1/lib/rake/sprocketstask.rb:147:in with_logger'
remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/sprockets-rails-3.2.1/lib/sprockets/rails/task.rb:67:in block (2 levels) in define' remote: /tmp/build_c720dae44cb069f65e0d0ecde81622fe/vendor/bundle/ruby/2.4.0/gems/rake-12.3.0/exe/rake:27:in <top (required)>'
remote: Tasks: TOP => assets:precompile
remote: (See full trace by running task with --trace)
remote: !
remote: ! Precompiling assets failed.
remote: !
remote: ! Push rejected, failed to compile Ruby app.
remote:
remote: ! Push failed
remote: Verifying deploy...
remote:
remote: ! Push rejected to heartcardapp.

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.