diff --git a/.gitignore b/.gitignore
index f51d0b1..0c72301 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,8 +29,15 @@ node_modules
# Ignore bundler config.
.bundle
-spec/test_app
+spec/test_app/tmp
Gemfile.lock
/gemfiles/*.lock
/tmp
+
+# ignore gem
+*.gem
+
+# ignore IDE files
+.idea
+.vscode
diff --git a/.travis.yml b/.travis.yml
index 9434934..70f23af 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,62 +1,32 @@
+dist: trusty
language: ruby
rvm:
- - 1.9.3
- - 2.0.0
- - 2.1
- - jruby-19mode
-before_script:
- - phantomjs --version
+ - ruby
env:
- - PHANTOMJS_VERSION=1.9.8
-gemfile:
- - gemfiles/opal_0.8_react_13.gemfile
- - gemfiles/opal_0.8_react_14.gemfile
- - gemfiles/opal_0.8_react_15.gemfile
- - gemfiles/opal_0.9_react_13.gemfile
- - gemfiles/opal_0.9_react_14.gemfile
- - gemfiles/opal_0.9_react_15.gemfile
-cache:
- directories:
- - "travis_phantomjs"
-branches:
- only:
- - master
+ - DRIVER=travis HYPER_DEV_GEM_SOURCE="https://gems.ruby-hyperloop.org" TZ=Europe/Berlin
+ - DRIVER=beheaded HYPER_DEV_GEM_SOURCE="https://gems.ruby-hyperloop.org" TZ=Europe/Berlin
before_install:
- - "phantomjs --version"
- - "export PATH=$PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64/bin:$PATH"
- - "phantomjs --version"
- - "if [ $(phantomjs --version) != $PHANTOMJS_VERSION ]; then rm -rf $PWD/travis_phantomjs; mkdir -p $PWD/travis_phantomjs; fi"
- - "if [ $(phantomjs --version) != $PHANTOMJS_VERSION ]; then wget https://github.com/Medium/phantomjs/releases/download/v$PHANTOMJS_VERSION/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -O $PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2; fi"
- - "if [ $(phantomjs --version) != $PHANTOMJS_VERSION ]; then tar -xvf $PWD/travis_phantomjs/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs; fi"
- - "phantomjs --version"
- - gem install bundler -v 1.13.7
-script:
- - bundle exec rake test_app
- - bundle exec rake
-# These two setup seems to run indefinitely long
-# further investigation required.
-matrix:
- exclude:
- - rvm: jruby-19mode
- gemfile: gemfiles/opal_0.9_react_13.gemfile
- - rvm: jruby-19mode
- gemfile: gemfiles/opal_0.9_react_14.gemfile
- - rvm: jruby-19mode
- gemfile: gemfiles/opal_0.9_react_15.gemfile
- include:
- - rvm: 2.1
- env: PHANTOMJS_VERSION=2.1.1
- gemfile: gemfiles/opal_0.10_react_13.gemfile
- - rvm: 2.1
- env: PHANTOMJS_VERSION=2.1.1
- gemfile: gemfiles/opal_0.10_react_14.gemfile
- - rvm: 2.1
- env: PHANTOMJS_VERSION=2.1.1
- gemfile: gemfiles/opal_0.10_react_15.gemfile
- - rvm: 2.1
- env: PHANTOMJS_VERSION=2.1.1
- gemfile: gemfiles/opal_master_react_15.gemfile
- allow_failures:
- - rvm: 2.1
- env: PHANTOMJS_VERSION=2.1.1
- gemfile: gemfiles/opal_master_react_15.gemfile
+ - if [[ "$DRIVER" == "travis" ]]; then wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb; fi
+ - if [[ "$DRIVER" == "travis" ]]; then sudo dpkg -i google-chrome*.deb; fi
+ - if [[ "$DRIVER" == "beheaded" ]]; then wget https://github.com/mozilla/geckodriver/releases/download/v0.19.1/geckodriver-v0.19.1-linux64.tar.gz; fi
+ - if [[ "$DRIVER" == "beheaded" ]]; then tar zxf geckodriver-v0.19.1-linux64.tar.gz; fi
+ - if [[ "$DRIVER" == "beheaded" ]]; then sudo mv geckodriver /usr/local/bin/; fi
+ - gem install bundler
+before_script:
+ - cd spec/test_app
+ - bundle update
+ - bundle exec rails db:setup
+ - cd ../../
+ - if [[ "$DRIVER" == "travis" ]]; then chromedriver-update; fi
+ - if [[ "$DRIVER" == "travis" ]]; then ls -lR ~/.chromedriver-helper/; fi
+ - if [[ "$DRIVER" == "travis" ]]; then chromedriver --version; fi
+ - if [[ "$DRIVER" == "travis" ]]; then google-chrome --version; fi
+ - if [[ "$DRIVER" == "travis" ]]; then which chromedriver; fi
+ - if [[ "$DRIVER" == "travis" ]]; then which google-chrome; fi
+ - if [[ "$DRIVER" == "beheaded" ]]; then firefox --version; fi
+ - if [[ "$DRIVER" == "beheaded" ]]; then geckodriver --version; fi
+ - if [[ "$DRIVER" == "beheaded" ]]; then which firefox; fi
+ - if [[ "$DRIVER" == "beheaded" ]]; then which geckodriver; fi
+script: bundle exec rspec
+gemfile:
+ - gemfiles/opal_0_11_react-rails_2_4.gemfile
diff --git a/Appraisals b/Appraisals
index 2004041..4e676b2 100644
--- a/Appraisals
+++ b/Appraisals
@@ -27,5 +27,5 @@ appraise "opal-master-react-15" do
gem 'opal', git: 'https://github.com/opal/opal.git'
gem "opal-sprockets", git: 'https://github.com/opal/opal-sprockets.git'
gem 'opal-rails', '~> 0.9.0'
- gem 'react-rails', '~> 1.10.0', require: false
+ gem 'react-rails', '~> 2.4.0', require: false
end
diff --git a/DOCS.md b/DOCS.md
index 4fbc3c2..a55dce7 100644
--- a/DOCS.md
+++ b/DOCS.md
@@ -1468,7 +1468,7 @@ There are also good tutorials on integrating Webpack with existing rails apps a
```ruby
Hyperloop.configuration do |config|
- config.prerendering = :off # :on by default
+ config.prerendering = :on # :off by default
end
```
diff --git a/Gemfile b/Gemfile
index ec6fa61..33ce79f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,8 +1,4 @@
source 'https://rubygems.org'
+gem "opal-jquery", git: "https://github.com/opal/opal-jquery.git", branch: "master"
+gem "opal-rails", git: "https://github.com/opal/opal-rails.git", branch: "master"
gemspec
-
-ruby ">= 1.9.3"
-
-group :development do
- gem "appraisal"
-end
diff --git a/README.md b/README.md
index 62fa1a5..6abf725 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@
+[](https://travis-ci.org/ruby-hyperloop/hyper-react)
[](https://badge.fury.io/rb/hyper-react)
diff --git a/Rakefile b/Rakefile
index 1e2c349..b2afa26 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,33 +1,44 @@
-require 'bundler'
-Bundler.require
-Bundler::GemHelper.install_tasks
+# require 'bundler'
+# Bundler.require
+# Bundler::GemHelper.install_tasks
+#
+# # Store the BUNDLE_GEMFILE env, since rake or rspec seems to clean it
+# # while invoking task.
+# ENV['REAL_BUNDLE_GEMFILE'] = ENV['BUNDLE_GEMFILE']
+#
+# require 'rspec/core/rake_task'
+# require 'opal/rspec/rake_task'
+#
+# RSpec::Core::RakeTask.new('ruby:rspec')
+#
+# task :test do
+# Rake::Task['ruby:rspec'].invoke
+# end
+#
+# require 'generators/reactive_ruby/test_app/test_app_generator'
+# desc "Generates a dummy app for testing"
+# task :test_app do
+# ReactiveRuby::TestAppGenerator.start
+# puts "Setting up test app database..."
+# system("bundle exec rake db:drop db:create db:migrate > #{File::NULL}")
+# end
+#
+# task :test_prepare do
+# system("./dciy_prepare.sh")
+# end
+#
+# task default: [ :test ]
-# Store the BUNDLE_GEMFILE env, since rake or rspec seems to clean it
-# while invoking task.
-ENV['REAL_BUNDLE_GEMFILE'] = ENV['BUNDLE_GEMFILE']
+require "bundler/gem_tasks"
+require "rspec/core/rake_task"
-require 'rspec/core/rake_task'
-require 'opal/rspec/rake_task'
+RSpec::Core::RakeTask.new(:spec)
-RSpec::Core::RakeTask.new('ruby:rspec')
-
-Opal::RSpec::RakeTask.new('opal:rspec') do |s, task|
- s.append_path 'spec/vendor'
- s.index_path = 'spec/index.html.erb'
- task.timeout = 80000 if task
-end
-
-task :test do
- Rake::Task['ruby:rspec'].invoke
- Rake::Task['opal:rspec'].invoke
-end
-
-require 'generators/reactive_ruby/test_app/test_app_generator'
-desc "Generates a dummy app for testing"
-task :test_app do
- ReactiveRuby::TestAppGenerator.start
- puts "Setting up test app database..."
- system("bundle exec rake db:drop db:create db:migrate > #{File::NULL}")
+namespace :spec do
+ task :prepare do
+ sh %{bundle update}
+ sh %{cd spec/test_app; bundle update}
+ end
end
-task default: [ :test ]
+task :default => :spec
diff --git a/config.ru b/config.ru
deleted file mode 100644
index 889f95d..0000000
--- a/config.ru
+++ /dev/null
@@ -1,26 +0,0 @@
-require 'bundler'
-Bundler.require
-
-require "opal/rspec"
-
-Opal::Config.arity_check_enabled = true
-
-if Opal::RSpec.const_defined?("SprocketsEnvironment")
- sprockets_env = Opal::RSpec::SprocketsEnvironment.new
- sprockets_env.cache = Sprockets::Cache::FileStore.new("tmp")
- sprockets_env.add_spec_paths_to_sprockets
- run Opal::Server.new(sprockets: sprockets_env) { |s|
- s.main = 'opal/rspec/sprockets_runner'
- s.debug = false
- s.append_path 'spec/vendor'
- s.index_path = 'spec/index.html.erb'
- }
-else
- run Opal::Server.new { |s|
- s.main = 'opal/rspec/sprockets_runner'
- s.append_path 'spec'
- s.append_path 'spec/vendor'
- s.debug = false
- s.index_path = 'spec/index.html.erb'
- }
-end
diff --git a/dciy.toml b/dciy.toml
new file mode 100644
index 0000000..d5bb652
--- /dev/null
+++ b/dciy.toml
@@ -0,0 +1,3 @@
+[dciy.commands]
+prepare = ["bundle exec rake spec:prepare"]
+cibuild = ["bundle exec rake"]
diff --git a/gemfiles/opal_0.10_react_13.gemfile b/gemfiles/opal_0.10_react_13.gemfile
deleted file mode 100644
index 7a8c894..0000000
--- a/gemfiles/opal_0.10_react_13.gemfile
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 1.9.3"
-
-gem "opal", "~> 0.10.0"
-gem "opal-rails", "~> 0.9.0"
-gem "react-rails", "~> 1.3.3", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/gemfiles/opal_0.10_react_14.gemfile b/gemfiles/opal_0.10_react_14.gemfile
deleted file mode 100644
index 275bf73..0000000
--- a/gemfiles/opal_0.10_react_14.gemfile
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 1.9.3"
-
-gem "opal", "~> 0.10.0"
-gem "opal-rails", "~> 0.9.0"
-gem "react-rails", "~> 1.6.2", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/gemfiles/opal_0.10_react_15.gemfile b/gemfiles/opal_0.10_react_15.gemfile
deleted file mode 100644
index 5e2fff2..0000000
--- a/gemfiles/opal_0.10_react_15.gemfile
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 1.9.3"
-
-gem "opal", "~> 0.10.0"
-gem "opal-rails", "~> 0.9.0"
-gem "react-rails", "~> 1.10.0", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/gemfiles/opal_0.8_react_13.gemfile b/gemfiles/opal_0.8_react_13.gemfile
deleted file mode 100644
index a36890c..0000000
--- a/gemfiles/opal_0.8_react_13.gemfile
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 1.9.3"
-
-gem "opal", "~> 0.8.0"
-gem "opal-rails", "~> 0.8.1"
-gem "react-rails", "~> 1.3.3", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/gemfiles/opal_0.8_react_14.gemfile b/gemfiles/opal_0.8_react_14.gemfile
deleted file mode 100644
index 5529f7d..0000000
--- a/gemfiles/opal_0.8_react_14.gemfile
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 1.9.3"
-
-gem "opal", "~> 0.8.0"
-gem "opal-rails", "~> 0.8.1"
-gem "react-rails", "~> 1.6.2", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/gemfiles/opal_0.8_react_15.gemfile b/gemfiles/opal_0.8_react_15.gemfile
deleted file mode 100644
index ded477a..0000000
--- a/gemfiles/opal_0.8_react_15.gemfile
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 1.9.3"
-
-gem "opal", "~> 0.8.0"
-gem "opal-rails", "~> 0.8.1"
-gem "react-rails", "~> 1.10.0", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/gemfiles/opal_0.9_react_13.gemfile b/gemfiles/opal_0.9_react_13.gemfile
deleted file mode 100644
index ea11d6b..0000000
--- a/gemfiles/opal_0.9_react_13.gemfile
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 1.9.3"
-
-gem "opal", "~> 0.9.0"
-gem "opal-rails", "~> 0.9.0"
-gem "react-rails", "~> 1.3.3", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/gemfiles/opal_0.9_react_14.gemfile b/gemfiles/opal_0.9_react_14.gemfile
deleted file mode 100644
index 61df4bc..0000000
--- a/gemfiles/opal_0.9_react_14.gemfile
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 1.9.3"
-
-gem "opal", "~> 0.9.0"
-gem "opal-rails", "~> 0.9.0"
-gem "react-rails", "~> 1.6.2", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/gemfiles/opal_0.9_react_15.gemfile b/gemfiles/opal_0.9_react_15.gemfile
deleted file mode 100644
index 602cb8e..0000000
--- a/gemfiles/opal_0.9_react_15.gemfile
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 1.9.3"
-
-gem "opal", "~> 0.9.0"
-gem "opal-rails", "~> 0.9.0"
-gem "react-rails", "~> 1.10.0", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/gemfiles/opal_0_11_react-rails_2_4.gemfile b/gemfiles/opal_0_11_react-rails_2_4.gemfile
new file mode 100644
index 0000000..f4d9fd8
--- /dev/null
+++ b/gemfiles/opal_0_11_react-rails_2_4.gemfile
@@ -0,0 +1,7 @@
+source "https://rubygems.org"
+source ENV['HYPER_DEV_GEM_SOURCE'] if ENV['HYPER_DEV_GEM_SOURCE']
+
+gem "opal-jquery", git: "https://github.com/opal/opal-jquery.git", branch: "master"
+gem "opal-rails", git: "https://github.com/opal/opal-rails.git", branch: "master"
+
+gemspec :path => "../"
diff --git a/gemfiles/opal_master_react_15.gemfile b/gemfiles/opal_master_react_15.gemfile
deleted file mode 100644
index 2ea22d4..0000000
--- a/gemfiles/opal_master_react_15.gemfile
+++ /dev/null
@@ -1,16 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-ruby ">= 2.0.0"
-
-gem "opal", :git => "https://github.com/opal/opal.git"
-gem "opal-sprockets", :git => "https://github.com/opal/opal-sprockets.git"
-gem "opal-rails", "~> 0.9.0"
-gem "react-rails", "~> 1.10.0", :require => false
-
-group :development do
- gem "appraisal"
-end
-
-gemspec :path => "../"
diff --git a/hyper-react.gemspec b/hyper-react.gemspec
index bd50967..e91132d 100644
--- a/hyper-react.gemspec
+++ b/hyper-react.gemspec
@@ -1,48 +1,47 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path('../lib/', __FILE__)
-
require 'reactive-ruby/version'
-Gem::Specification.new do |s|
- s.name = 'hyper-react'
- s.version = React::VERSION
+Gem::Specification.new do |spec|
+ spec.name = 'hyper-react'
+ spec.version = React::VERSION
- s.authors = ['David Chang', 'Adam Jahn', 'Mitch VanDuyn']
- s.email = 'reactrb@catprint.com'
- s.homepage = 'http://ruby-hyperloop.io/gems/reactrb/'
- s.summary = 'Opal Ruby wrapper of React.js library.'
- s.license = 'MIT'
- s.description = "Write React UI components in pure Ruby."
- s.files = `git ls-files`.split("\n")
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
- s.require_paths = ['lib']
+ spec.authors = ['David Chang', 'Adam Jahn', 'Mitch VanDuyn', 'Jan Biedermann']
+ spec.email = ['mitch@catprint.com', 'jan@kursator.com']
+ spec.homepage = 'http://ruby-hyperloop.org'
+ spec.summary = 'Opal Ruby wrapper of React.js library.'
+ spec.license = 'MIT'
+ spec.description = 'Write React UI components in pure Ruby.'
+ # spec.metadata = {
+ # "homepage_uri" => 'http://ruby-hyperloop.org',
+ # "source_code_uri" => 'https://github.com/ruby-hyperloop/hyper-component'
+ # }
- s.add_dependency 'opal', '>= 0.8.0'
- s.add_dependency 'opal-activesupport', '>= 0.2.0'
- s.add_dependency 'hyper-store', '>= 0.2.1'
- s.add_dependency 'hyperloop-config', '>= 0.9.7'
- s.add_development_dependency 'rake', '< 11.0'
- s.add_development_dependency 'rspec-rails', '3.3.3'
- s.add_development_dependency 'timecop'
- s.add_development_dependency 'opal-rspec'
- s.add_development_dependency 'sinatra'
- s.add_development_dependency 'opal-jquery'
+ spec.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(gemfiles|spec)/}) }
+ spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ spec.require_paths = ['lib']
- # For Test Rails App
- s.add_development_dependency 'rails', '4.2.4'
- s.add_development_dependency 'mime-types', '< 3'
- s.add_development_dependency 'opal-rails'
- s.add_development_dependency 'react-rails', '<= 1.10.0'
+ spec.add_dependency 'hyper-store', React::VERSION
+ spec.add_dependency 'opal', '>= 0.11.0', '< 0.12.0'
+ spec.add_dependency 'opal-activesupport', '~> 0.3.1'
- s.add_development_dependency 'nokogiri', '< 1.7'
- s.add_development_dependency 'rubocop'
- if RUBY_PLATFORM == 'java'
- s.add_development_dependency 'jdbc-sqlite3'
- s.add_development_dependency 'activerecord-jdbcsqlite3-adapter'
- s.add_development_dependency 'therubyrhino'
- else
- s.add_development_dependency 'sqlite3', '1.3.10'
- s.add_development_dependency 'therubyracer', '0.12.2'
- end
+ spec.add_development_dependency 'chromedriver-helper'
+ spec.add_development_dependency 'hyper-spec', React::VERSION
+ spec.add_development_dependency 'jquery-rails'
+ spec.add_development_dependency 'listen'
+ spec.add_development_dependency 'mime-types'
+ spec.add_development_dependency 'nokogiri'
+ spec.add_development_dependency 'opal-jquery'
+ spec.add_development_dependency 'opal-rails', '~> 0.9.3'
+ spec.add_development_dependency 'opal-rspec'
+ spec.add_development_dependency 'rails', '>= 4.0.0'
+ spec.add_development_dependency 'rails-controller-testing'
+ spec.add_development_dependency 'rake'
+ spec.add_development_dependency 'react-rails', '>= 2.4.0', '< 2.5.0'
+ spec.add_development_dependency 'rspec-rails'
+ spec.add_development_dependency 'rubocop', '~> 0.51.0'
+ spec.add_development_dependency 'sqlite3'
+ spec.add_development_dependency 'mini_racer', '~> 0.1.15'
+ spec.add_development_dependency 'timecop', '~> 0.8.1'
end
diff --git a/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/server_rendering.js b/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/server_rendering.js
new file mode 100644
index 0000000..6110b3c
--- /dev/null
+++ b/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/server_rendering.js
@@ -0,0 +1,5 @@
+//= require 'react-server'
+//= require 'react_ujs'
+//= require 'components'
+
+Opal.load('components')
\ No newline at end of file
diff --git a/lib/generators/reactive_ruby/test_app/test_app_generator.rb b/lib/generators/reactive_ruby/test_app/test_app_generator.rb
index 41f2dd9..a7c04aa 100644
--- a/lib/generators/reactive_ruby/test_app/test_app_generator.rb
+++ b/lib/generators/reactive_ruby/test_app/test_app_generator.rb
@@ -28,6 +28,8 @@ def configure_test_app
template 'test_application.rb.erb', "#{test_app_path}/config/application.rb", force: true
template 'assets/javascripts/test_application.rb',
"#{test_app_path}/app/assets/javascripts/application.rb", force: true
+ template 'assets/javascripts/server_rendering.js',
+ "#{test_app_path}/app/assets/javascripts/server_rendering.js", force: true
template 'assets/javascripts/components.rb',
"#{test_app_path}/app/views/components.rb", force: true
template 'views/components/hello_world.rb',
@@ -70,6 +72,10 @@ def configure_opal_rspec
config.opal.spec_location = 'spec-opal'
config.hyperloop.auto_config = false
+ config.react.server_renderer_options = {
+ files: ["server_rendering.js"]
+ }
+ config.react.server_renderer_directories = ["/app/assets/javascripts"]
]
end
end
diff --git a/lib/hyper-react.rb b/lib/hyper-react.rb
index 8dcb4ac..754762a 100644
--- a/lib/hyper-react.rb
+++ b/lib/hyper-react.rb
@@ -1,14 +1,12 @@
require 'hyperloop-config'
Hyperloop.import 'hyper-store'
-Hyperloop.import 'react/react-source-browser'
+Hyperloop.import 'react/react-source-browser', client_only: true
Hyperloop.import 'react/react-source-server', server_only: true
-Hyperloop.import 'opal-jquery', client_only: true
Hyperloop.import 'browser/delay', client_only: true
-Hyperloop.import 'react_ujs', client_only: true
Hyperloop.import 'hyper-react'
+Hyperloop.import 'react_ujs'
if RUBY_ENGINE == 'opal'
-
module Hyperloop
class Component
end
@@ -28,6 +26,7 @@ class Component
end
require 'react/hash'
require 'react/top_level'
+ require 'react/top_level_render'
require 'react/observable'
require 'react/validator'
require 'react/component'
@@ -41,7 +40,7 @@ class Component
require 'react/rendering_context'
require 'react/state'
require 'react/object'
- require "react/ext/opal-jquery/element"
+ require 'react/ext/opal-jquery/element'
require 'reactive-ruby/isomorphic_helpers'
require 'rails-helpers/top_level_rails_component'
require 'reactive-ruby/version'
@@ -53,17 +52,11 @@ def self.inherited(child)
end
end
React::Component.deprecation_warning(
- 'components.rb',
+ 'component.rb',
"Requiring 'hyper-react' is deprecated. Use gem 'hyper-component', and require 'hyper-component' instead."
) unless defined? Hyperloop::Component::VERSION
else
require 'opal'
- # rubocop:disable Lint/HandleExceptions
- begin
- require 'opal-jquery'
- rescue LoadError
- end
- # rubocop:enable Lint/HandleExceptions
require 'hyper-store'
require 'opal-activesupport'
@@ -73,5 +66,5 @@ def self.inherited(child)
require 'reactive-ruby/serializers'
Opal.append_path File.expand_path('../', __FILE__).untaint
- require "react/react-source"
+ require 'react/react-source'
end
diff --git a/lib/rails-helpers/top_level_rails_component.rb b/lib/rails-helpers/top_level_rails_component.rb
index 4e25068..27e37af 100644
--- a/lib/rails-helpers/top_level_rails_component.rb
+++ b/lib/rails-helpers/top_level_rails_component.rb
@@ -3,7 +3,7 @@ class TopLevelRailsComponent
include Hyperloop::Component::Mixin
def self.search_path
- @search_path ||= [Module]
+ @search_path ||= [Object]
end
export_component
@@ -16,24 +16,45 @@ def self.search_path
def render
paths_searched = []
- if params.component_name.start_with? "::"
- paths_searched << params.component_name.gsub(/^\:\:/,"")
- component = params.component_name.gsub(/^\:\:/,"").split("::").inject(Module) { |scope, next_const| scope.const_get(next_const, false) } rescue nil
- return present component, params.render_params if component && component.method_defined?(:render)
+ component = nil
+ if params.component_name.start_with?('::')
+ # if absolute path of component is given, look it up and fail if not found
+ paths_searched << params.component_name
+ component = begin
+ Object.const_get(params.component_name)
+ rescue NameError
+ nil
+ end
else
- self.class.search_path.each do |path|
- # try each path + params.controller + params.component_name
- paths_searched << "#{path.name + '::' unless path == Module}#{params.controller}::#{params.component_name}"
- component = "#{params.controller}::#{params.component_name}".split("::").inject(path) { |scope, next_const| scope.const_get(next_const, false) } rescue nil
- return present component, params.render_params if component && component.method_defined?(:render)
+ # if relative path is given, look it up like this
+ # 1) we check each path + controller-name + component-name
+ # 2) if we can't find it there we check each path + component-name
+ # if we can't find it we just try const_get
+ # so (assuming controller name is Home)
+ # ::Foo::Bar will only resolve to some component named ::Foo::Bar
+ # but Foo::Bar will check (in this order) ::Home::Foo::Bar, ::Components::Home::Foo::Bar, ::Foo::Bar, ::Components::Foo::Bar
+ self.class.search_path.each do |scope|
+ paths_searched << "#{scope.name}::#{params.controller}::#{params.component_name}"
+ component = begin
+ scope.const_get(params.controller, false).const_get(params.component_name, false)
+ rescue NameError
+ nil
+ end
+ break if component != nil
end
- self.class.search_path.each do |path|
- # then try each path + params.component_name
- paths_searched << "#{path.name + '::' unless path == Module}#{params.component_name}"
- component = "#{params.component_name}".split("::").inject(path) { |scope, next_const| scope.const_get(next_const, false) } rescue nil
- return present component, params.render_params if component && component.method_defined?(:render)
+ unless component
+ self.class.search_path.each do |scope|
+ paths_searched << "#{scope.name}::#{params.component_name}"
+ component = begin
+ scope.const_get(params.component_name, false)
+ rescue NameError
+ nil
+ end
+ break if component != nil
+ end
end
end
+ return React::RenderingContext.render(component, params.render_params) if component && component.method_defined?(:render)
raise "Could not find component class '#{params.component_name}' for params.controller '#{params.controller}' in any component directory. Tried [#{paths_searched.join(", ")}]"
end
end
diff --git a/lib/react-sources/react-server.js b/lib/react-sources/react-server.js
deleted file mode 100644
index 4236cb8..0000000
--- a/lib/react-sources/react-server.js
+++ /dev/null
@@ -1,2 +0,0 @@
-// A placeholder file to prevent file not found error of requireing
-// `react-server` in react/react-source
diff --git a/lib/react/api.rb b/lib/react/api.rb
index c3ab079..16aef16 100644
--- a/lib/react/api.rb
+++ b/lib/react/api.rb
@@ -27,8 +27,7 @@ def self.eval_native_react_component(name)
(`!!#{component}.prototype.isReactComponent` ||
`!!#{component}.prototype.render`)
is_functional_component = `typeof #{component} === "function"`
- is_not_using_react_v13 = `!Opal.global.React.version.match(/0\.13/)`
- unless is_component_class || (is_not_using_react_v13 && is_functional_component)
+ unless is_component_class || is_functional_component
raise 'does not appear to be a native react component'
end
component
@@ -46,56 +45,84 @@ def self.create_native_react_class(type)
render_fn = (type.method_defined? :_render_wrapper) ? :_render_wrapper : :render
# this was hashing type.to_s, not sure why but .to_s does not work as it Foo::Bar::View.to_s just returns "View"
@@component_classes[type] ||= %x{
- React.createClass({
- displayName: #{type.name},
- propTypes: #{type.respond_to?(:prop_types) ? type.prop_types.to_n : `{}`},
- getDefaultProps: function(){
+ class extends React.Component {
+ constructor(props) {
+ super(props);
+ this.mixins = #{type.respond_to?(:native_mixins) ? type.native_mixins : `[]`};
+ this.statics = #{type.respond_to?(:static_call_backs) ? type.static_call_backs.to_n : `{}`};
+ this.state = {};
+ this.__opalInstanceInitializedState = false;
+ this.__opalInstanceSyncSetState = true;
+ this.__opalInstance = #{type.new(`this`)};
+ this.__opalInstanceInitializedState = true;
+ this.__opalInstanceSyncSetState = false;
+ }
+ static get displayName() {
+ return #{type.name};
+ }
+ static get defaultProps() {
return #{type.respond_to?(:default_props) ? type.default_props.to_n : `{}`};
- },
- mixins: #{type.respond_to?(:native_mixins) ? type.native_mixins : `[]`},
- statics: #{type.respond_to?(:static_call_backs) ? type.static_call_backs.to_n : `{}`},
- componentWillMount: function() {
- var instance = this._getOpalInstance.apply(this);
- return #{`instance`.component_will_mount if type.method_defined? :component_will_mount};
- },
- componentDidMount: function() {
- var instance = this._getOpalInstance.apply(this);
- return #{`instance`.component_did_mount if type.method_defined? :component_did_mount};
- },
- componentWillReceiveProps: function(next_props) {
- var instance = this._getOpalInstance.apply(this);
- return #{`instance`.component_will_receive_props(Hash.new(`next_props`)) if type.method_defined? :component_will_receive_props};
- },
- shouldComponentUpdate: function(next_props, next_state) {
- var instance = this._getOpalInstance.apply(this);
- return #{`instance`.should_component_update?(Hash.new(`next_props`), Hash.new(`next_state`)) if type.method_defined? :should_component_update?};
- },
- componentWillUpdate: function(next_props, next_state) {
- var instance = this._getOpalInstance.apply(this);
- return #{`instance`.component_will_update(Hash.new(`next_props`), Hash.new(`next_state`)) if type.method_defined? :component_will_update};
- },
- componentDidUpdate: function(prev_props, prev_state) {
- var instance = this._getOpalInstance.apply(this);
- return #{`instance`.component_did_update(Hash.new(`prev_props`), Hash.new(`prev_state`)) if type.method_defined? :component_did_update};
- },
- componentWillUnmount: function() {
- var instance = this._getOpalInstance.apply(this);
- return #{`instance`.component_will_unmount if type.method_defined? :component_will_unmount};
- },
- _getOpalInstance: function() {
- if (this.__opalInstance == undefined) {
- var instance = #{type.new(`this`)};
- } else {
- var instance = this.__opalInstance;
+ }
+ static get propTypes() {
+ return #{type.respond_to?(:prop_types) ? type.prop_types.to_n : `{}`};
+ }
+ componentWillMount() {
+ if (#{type.method_defined? :component_will_mount}) {
+ this.__opalInstanceSyncSetState = true;
+ this.__opalInstance.$component_will_mount();
+ this.__opalInstanceSyncSetState = false;
+ }
+ }
+ componentDidMount() {
+ this.__opalInstance.is_mounted = true
+ if (#{type.method_defined? :component_did_mount}) {
+ this.__opalInstanceSyncSetState = false;
+ this.__opalInstance.$component_did_mount();
+ }
+ }
+ componentWillReceiveProps(next_props) {
+ if (#{type.method_defined? :component_will_receive_props}) {
+ this.__opalInstanceSyncSetState = true;
+ this.__opalInstance.$component_will_receive_props(Opal.Hash.$new(next_props));
+ this.__opalInstanceSyncSetState = false;
+ }
+ }
+ shouldComponentUpdate(next_props, next_state) {
+ if (#{type.method_defined? :should_component_update?}) {
+ this.__opalInstanceSyncSetState = false;
+ return this.__opalInstance["$should_component_update?"](Opal.Hash.$new(next_props), Opal.Hash.$new(next_state));
+ } else { return true; }
+ }
+ componentWillUpdate(next_props, next_state) {
+ if (#{type.method_defined? :component_will_update}) {
+ this.__opalInstanceSyncSetState = false;
+ this.__opalInstance.$component_will_update(Opal.Hash.$new(next_props), Opal.Hash.$new(next_state));
}
- this.__opalInstance = instance;
- return instance;
- },
- render: function() {
- var instance = this._getOpalInstance.apply(this);
- return #{`instance`.send(render_fn).to_n};
}
- })
+ componentDidUpdate(prev_props, prev_state) {
+ if (#{type.method_defined? :component_did_update}) {
+ this.__opalInstanceSyncSetState = false;
+ this.__opalInstance.$component_did_update(Opal.Hash.$new(prev_props), Opal.Hash.$new(prev_state));
+ }
+ }
+ componentWillUnmount() {
+ this.__opalInstance.is_mounted = false;
+ if (#{type.method_defined? :component_will_unmount}) {
+ this.__opalInstanceSyncSetState = false;
+ this.__opalInstance.$component_will_unmount();
+ }
+ }
+ componentDidCatch(error, info) {
+ if (#{type.method_defined? :component_did_catch}) {
+ this.__opalInstanceSyncSetState = false;
+ this.__opalInstance.$component_did_catch(error, Opal.Hash.$new(info));
+ }
+ }
+ render() {
+ this.__opalInstanceSyncSetState = false;
+ return this.__opalInstance.$send(render_fn).$to_n();
+ }
+ }
}
end
@@ -103,13 +130,14 @@ def self.create_element(type, properties = {}, &block)
params = []
# Component Spec, Normal DOM, String or Native Component
- if @@component_classes[type]
- params << @@component_classes[type]
- elsif type.kind_of?(Class)
+ ncc = @@component_classes[type]
+ if ncc
+ params << ncc
+ elsif type.is_a?(Class)
params << create_native_react_class(type)
- elsif React::Component::Tags::HTML_TAGS.include?(type)
+ elsif block_given? || React::Component::Tags::HTML_TAGS.include?(type)
params << type
- elsif type.is_a? String
+ elsif type.is_a?(String)
return React::Element.new(type)
else
raise "#{type} not implemented"
@@ -121,9 +149,12 @@ def self.create_element(type, properties = {}, &block)
# Children Nodes
if block_given?
- [yield].flatten.each do |ele|
- params << ele.to_n
- end
+ a = [yield].flatten
+ %x{
+ for(var i=0, l=a.length; i