diff --git a/.travis.yml b/.travis.yml
index 3da3e22aa..fc3867f3b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,13 @@
-dist: xenial
+dist: focal
+
+env:
+ global:
+ - PGUSER=postgres
+ - PGPORT=5432
+ - PGHOST=localhost
addons:
+ postgresql: '12'
apt:
sources:
- sourceline: 'deb http://dl.yarnpkg.com/debian/ stable main'
@@ -8,12 +15,11 @@ addons:
- sourceline: 'deb http://dl.google.com/linux/chrome/deb/ stable main'
key_url: 'https://dl-ssl.google.com/linux/linux_signing_key.pub'
packages:
- - postgresql-11
- chromium-chromedriver
- google-chrome-stable
- yarn
- redis-server
- postgresql: '11'
+ - postgresql-12
_test_gem_pg: &_test_gem_pg
stage: test
@@ -25,11 +31,9 @@ _test_gem_pg: &_test_gem_pg
- node_modules # NPM packages
before_install:
- - echo 'installing postgresql'
- - sudo sed -i 's/port = 5433/port = 5432/' /etc/postgresql/11/main/postgresql.conf
- - sudo cp /etc/postgresql/{9.6,11}/main/pg_hba.conf
- - sudo service postgresql stop
- - sudo service postgresql start 11
+ - sudo sed -i -e '/local.*peer/s/postgres/all/' -e 's/peer\|md5/trust/g' /etc/postgresql/*/main/pg_hba.conf
+ - sudo service postgresql restart
+ - sleep 1
- postgres --version
- sudo rm -f /usr/local/bin/yarn
- nvm install 10
@@ -42,6 +46,8 @@ _test_gem_pg: &_test_gem_pg
- echo before_script $COMPONENT
- echo updating chrome driver
- cd ruby/$COMPONENT
+ - echo creating psql database
+ - psql -c 'create database hyper_mesh_test_db;' -U postgres
- bundle install --jobs=3 --retry=3
- bundle exec ruby -e 'require "webdrivers"; Webdrivers::Chromedriver.update; puts Webdrivers::Chromedriver.current_version'
- ls -la ~/.webdrivers
@@ -50,6 +56,7 @@ _test_gem_pg: &_test_gem_pg
- google-chrome --version
- which google-chrome
- yarn install
+
script:
- echo running script $COMPONENT
- DRIVER=travis bundle exec rake $TASK
@@ -78,12 +85,21 @@ _test_gem: &_test_gem
mariadb: '10.3'
services:
- redis-server
+
before_install:
- echo installing $COMPONENT
+ - sudo apt-get remove --purge mysql-server mysql-client mysql-common
+ - sudo apt-get autoremove
+ - sudo apt-get autoclean
+ - sudo rm -rf /var/lib/mysql
+ - sudo rm -rf /etc/mysql
+ - sudo apt install mariadb-server mariadb-client -y
+ - sudo apt-get install libmysqlclient-dev
+
# yarn is in /usr/local/bin/yarn version 1.3.2 and is not a package
# must remove this zombie for new yarn to work
- sudo rm -f /usr/local/bin/yarn
- - nvm install 10
+ - nvm install 14
- rvm install 2.6.3 # was 2.5.1
- gem install bundler
- echo 'install completed'
@@ -117,106 +133,133 @@ _deploy_gem: &_deploy_gem
jobs:
include:
- - <<: *_test_gem
- env: COMPONENT=rails-hyperstack RUBY_VERSION=2.5.1
- - <<: *_test_gem
- env: COMPONENT=hyper-spec RUBY_VERSION=2.5.1
- - <<: *_test_gem
- env: COMPONENT=hyper-trace RUBY_VERSION=2.5.1
- - <<: *_test_gem
- env: COMPONENT=hyperstack-config RUBY_VERSION=2.5.1
- - <<: *_test_gem
- env: COMPONENT=hyper-state RUBY_VERSION=2.5.1
- - <<: *_test_gem
- env: COMPONENT=hyper-component RUBY_VERSION=2.5.1
- - <<: *_test_gem
- env: COMPONENT=hyper-router RUBY_VERSION=2.5.1
- - <<: *_test_gem
- env: COMPONENT=hyper-store RUBY_VERSION=2.5.1
+ # - <<: *_test_gem
+ # env: COMPONENT=rails-hyperstack RUBY_VERSION=2.5.1
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-spec RUBY_VERSION=2.5.1
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-trace RUBY_VERSION=2.5.1
+ # - <<: *_test_gem
+ # env: COMPONENT=hyperstack-config RUBY_VERSION=2.5.1
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-state RUBY_VERSION=2.5.1
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-component RUBY_VERSION=2.5.1
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-router RUBY_VERSION=2.5.1
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-store RUBY_VERSION=2.5.1
- <<: *_test_gem
env: COMPONENT=hyper-operation RUBY_VERSION=2.5.1
- - <<: *_test_gem_pg
- env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 TASK=part1 DB=hyper_mesh_test_db
- - <<: *_test_gem_pg
- env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 TASK=part2 DB=hyper_mesh_test_db
- - <<: *_test_gem_pg
- env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 TASK=part3 DB=hyper_mesh_test_db
- - <<: *_test_gem
- env: COMPONENT=hyper-i18n RUBY_VERSION=2.5.1
+ # - <<: *_test_gem_pg
+ # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 TASK=part1 DB=hyper_mesh_test_db
+ # - <<: *_test_gem_pg
+ # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 TASK=part2 DB=hyper_mesh_test_db
+ # - <<: *_test_gem_pg
+ # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 TASK=part3 DB=hyper_mesh_test_db
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-i18n RUBY_VERSION=2.5.1
- - <<: *_test_gem
- env: COMPONENT=rails-hyperstack RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-spec RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-trace RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyperstack-config RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-state RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-component RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-router RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-store RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-operation RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem_pg
- env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0' TASK=part1 DB=hyper_mesh_test_db
- - <<: *_test_gem_pg
- env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0' TASK=part2 DB=hyper_mesh_test_db
- - <<: *_test_gem_pg
- env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0' TASK=part3 DB=hyper_mesh_test_db
- - <<: *_test_gem
- env: COMPONENT=hyper-i18n RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=rails-hyperstack RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-spec RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-trace RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyperstack-config RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-state RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-component RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-router RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-store RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-operation RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem_pg
+ # # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0' TASK=part1 DB=hyper_mesh_test_db
+ # # - <<: *_test_gem_pg
+ # # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0' TASK=part2 DB=hyper_mesh_test_db
+ # # - <<: *_test_gem_pg
+ # # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0' TASK=part3 DB=hyper_mesh_test_db
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-i18n RUBY_VERSION=2.5.1 OPAL_VERSION='~>0.11' RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=rails-hyperstack RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-spec RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-trace RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyperstack-config RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-state RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-component RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-router RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-store RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
- - <<: *_test_gem
- env: COMPONENT=hyper-operation RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
- - <<: *_test_gem_pg
- env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0' TASK=part1 DB=hyper_mesh_test_db
- - <<: *_test_gem_pg
- env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0' TASK=part2 DB=hyper_mesh_test_db
- - <<: *_test_gem_pg
- env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0' TASK=part3 DB=hyper_mesh_test_db
- - <<: *_test_gem
- env: COMPONENT=hyper-i18n RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
-
- - <<: *_deploy_gem
- env: COMPONENT=hyper-i18n
- - <<: *_deploy_gem
- env: COMPONENT=hyper-trace
- - <<: *_deploy_gem
- env: COMPONENT=hyper-state
- - <<: *_deploy_gem
- env: COMPONENT=hyper-component
- - <<: *_deploy_gem
- env: COMPONENT=hyper-model
- - <<: *_deploy_gem
- env: COMPONENT=hyper-operation
- - <<: *_deploy_gem
- env: COMPONENT=hyper-router
- - <<: *_deploy_gem
- env: COMPONENT=hyper-spec
- - <<: *_deploy_gem
- env: COMPONENT=hyper-store
- - <<: *_deploy_gem
- env: COMPONENT=rails-hyperstack
- - <<: *_deploy_gem
- env: COMPONENT=hyperstack-config
+ # - <<: *_test_gem
+ # env: COMPONENT=rails-hyperstack RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-spec RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-trace RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+ # - <<: *_test_gem
+ # env: COMPONENT=hyperstack-config RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-state RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-component RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-router RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-store RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-operation RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+ # - <<: *_test_gem_pg
+ # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0' TASK=part1 DB=hyper_mesh_test_db
+ # - <<: *_test_gem_pg
+ # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0' TASK=part2 DB=hyper_mesh_test_db
+ # - <<: *_test_gem_pg
+ # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0' TASK=part3 DB=hyper_mesh_test_db
+ # - <<: *_test_gem
+ # env: COMPONENT=hyper-i18n RUBY_VERSION=2.5.1 RAILS_VERSION='~>6.0.0'
+
+ # # - <<: *_test_gem
+ # # env: COMPONENT=rails-hyperstack RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-spec RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-trace RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyperstack-config RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-state RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-component RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-router RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-store RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-operation RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+ # # - <<: *_test_gem_pg
+ # # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0' TASK=part1 DB=hyper_mesh_test_db
+ # # - <<: *_test_gem_pg
+ # # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0' TASK=part2 DB=hyper_mesh_test_db
+ # # - <<: *_test_gem_pg
+ # # env: COMPONENT=hyper-model RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0' TASK=part3 DB=hyper_mesh_test_db
+ # # - <<: *_test_gem
+ # # env: COMPONENT=hyper-i18n RUBY_VERSION=2.5.1 RAILS_VERSION='~>5.0'
+
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyper-i18n
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyper-trace
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyper-state
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyper-component
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyper-model
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyper-operation
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyper-router
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyper-spec
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyper-store
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=rails-hyperstack
+ # # - <<: *_deploy_gem
+ # # env: COMPONENT=hyperstack-config
diff --git a/current-status.md b/current-status.md
index de398a2e7..5f3b632cc 100644
--- a/current-status.md
+++ b/current-status.md
@@ -10,6 +10,7 @@ We now are issuing 1.0 release candidates weekly until all issues are either clo
| Release
Date | Version | Open
Issues | Documentation
Sections
Draft Ready | Documentation
Sections
WIP |
|--------------|---------|-------------|-------|------|
+| April 12, 2021 | 1.0.alpha1.8 | 128 | 36 | 9 |
| April 5, 2021 | 1.0.alpha1.7 | 147 | 35 | 10 |
| March 29, 2021 | 1.0.alpha1.6 | 167 | 35 | 10 |
diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md
index 2c24fd661..3a639f989 100644
--- a/docs/SUMMARY.md
+++ b/docs/SUMMARY.md
@@ -32,7 +32,7 @@
* [Operations](operations/README.md)
* [Policies](policies/README.md)
* [Internationalization](internationalization/README.md)
-* [Development Workflow and Procedures](development-workflow/README.md)
+* [Development Tools, Workflow and Procedures](development-workflow/README.md)
* [Debugging](development-workflow/debugging.md)
* [HyperTrace](development-workflow/hyper-trace.md)
* [HyperSpec](development-workflow/hyper-spec/README.md)
diff --git a/docs/hyper-model/README.md b/docs/hyper-model/README.md
index b0c5205d0..cad9ae85e 100644
--- a/docs/hyper-model/README.md
+++ b/docs/hyper-model/README.md
@@ -15,7 +15,7 @@ In other words, one browser creates, updates, or destroys a Model, and the chang
* You access your Model data in your Components, Operations, and Stores just like you would on the server or in an ERB or HAML view file.
* If an optional push transport is connected Hyperstack broadcasts any changes made to your ActiveRecord models as they are persisted on the server or updated by one of the authorized clients.
-* Some Models can be designated as _server-only_ which means they are not available to the Isomorphic code.
+* Some Models (or even parts of Models) can be designated as _server-only_ which means they are not available to the client code.
For example, consider a simple model called `Dictionary` which might be part of Wiktionary type app.
@@ -38,8 +38,7 @@ class WordOfTheDay < Hyperstack::Component
def pick_entry!
# pick a random word and assign the selected record to entry
- @entry = Dictionary.defined.all[rand(Dictionary.defined.count)]
- force_update! # redraw our component when the word changes
+ mutate @entry = Dictionary.defined[rand(Dictionary.defined.count)]
# Notice that we use standard ActiveRecord constructs to select our
# random entry value
end
@@ -61,7 +60,8 @@ class WordOfTheDay < Hyperstack::Component
end
```
-For complete examples with _push_ updates, see any of the apps in the `examples` directory, or build your own in 5 minutes following one of the quickstart guides:
+**This is the entire code. There are no application APIs needed. The synchronization between server and client is completely taken care of by HyperModel. If you have
+an existing code base little to updates to your existing Models is needed, and you will use the same ActiveRecord API you have been using.**
## Isomorphic Models
@@ -72,34 +72,7 @@ In order for Hyperstack to see your Models \(and make them Isomorphic\) you need
| **Location of Models** | **Scope** |
| :--- | :--- |
| `app\models` | Server-side code only |
-| `app\Hyperstack\models` | Isomorphic code \(client and server\) |
-
-### Rails 5.1.x
-
-Upto Rails 4.2, all models inherited from `ActiveRecord::Base`. But starting from Rails 5, all models will inherit from `ApplicationRecord`.
-
-To accommodate this change, the following file has been automatically added to models in Rails 5 applications.
-
-```ruby
-# app/models/application_record.rb
-class ApplicationRecord < ActiveRecord::Base
- self.abstract_class = true
-end
-```
-
-For Hyperstack to see this change, this file needs to be moved \(or copied if you have some server-side models\) to the `apps/Hyperstack` folder.
-
-### Explicit Scope Access
-
-In order to prevent unauthorized access to information like scope counts, lists of record ids, etc, Hyperstack now \(see issue [https://github.com/ruby-Hyperstack/hyper-mesh/issues/43](https://github.com/ruby-Hyperstack/hyper-mesh/issues/43)\) requires you explicitly allow scopes to be viewed on the client, otherwise you will get an AccessViolation.
-
-To globally allow access to all scopes add this to the ApplicationRecord class
-
-```ruby
-class ApplicationRecord < ActiveRecord::Base
- regulate_scope :all
-end
-```
+| `app\hyperstack\models` | Isomorphic code \(client and server\) |
## ActiveRecord API
@@ -109,15 +82,15 @@ Hyperstack uses a subset of the standard ActiveRecord API to give your Isomorphi
Hyperstack integrates with React \(through Components\) to deliver your Model data to the client without you having to create extra APIs or specialized controllers. The key idea of React is that when state \(or params\) change, the portions of the display effected by this data will be updated.
-Hyperstack automatically creates React state objects that will be updated as server side data is loaded or changes. When these states change the associated parts of the display will be updated.
+On the client each database record being used by the client is represented as an observable store **([see the chapter on HyperState for details](hyper-state/README.md))** which will mutate as server side data is loaded or changes. When these states change the associated parts of the display will be updated.
-A brief overview of how this works will help you understand the how Hypeloop gets the job done.
+A brief overview of how this works will help you understand the how HyperStack gets the job done.
#### Rendering Cycle
On the UI you will be reading models in order to display data.
-If during the rendering of the display the Model data is not yet loaded, placeholder values \(the default values from the `columns_hash`\) will be returned by Hyperstack.
+If during the rendering of the display the Model data is not yet loaded, placeholder values \(the default values from the database schema\) will be returned by Hyperstack.
Hyperstack then keeps track of where these placeholders \(or `DummyValue`s\) are displayed, and when they do get loaded, those parts of the display will re-render.
@@ -143,7 +116,7 @@ There are a number of methods that allow you to interact with this load cycle wh
#### New and Create
-`new`: Takes a hash of attributes and initializes a new unsaved record. The values of any attributes not specified in the hash will be taken from the Models default values specified in the `columns_hash`.
+`new`: Takes a hash of attributes and initializes a new unsaved record. The values of any attributes not specified in the hash will be taken from the Models default values specified in the data base schema.
If `new` is passed a native javascript object it will be treated as a hash and converted accordingly.
@@ -209,7 +182,7 @@ Word.offset(500).limit(20) # get words 500-519
#### Applying Class Methods to Collections
-Like Rails if you define a class method on a model, you can apply it to collection of those records, allowing you
+Like Rails if you define a class method on a model, you can apply it to a collection of those records, allowing you
to chain methods with scopes (and relationships)
```ruby
@@ -264,6 +237,9 @@ class User < ActiveRecord::Base
end
```
+
+
+
Sometimes it is desirable to only run the method on the server. This can be done using the `server_method` macro:
```ruby
diff --git a/docs/hyper-state/README.md b/docs/hyper-state/README.md
index 5808cba3d..863afa1eb 100644
--- a/docs/hyper-state/README.md
+++ b/docs/hyper-state/README.md
@@ -2,10 +2,10 @@
### Revisiting the Tic Tac Toe Game
-The easiest way to understand HyperState is by example. If you you did not see the Tic-Tac-Toe example, then **[please review it now](client-dsl/interlude-tic-tac-toe.md)**, as we are going to use this to demonstrate how to use the `Hyperstack::State::Observable` module.
+The easiest way to understand HyperState is by example. If you you did not see the Tic-Tac-Toe example, then **[please review it now](/client-dsl/interlude-tic-tac-toe.md)**, as we are going to use this to demonstrate how to use the `Hyperstack::State::Observable` module.
In our original Tic-Tac-Toe implementation the state of the game was stored in the `DisplayGame` component. State was updated by
-"bubbling up" events from lower level components up to `DisplayGame` where the event hander updated the state.
+"bubbling up" events from lower level components up to `DisplayGame` where the event handler updated the state.
This is a nice simple approach but suffers from two issues:
+ Each level of lower level components must be responsible for bubbling up the events to the higher component.
@@ -338,7 +338,7 @@ the appropriate `mutate` or `observe` method.
Typically in a large system you will have one or more central stores, and what you end up passing as parameters are either instances of those stores, or some other kind of index into the store. If there is only one store (as in the case of our Game), you
need not pass any parameters at all.
-We can rewrite the last iteration of DisplayBoard to demonstrate this:
+We can rewrite the previous iteration of `DisplayBoard` to demonstrate this:
```ruby
class DisplaySquare
@@ -348,6 +348,7 @@ class DisplaySquare
.on(:click) { Game.handle_click(id) }
end
end
+
class DisplayBoard < HyperComponent
render(DIV) do
(0..6).step(3) do |row|
@@ -363,7 +364,7 @@ Here `DisplayBoard` no longer takes any parameter (and could be renamed again to
`DisplaySquare` - takes the id of the square to display, but the game or the current board are never passed as parameters;
there is no need to as they are implicit.
-Whether to not pass a store class, an instance of a store, or some other index into the store is a design decision that depends on
+Whether to pass (or not pass) a store class, an instance of a store, or some other index into the store is a design decision that depends on
lots of factors, mainly how you see your application evolving over time.
### Summary of Methods
@@ -503,5 +504,5 @@ a component **unless** the state will be accessed outside the component. Howev
would be better off to move the state into a separate store.
> In addition components also act as the **Observers** in the system. What this means is
-that current component that is running its render method is recording all stores that call `observe`, when
+that the current component that is running its render method is recording all stores that call `observe`, when
a store mutates, then all the components that recorded observations will be rerendered.
diff --git a/docs/hyper-state/old-param-state-stuff.md b/docs/hyper-state/old-param-state-stuff.md
deleted file mode 100644
index bd5e3497c..000000000
--- a/docs/hyper-state/old-param-state-stuff.md
+++ /dev/null
@@ -1,358 +0,0 @@
-
-
-### Param Equality
-
-Params can be arbitrarily
-
-### Params, Immutability and State
-
-Some care must be taken when passing params that are not simple scalars (string, numbers, etc) or JSON like
-combinations of arrays and hashes. When passing more complex objects
-
-Hyperstack differs from React in how it deals with changes in param values
-
-A component will re-render when new param values are received. If it appears that parameter values have changed,
-then the component will not re-render. For scalars such as strings and numbers and JSON like combinations of arrays
-and hashes, the component will be re-rendered if the value of the param changes.
-
-For more complex objects such as application defined classes, there is generally no way to easily determine that an
-object's value has changed. Hyperstack solves this problem with the `Observable` class, that allows objects to
-track which components are depending on their values
-
-In React \(and Hyperstack\) state is mutable. Changes \(mutations\) to state variables cause Components to re-render. Where state is passed into a child Component as a `param`, it will cause a re-rendering of that child Component. Change flows from a parent to a child - change does not flow upward and this is why params are not mutable.
-
-State variables are normal instance variables or objects. When a state variable changes, we use the `mutate` method to get React's attention and cause a re-render. Like normal instance variables, state variables are created when they are first accessed, so there is no explicit declaration.
-
-The syntax of `mutate` is simple - its `mutate` and any other number of parameters and/or a block. Normal evaluation means the parameters are going to be evaluated first, and then `mutate` gets called.
-
-* `mutate @foo = 12, @bar[:zap] = 777` executes the two assignments first, then calls mutate
-* or you can say `mutate { @foo = 12; @bar[:zap] = 777 }` which is more explicit, and does the same thing
-
-Here are some examples:
-
-```ruby
-class Counter < HyperComponent
- before_mount do
- @count = 0 # optional initialization
- end
-
- render(DIV) do
- # note how we mutate count
- BUTTON { "+" }.on(:click) { mutate @count += 1) }
- P { @count.to_s }
- end
-end
-```
-
-```ruby
-class LikeButton < HyperComponent
- render(DIV) do
- BUTTON do
- "You #{@liked ? 'like' : 'haven\'t liked'} this. Click to toggle."
- end.on(:click) do
- mutate @liked = !@liked
- end
- end
-end
-```
-
-### Components are Just State Machines
-
-React thinks of UIs as simple state machines. By thinking of a UI as being in various states and rendering those states, it's easy to keep your UI consistent.
-
-In React, you simply update a component's state, and then the new UI will be rendered on this new state. React takes care of updating the DOM for you in the most efficient way.
-
-### What Components Should Have State?
-
-Most of your components should simply take some params and render based on their value. However, sometimes you need to respond to user input, a server request or the passage of time. For this you use state.
-
-**Try to keep as many of your components as possible stateless.** By doing this you'll isolate the state to its most logical place and minimize redundancy, making it easier to reason about your application.
-
-A common pattern is to create several stateless components that just render data, and have a stateful component above them in the hierarchy that passes its state to its children via `param`s. The stateful component encapsulates all of the interaction logic, while the stateless components take care of rendering data in a declarative way.
-
-State can be held in any object \(not just a Component\). For example:
-
-```ruby
-class TestIt
- def self.swap_state
- @@test = !@@test
- end
-
- def self.result
- @@test ? 'pass' : 'fail'
- end
-end
-
-class TestResults < HyperComponent
- render(DIV) do
- P { "Test is #{TestIt.result}" }
- BUTTON { 'Swap' }.on(:click) do
- mutate TestIt::swap_state
- end
- end
-end
-```
-
-In the example above, the singleton class `TestIt` holds its own internal state which is changed through a `swap_state` class method. The `TestResults` Component has no knowledge of the internal workings of the `TestIt` class.
-
-When the BUTTON is pressed, we call `mutate`, passing the object which is being mutated. The actual mutated value is not important, it is the fact that the _observed_ object \(our `TestIt` class\) is being mutated that will cause a re-render of the _observing_ `TestResults` Component. Think about `mutate` as a way of telling React that the Component needs to be re-rendered as the state has changed.
-
-In the example above, we could also move the _observing_ and _mutating_ behaviour out of the Component completely and manage it in the `TestIt` class - in this case, we would call it a Store. Stores are covered in the Hyper-Store documentation later.
-
-### What Should Go in State?
-
-**State should contain data that a component's instance variables, event handlers, timers, or http requests may change and trigger a UI update.**
-
-When building a stateful component, think about the minimal possible representation of its state, and only store those properties in `state`. Add to your class methods to compute higher level values from your state variables. Avoid adding redundant or computed values as state variables as these values must then be kept in sync whenever state changes.
-
-### What Shouldn't Go in State?
-
-State should contain the minimal amount of data needed to represent your UI's state. As such, it should not contain:
-
-* **Computed data:** Don't worry about precomputing values based on state — it's easier to ensure that your UI is consistent if you do all computation during rendering. For example, if you have an array of list items in state and you want to render the count as a string, simply render `"#{@list_items.length} list items'` in your `render` method rather than storing the count as another state.
-* **Data that does not effect rendering:** Changing an instance variable \(or any object\) that does not affect rendering does not need to be mutated \(i.e you do not need to call `mutate`\).
-
-The rule is simple: anytime you are updating a state variable use `mutate` and your UI will be re-rendered appropriately.
-
-### State and user input
-
-Often in a UI you gather input from a user and re-render the Component as they type. For example:
-
-```ruby
-class UsingState < HyperComponent
-
- render(DIV) do
- # the button method returns an HTML element
- # .on(:click) is an event handeler
- # notice how we use the mutate method to get
- # React's attention. This will cause a
- # re-render of the Component
- button.on(:click) { mutate(@show = !@show) }
- DIV do
- input
- output
- easter_egg
- end if @show
- end
-
- def button
- BUTTON(class: 'ui primary button') do
- @show ? 'Hide' : 'Show'
- end
- end
-
- def input
- DIV(class: 'ui input fluid block') do
- INPUT(type: :text).on(:change) do |evt|
- # we are updating the value per keypress
- # using mutate will cause a rerender
- mutate @input_value = evt.target.value
- end
- end
- end
-
- def output
- # rerender whenever input_value changes
- P { "#{@input_value}" }
- end
-
- def easter_egg
- H2 {'you found it!'} if @input_value == 'egg'
- end
-end
-```
-
-### State and HTTP responses
-
-Often your UI will re-render based on the response to a HTTP request to a remote service. Hyperstack does not need to understand the internals of the HTTP response JSON, but does need to _observe_ the object holding that response so we call `mutate` when updating our response object in the block which executes when the HTTP.get promise resolves.
-
-```ruby
-class FaaS < HyperComponent
- render(DIV) do
- BUTTON { 'faastruby.io' }.on(:click) do
- faast_ruby
- end
-
- DIV(class: :block) do
- P { @hello_response['function_response'].to_s }
- P { "executed in #{@hello_response['execution_time']} ms" }
- end if @hello_response
- end
-
- def faast_ruby
- HTTP.get('https://api.faastruby.io/paulo/hello-world',
- data: {time: true}
- ) do |response|
- # this code executes when the promise resolves
- # notice that we call mutate when updating the state instance variable
- mutate @hello_response = response.json if response.ok?
- end
- end
-end
-```
-
-### State and updating interval
-
-One common use case is a component wanting to update itself on a time interval. It's easy to use the kernel method `every`, but it's important to cancel your interval when you don't need it anymore to save memory. Hyperstack provides Lifecycle Methods \(covered in the next section\) that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide a React friendly `every` function that will automatically get cleaned up when your component is destroyed.
-
-```ruby
-module ReactInterval
-
- def self.included(base)
- base.before_mount do
- @intervals = []
- end
-
- base.before_unmount do
- @intervals.each(&:stop)
- end
- end
-
- def every(seconds, &block)
- Kernel.every(seconds, &block).tap { |i| @intervals << i }
- end
-end
-
-class TickTock < HyperComponent
- include ReactInterval
-
- before_mount do
- @seconds = 0
- end
-
- after_mount do
- every(1) { mutate @seconds = @seconds + 1 }
- end
-
- render(DIV) do
- P { "Hyperstack has been running for #{@seconds} seconds" }
- end
-end
-```
-
-Notice that TickTock effectively has two `before_mount` methods, one that is called to initialize the `@intervals` array and another to initialize `@seconds`
-
-
-
-# Stores
-
-A core concept behind React is that Components contain their own state and pass state down to their children as params. React re-renders the interface based on those state changes. Each Component is discreet and only needs to worry about how to render itself and pass state down to its children.
-
-Sometimes however, at an application level, Components need to be able to share information or state in a way which does not adhere to this strict parent-child relationship.
-
-Some examples of where this can be necessary are:
-
-* Where a child needs to pass a message back to its parent. An example would be if the child component is an item in a list, it might need to inform it's parent that it has been clicked on.
-* When Hyperstack models are passed as params, child components might change the values of fields in the model, which might be rendered elsewhere on the page.
-* There has to be a place to store non-persisted, global application-level data; like the ID of the currently logged in user or a preference or variable that affects the whole UI.
-
-Taking each of these examples, there are ways to accomplish each:
-
-* Child passing a message to parent: the easiest way is to pass a `Proc` as a param to the child from the parent that the child can `call` to pass a message back to the parent. This model works well when there is a simple upward exchange of information \(a child telling a parent that it has been selected for example\). You can read more about Params of type Proc in the Component section of these docs. If howevere, you find yourself adding overusing this method, or passing messages from child to grandparent then you have reached the limits of this method and a Store would be a better option \(read about Stores in this section.\)
-* Models are stores. An instance of a model can be passed between Components, and any Component using the data in a Model to render the UI will re-render when the Model data changes. As an example, if you had a page displaying data from a Model and let's say you have an edit button on that page \(which invokes a Dialog \(Modal\) based Component which receives the model as a param\). As the user edits the Model fields in Dialog, the underlying page will show the changes as they are made as the changes to Model fields will be observed by the parent Components. In this way, Models act very much like Stores.
-* Stores are where global, application wide state can exist in singleton classes that all Components can access or as class instances objects which hold data and state. **A Store is a class or an instance of a class which holds state variables which can affect a re-render of any Component observing that data.**
-
-In technical terms, a Store is a class that includes the `include Hyperstack::State::Observable` mixin, which just adds the `mutate` and `observe` primitive methods \(plus helpers built on top of them\).
-
-In most cases, you will want class level instance variables that share data across components. Occasionally you might need multiple instances of a store that you can pass between Components as params \(much like a Model\).
-
-As an example, let's imagine we have a filter field on a Menu Bar in our application. As the user types, we want the user interface to display only the items which match the filter. As many of the Components on the page might depend on the filter, a singleton Store is the perfect answer.
-
-```ruby
-# app/hyperstack/stores/item_store.rb
-class ItemStore
- include Hyperstack::State::Observable
-
- class << self
- def filter=(f)
- mutate @filter = f
- end
-
- def filter
- observe @filter || ''
- end
- end
-end
-```
-
-In Our application code, we would use the filter like this:
-
-```ruby
-# the TextField on the Menu Bar could look like this:
-TextField(label: 'Filter', value: ItemStore.filter).on(:change) do |e|
- ItemStore.filter = e.target.value
-end
-
-# elsewhere in the code we could use the filter to decide if an item is added to a list
-show_item(item) if item.name.include?(ItemStore.filter)
-```
-
-## The observe and mutate methods
-
-As with Components, you `mutate` an instance variable to notify React that the Component might need to be re-rendered based on the state change of that object. Stores are the same. When you `mutate` and instance variable in Store, all Components that are observing that variable will be re-rendered.
-
-`observe` records that a Component is observing an instance variable in a Store and might need to be re-rendered if the variable is mutated in the future.
-
-> If you `mutate` an instance variable outside of a Component, you need to `observe` it because, for simplicity, a Component observe their own instance vaibales.
-
-The `observe` and `mutate` methods take:
-
-* a single param as shown above
-* a string of params \(`mutate a=1, b=2`\)
-* or a block in which case the entire block will be executed before signalling the rest of the system
-* no params \(handy for adding to the end of a method\)
-
-## Helper methods
-
-To make things easier the `Hyperstack::State::Observable` mixin contains some useful helper methods:
-
-The `observer` and `mutator` methods create a method wrapped in `observe` or `mutate` block.
-
-* `observer`
-* `mutator`
-
-```ruby
-mutator(:inc) { @count = @count + 1 }
-mutator(:reset) { @count = 0 }
-```
-
-The `state_accessor`, `state_reader` and `state_writer` methods work just like `attr_accessor` methods except access is wrapped in the appropriate `mutate` or `observe` method. These methods can be used either at the class or instance level as needed.
-
-* `state_reader`
-* `state_writer`
-* `state_accessor`
-
-Finally there is the `toggle` method which does what it says on the tin.
-
-* `toggle` toggle\(:foo\) === mutate @foo = !@foo
-
-```ruby
-class ClickStore
- include Hyperstack::State::Observable
-
- class << self
- observer(:count) { @count ||= 0 }
- state_writer :count
- mutator(:inc) { @count = @count + 1 }
- mutator(:reset) { @count = 0 }
- end
-end
-```
-
-### Initializing class variables in singleton Store
-
-You can keep the logic around initialization in your Store. Remember that in Ruby your class instance variables can be initialized as the class is defined:
-
-```ruby
-class CardStore
- include Hyperstack::State::Observable
-
- @show_card_status = true
- @show_card_details = false
-
- class << self
- state_accessor :show_card_status
- state_accessor :show_card_details
- end
-end
-```
diff --git a/docs/specs/spec/hyper-state/tic_tac_toe_spec.rb b/docs/specs/spec/hyper-state/tic_tac_toe_spec.rb
index 1604f6989..8961b8bd8 100644
--- a/docs/specs/spec/hyper-state/tic_tac_toe_spec.rb
+++ b/docs/specs/spec/hyper-state/tic_tac_toe_spec.rb
@@ -71,7 +71,6 @@ def history
end
def run_the_spec(initial_history)
- binding.pry
expect(page).to have_content "Next player: X", wait: 0
expect(history).to eq initial_history
expect(squares.count).to eq 9
diff --git a/readme.md b/readme.md
index 5a538c7c2..a255dbe7b 100644
--- a/readme.md
+++ b/readme.md
@@ -46,7 +46,7 @@ We now are issuing 1.0 release candidates weekly until all issues are either clo
| Release
Date | Version | Open
Issues | Documentation
Sections
Draft Ready | Documentation
Sections
WIP |
|--------------|---------|-------------|-------|------|
-| April 5, 2021 | 1.0.alpha1.7 | 147 | 35 | 10 |
+| April 12, 2021 | 1.0.alpha1.8 | 128 | 36 | 9 |
> Open issues includes enhancements, documentation, and discussion issues as well as few bugs.
>
diff --git a/release-notes/1.0.alpha1.8.md b/release-notes/1.0.alpha1.8.md
index 23ec55420..349055818 100644
--- a/release-notes/1.0.alpha1.8.md
+++ b/release-notes/1.0.alpha1.8.md
@@ -2,11 +2,10 @@
| Release
Date | Version | Open
Issues | Documentation
Sections
Draft Ready | Documentation
Sections
WIP |
|--------------|---------|-------------|-------|------|
-| April 12, 2021 | 1.0.alpha1.8 | ?? | ?? | ?? |
+| April 12, 2021 | 1.0.alpha1.8 | 127 | 36 | 9 |
| April 5, 2021 | 1.0.alpha1.7 | 147 | 35 | 10 |
| March 29, 2021 | 1.0.alpha1.6 | 167 | 35 | 10 |
-> Open issues includes enhancements, documentation, and discussion issues as well as few bugs. Additional issues
-may be closed that are not documented below because of duplicates, documentation updates, and old issues previously closed.
+> Open issues includes enhancements, documentation, and discussion issues as well as few bugs. Issues tagged for post launch are not included. Additional issues may be closed that are not documented below because of duplicates, documentation updates, and old issues previously closed.
>
> The documentation WIP (work in progress) numbers are approx, as more sections may be added.
@@ -23,11 +22,15 @@ None
None
### Feature Added
+
++ [#402](https://github.com/hyperstack-org/hyperstack/issues/402) Class level
+`initialize` method will be called at boot for Observers
+ [#401](https://github.com/hyperstack-org/hyperstack/issues/401) Can call `receives` inside the singleton class.
+
### Fixed
-None
++ [#403](https://github.com/hyperstack-org/hyperstack/issues/403) Fixed: `isomorphic` method only worked before mounting
### Not Reproducible
diff --git a/ruby/hyper-component/Gemfile b/ruby/hyper-component/Gemfile
index 7bb59f443..052aad50c 100644
--- a/ruby/hyper-component/Gemfile
+++ b/ruby/hyper-component/Gemfile
@@ -4,9 +4,9 @@ gem 'hyper-spec', path: '../hyper-spec'
gem 'hyperstack-config', path: '../hyperstack-config'
gem 'hyper-store', path: '../hyper-store'
gem 'hyper-state', path: '../hyper-state'
-unless ENV['OPAL_VERSION']&.match("0.11")
- gem 'opal-browser', git: 'https://github.com/opal/opal-browser'
-end
+# unless ENV['OPAL_VERSION']&.match("0.11")
+# gem 'opal-browser', git: 'https://github.com/opal/opal-browser'
+# end
gem 'hyper-trace', path: '../hyper-trace'
#gem 'puma', '~> 3.11.0' # As of adding, version 3.12.0 isn't working so we are locking
diff --git a/ruby/hyper-component/hyper-component.gemspec b/ruby/hyper-component/hyper-component.gemspec
index 8b2049eac..9c1c773c4 100644
--- a/ruby/hyper-component/hyper-component.gemspec
+++ b/ruby/hyper-component/hyper-component.gemspec
@@ -8,7 +8,8 @@ Gem::Specification.new do |spec|
spec.authors = ['David Chang', 'Adam Jahn', 'Mitch VanDuyn', 'Jan Biedermann', 'Adam Creekroad']
spec.email = ['mitch@catprint.com']
- spec.homepage = 'http://hyperstack.org'
+ spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.summary = 'Opal Ruby wrapper of React.js library.'
spec.license = 'MIT'
spec.description = 'Write React UI components in pure Ruby.'
@@ -27,13 +28,13 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'jquery-rails'
spec.add_development_dependency 'listen'
spec.add_development_dependency 'mime-types'
- spec.add_development_dependency 'mini_racer'
+ spec.add_development_dependency 'mini_racer', '< 0.4.0' # something is busted with 0.4.0 and its libv8-node dependency
spec.add_development_dependency 'nokogiri'
spec.add_development_dependency 'opal-jquery'
- spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0'
+ spec.add_development_dependency 'opal-rails'
spec.add_development_dependency 'pry-rescue'
spec.add_development_dependency 'pry-stack_explorer'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
spec.add_development_dependency 'rails-controller-testing'
spec.add_development_dependency 'rake'
diff --git a/ruby/hyper-component/lib/hyperstack/component/version.rb b/ruby/hyper-component/lib/hyperstack/component/version.rb
index 972624ade..de5a13179 100644
--- a/ruby/hyper-component/lib/hyperstack/component/version.rb
+++ b/ruby/hyper-component/lib/hyperstack/component/version.rb
@@ -1,5 +1,5 @@
module Hyperstack
module Component
- VERSION = '1.0.alpha1.7' # '1.0.alpha1.5'
+ VERSION = '1.0.alpha1.8' # '1.0.alpha1.5'
end
end
diff --git a/ruby/hyper-component/spec/active_support_spec.rb b/ruby/hyper-component/spec/active_support_spec.rb
index 8d0546730..a7614ba5f 100644
--- a/ruby/hyper-component/spec/active_support_spec.rb
+++ b/ruby/hyper-component/spec/active_support_spec.rb
@@ -18,6 +18,7 @@ def payments
GenericEnumerable.new([ Payment.new(5), Payment.new(15), Payment.new(10) ])
end
end
+
expect_evaluate_ruby do
{ Payment.new(5) => 5, Payment.new(15) => 15, Payment.new(10) => 10 } == payments.index_with(&:price)
end.to be_truthy
diff --git a/ruby/hyper-component/spec/client_features/component_spec.rb b/ruby/hyper-component/spec/client_features/component_spec.rb
index 8f469c40f..adeca9003 100644
--- a/ruby/hyper-component/spec/client_features/component_spec.rb
+++ b/ruby/hyper-component/spec/client_features/component_spec.rb
@@ -542,7 +542,7 @@ class Lorem; end
end
Hyperstack::Component::ReactTestUtils.render_component_into_document(Foo, bar: 10, lorem: Lorem.new)
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo`\nRequired prop `foo` was not specified\nProvided prop `bar` could not be converted to String/)
end
@@ -560,7 +560,7 @@ class Lorem; end
end
Hyperstack::Component::ReactTestUtils.render_component_into_document(Foo, foo: 10, bar: '10', lorem: Lorem.new)
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n")).to_not match(/prop/)
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n")).to_not match(/prop/)
end
end
@@ -594,10 +594,10 @@ class Foo
foo.class_eval do
render { "hello" }
end
-
+
Hyperstack::Component::ReactTestUtils.render_component_into_document(foo)
end
- expect(page.driver.browser.manage.logs.get(:browser)
+ expect(page.driver.browser.logs.get(:browser)
.reject { |entry| entry.to_s.include?('Deprecated feature') }
.reject { |entry| entry.to_s.include?('Object freezing is not supported by Opal')}
.map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n").size)
@@ -612,7 +612,7 @@ class Foo < Hyperloop::Component
render { Foo }
end
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/did you mean to say Foo()/)
end
end
diff --git a/ruby/hyper-component/spec/client_features/dsl_spec.rb b/ruby/hyper-component/spec/client_features/dsl_spec.rb
index 81aa0a60a..68daab280 100644
--- a/ruby/hyper-component/spec/client_features/dsl_spec.rb
+++ b/ruby/hyper-component/spec/client_features/dsl_spec.rb
@@ -182,7 +182,7 @@ class NestedComp < Hyperloop::Component
class Comp; end
end
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Comp does not appear to be a react component./)
end
diff --git a/ruby/hyper-component/spec/client_features/native_library_spec.rb b/ruby/hyper-component/spec/client_features/native_library_spec.rb
index 2b1f17f3c..1d54d80ba 100644
--- a/ruby/hyper-component/spec/client_features/native_library_spec.rb
+++ b/ruby/hyper-component/spec/client_features/native_library_spec.rb
@@ -171,7 +171,7 @@ class Foo < Hyperstack::Component::NativeLibrary
rename "MispelledComponent" => "Bar"
end
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/NativeLibrary.MispelledComponent is undefined/)
# TODO was testing for cannot import, but that message gets trunkated
end
diff --git a/ruby/hyper-component/spec/client_features/opal_jquery_extensions_spec.rb b/ruby/hyper-component/spec/client_features/opal_jquery_extensions_spec.rb
index 62d7637ed..089333340 100644
--- a/ruby/hyper-component/spec/client_features/opal_jquery_extensions_spec.rb
+++ b/ruby/hyper-component/spec/client_features/opal_jquery_extensions_spec.rb
@@ -90,7 +90,7 @@ class Foo < Hyperloop::Component
Element[JS.call(:eval, "(function () { return window; })();")]
true
end.to be_truthy
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.not_to match(/Exception|Error/)
end
diff --git a/ruby/hyper-component/spec/client_features/param_declaration_spec.rb b/ruby/hyper-component/spec/client_features/param_declaration_spec.rb
index 40befc90b..7d159fb2a 100644
--- a/ruby/hyper-component/spec/client_features/param_declaration_spec.rb
+++ b/ruby/hyper-component/spec/client_features/param_declaration_spec.rb
@@ -125,7 +125,7 @@ class Foo < Hyperloop::Component
end
end
expect(page.body[-60..-19]).to include('
12-string
')
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo1` could not be converted to String/)
end
@@ -155,7 +155,7 @@ class Foo2 < Hyperloop::Component
Hyperstack::Component::ReactTestUtils.render_component_into_document(Foo2, bar: 10, lorem: Lorem.new)
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo2`\nRequired prop `foo` was not specified\nProvided prop `bar` could not be converted to String/)
end
@@ -171,7 +171,7 @@ class Foo < Hyperloop::Component
end
Hyperstack::Component::ReactTestUtils.render_component_into_document(Foo, foo: 10, bar: '10', lorem: Lorem.new)
end
- expect(page.driver.browser.manage.logs.get(:browser).reject { |m| m.message =~ /(D|d)eprecated/ }.map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).reject { |m| m.message =~ /(D|d)eprecated/ }.map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.not_to match(/Warning|Error/)
end
@@ -191,7 +191,7 @@ class Foo < Hyperloop::Component
param :bar, type: []
end
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo` could not be converted to Array/)
end
@@ -202,7 +202,7 @@ class Foo < Hyperloop::Component
param :bar, type: [String]
end
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo`\[0\] could not be converted to String/)
end
@@ -227,7 +227,7 @@ def self._react_param_conversion(json, validate_only)
end
end
expect(page.body[-60..-19]).to include('1, 2')
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo` could not be converted to BazWoggle/)
end
diff --git a/ruby/hyper-component/spec/client_features/state_spec.rb b/ruby/hyper-component/spec/client_features/state_spec.rb
index e3dacde8f..29d0b9b40 100644
--- a/ruby/hyper-component/spec/client_features/state_spec.rb
+++ b/ruby/hyper-component/spec/client_features/state_spec.rb
@@ -40,7 +40,7 @@ class << self
end
expect_evaluate_ruby("MARKUP").to eq('Boom')
expect_evaluate_ruby("StateTest.boom").to be_falsy
- expect(page.driver.browser.manage.logs.get(:browser).reject { |entry|
+ expect(page.driver.browser.logs.get(:browser).reject { |entry|
entry_s = entry.to_s
entry_s.include?("Deprecated feature") ||
entry_s.include?("Mount() on the server. This is a no-op.") ||
diff --git a/ruby/hyper-component/spec/deprecated_features/param_declaration_legacy_spec.rb b/ruby/hyper-component/spec/deprecated_features/param_declaration_legacy_spec.rb
index a7156e80b..d767b7b1b 100644
--- a/ruby/hyper-component/spec/deprecated_features/param_declaration_legacy_spec.rb
+++ b/ruby/hyper-component/spec/deprecated_features/param_declaration_legacy_spec.rb
@@ -49,7 +49,7 @@ def setup
element = Hyperstack::Component::ReactAPI.create_element(Foo).on(:foo_submit) { 'bar' }
Hyperstack::Component::ReactTestUtils.render_into_document(element)
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to_not match(/Exception raised/)
end
@@ -73,7 +73,7 @@ def setup
element = Hyperstack::Component::ReactAPI.create_element(Foo).on(:foo_invoked) { return [1,2,3], 'bar' }
Hyperstack::Component::ReactTestUtils.render_into_document(element)
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to_not match(/Exception raised/)
end
end
@@ -199,7 +199,7 @@ class Foo < Hyperloop::Component
end
end
expect(page.body[-60..-19]).to include('12-string
')
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo1` could not be converted to String/)
end
@@ -216,7 +216,7 @@ class Foo2 < Hyperloop::Component
Hyperstack::Component::ReactTestUtils.render_component_into_document(Foo2, bar: 10, lorem: Lorem.new)
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo2`\nRequired prop `foo` was not specified\nProvided prop `bar` could not be converted to String/)
end
@@ -233,7 +233,7 @@ class Foo < Hyperloop::Component
end
Hyperstack::Component::ReactTestUtils.render_component_into_document(Foo, foo: 10, bar: '10', lorem: Lorem.new)
end
- expect(page.driver.browser.manage.logs.get(:browser).reject { |m| m.message =~ /(D|d)eprecated/ }.map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).reject { |m| m.message =~ /(D|d)eprecated/ }.map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.not_to match(/Warning|Error/)
end
@@ -254,7 +254,7 @@ class Foo < Hyperloop::Component
param :bar, type: []
end
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo` could not be converted to Array/)
end
@@ -265,7 +265,7 @@ class Foo < Hyperloop::Component
param :bar, type: [String]
end
end
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo`\[0\] could not be converted to String/)
end
@@ -290,7 +290,7 @@ def self._react_param_conversion(json, validate_only)
end
end
expect(page.body[-60..-19]).to include('1, 2')
- expect(page.driver.browser.manage.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
+ expect(page.driver.browser.logs.get(:browser).map { |m| m.message.gsub(/\\n/, "\n") }.to_a.join("\n"))
.to match(/Warning: Failed prop( type|Type): In component `Foo`\nProvided prop `foo` could not be converted to BazWoggle/)
end
diff --git a/ruby/hyper-component/spec/spec_helper.rb b/ruby/hyper-component/spec/spec_helper.rb
index 47c233658..2c3f55c5c 100644
--- a/ruby/hyper-component/spec/spec_helper.rb
+++ b/ruby/hyper-component/spec/spec_helper.rb
@@ -1,7 +1,6 @@
ENV["RAILS_ENV"] ||= 'test'
require 'opal'
-#require 'opal-rspec'
require 'opal-jquery'
begin
@@ -12,10 +11,8 @@
require 'rspec/rails'
require 'hyper-spec'
require 'pry'
-require 'opal-browser'
require 'timecop'
-
RSpec.configure do |config|
config.color = true
config.fail_fast = ENV['FAIL_FAST'] || false
@@ -51,13 +48,13 @@
# Fail tests on JavaScript errors in Chrome Headless
class JavaScriptError < StandardError; end
- config.after(:each, js: true) do |spec|
- logs = page.driver.browser.manage.logs.get(:browser)
+ config.after(:each, js: true) do
+ logs = page.driver.browser.logs.get(:browser)
errors = logs.select { |e| e.level == "SEVERE" && e.message.present? }
- .map { |m| m.message.gsub(/\\n/, "\n") }.to_a
+ .map { |m| m.message.gsub(/\\n/, "\n") }.to_a
if client_options[:deprecation_warnings] == :on
warnings = logs.select { |e| e.level == "WARNING" && e.message.present? }
- .map { |m| m.message.gsub(/\\n/, "\n") }.to_a
+ .map { |m| m.message.gsub(/\\n/, "\n") }.to_a
puts "\033[0;33;1m\nJavascript client console warnings:\n\n" + warnings.join("\n\n") + "\033[0;30;21m" if warnings.present?
end
unless client_options[:raise_on_js_errors] == :off
diff --git a/ruby/hyper-component/spec/test_app/app/assets/config/manifest.js b/ruby/hyper-component/spec/test_app/app/assets/config/manifest.js
index b16e53d6d..27de0df30 100644
--- a/ruby/hyper-component/spec/test_app/app/assets/config/manifest.js
+++ b/ruby/hyper-component/spec/test_app/app/assets/config/manifest.js
@@ -1,3 +1,4 @@
//= link_tree ../images
//= link_directory ../javascripts .js
+//= link application.css
//= link_directory ../stylesheets .css
diff --git a/ruby/hyper-component/spec/test_app/app/hyperstack/components/components.rb b/ruby/hyper-component/spec/test_app/app/hyperstack/components/components.rb
index 87bfdc23a..edac28d18 100644
--- a/ruby/hyper-component/spec/test_app/app/hyperstack/components/components.rb
+++ b/ruby/hyper-component/spec/test_app/app/hyperstack/components/components.rb
@@ -1,14 +1,4 @@
-# require 'hyper-component'
-# if Hyperstack::Component::IsomorphicHelpers.on_opal_client?
-# require 'browser'
-# require 'browser/delay'
-# #require 'react/ext/opal-jquery/element'
-# require 'hyperstack/component/jquery'
-# end
-# require 'hyperstack/component/server'
-# require 'hyperstack/component/auto-import'
require 'js'
-# require 'hyper-store'
require 'hyperstack/internal/component/haml'
# these mechanisms are deprecated in favor of using the features of hyper-spec. However
diff --git a/ruby/hyper-component/spec/test_app/app/xxxjavascript/packs/client_only.js b/ruby/hyper-component/spec/test_app/app/xxxjavascript/packs/client_only.js
new file mode 100644
index 000000000..52f446dd4
--- /dev/null
+++ b/ruby/hyper-component/spec/test_app/app/xxxjavascript/packs/client_only.js
@@ -0,0 +1,7 @@
+//app/javascript/packs/client_only.js
+// add any requires for packages that will run client side only
+ReactDOM = require('react-dom'); // react-js client side code
+jQuery = require('jquery'); // remove if you don't need jQuery
+// to add additional NPM packages call run yarn add package-name@version
+// then add the require here.
+
diff --git a/ruby/hyper-component/spec/test_app/config/application.rb b/ruby/hyper-component/spec/test_app/config/application.rb
index 383ddfaec..1b198059e 100644
--- a/ruby/hyper-component/spec/test_app/config/application.rb
+++ b/ruby/hyper-component/spec/test_app/config/application.rb
@@ -5,7 +5,7 @@
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups(assets: %w(development test)))
-# require 'jquery-rails'
+require 'jquery-rails'
# require 'opal'
# require 'opal-jquery'
# require 'opal-browser'
diff --git a/ruby/hyper-console/lib/hyperloop/console/version.rb b/ruby/hyper-console/lib/hyperloop/console/version.rb
index bb6cf77b4..7d7cbeb0f 100644
--- a/ruby/hyper-console/lib/hyperloop/console/version.rb
+++ b/ruby/hyper-console/lib/hyperloop/console/version.rb
@@ -1,5 +1,5 @@
module Hyperloop
module Console
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
end
diff --git a/ruby/hyper-i18n/hyper-i18n.gemspec b/ruby/hyper-i18n/hyper-i18n.gemspec
index 568d1a7f9..304b20aa0 100644
--- a/ruby/hyper-i18n/hyper-i18n.gemspec
+++ b/ruby/hyper-i18n/hyper-i18n.gemspec
@@ -11,7 +11,8 @@ Gem::Specification.new do |spec|
spec.email = ['adamgeorge.31@gmail.com']
spec.summary = 'HyperI18n seamlessly brings Rails I18n into your Hyperstack application.'
- spec.homepage = 'https://www.github.com/ruby-hyperstack/hyper-i18n'
+ spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = 'MIT'
spec.files = `git ls-files`.split("\n")
@@ -26,10 +27,10 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'chromedriver-helper'
spec.add_development_dependency 'hyper-model', Hyperstack::I18n::VERSION
spec.add_development_dependency 'hyper-spec', Hyperstack::I18n::VERSION
- spec.add_development_dependency 'mini_racer'
- spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0.0'
+ spec.add_development_dependency 'mini_racer', '< 0.4.0' # something is busted with 0.4.0 and its libv8-node dependency
+ spec.add_development_dependency 'opal-rails'
spec.add_development_dependency 'pry'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'rake', '~> 10.0'
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'rspec-rails'
diff --git a/ruby/hyper-i18n/lib/hyper-i18n/version.rb b/ruby/hyper-i18n/lib/hyper-i18n/version.rb
index 32802d9f0..23b0d5f44 100644
--- a/ruby/hyper-i18n/lib/hyper-i18n/version.rb
+++ b/ruby/hyper-i18n/lib/hyper-i18n/version.rb
@@ -1,3 +1,3 @@
module HyperI18n
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
diff --git a/ruby/hyper-i18n/lib/hyperstack/i18n/version.rb b/ruby/hyper-i18n/lib/hyperstack/i18n/version.rb
index 6fbb26b65..414e46f90 100644
--- a/ruby/hyper-i18n/lib/hyperstack/i18n/version.rb
+++ b/ruby/hyper-i18n/lib/hyperstack/i18n/version.rb
@@ -1,5 +1,5 @@
module Hyperstack
module I18n
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
end
diff --git a/ruby/hyper-model/hyper-model.gemspec b/ruby/hyper-model/hyper-model.gemspec
index 61e8d1788..e20545e48 100644
--- a/ruby/hyper-model/hyper-model.gemspec
+++ b/ruby/hyper-model/hyper-model.gemspec
@@ -14,12 +14,8 @@ Gem::Specification.new do |spec|
'possible technologies) so changes to records on the server are '\
'dynamically updated on all authorised clients.'
spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = 'MIT'
- # spec.metadata = {
- # "homepage_uri" => 'http://ruby-hyperstack.org',
- # "source_code_uri" => 'https://github.com/ruby-hyperstack/hyper-component'
- # }
-
spec.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(examples|gemfiles|pkg|reactive_record_test_app|spec)/}) }
# spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
spec.test_files = `git ls-files -- {spec}/*`.split("\n")
@@ -34,12 +30,12 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'factory_bot_rails'
spec.add_development_dependency 'hyper-spec', HyperModel::VERSION
spec.add_development_dependency 'hyper-trace', HyperModel::VERSION
- spec.add_development_dependency 'mini_racer'
+ spec.add_development_dependency 'mini_racer', '< 0.4.0' # something is busted with 0.4.0 and its libv8-node dependency
spec.add_development_dependency 'pg'
- spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0'
+ spec.add_development_dependency 'opal-rails'
spec.add_development_dependency 'pry-rescue'
spec.add_development_dependency 'pry-stack_explorer'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'pusher'
spec.add_development_dependency 'pusher-fake'
spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
diff --git a/ruby/hyper-model/lib/hyper_model/version.rb b/ruby/hyper-model/lib/hyper_model/version.rb
index e990965a4..a5881f945 100644
--- a/ruby/hyper-model/lib/hyper_model/version.rb
+++ b/ruby/hyper-model/lib/hyper_model/version.rb
@@ -1,3 +1,3 @@
module HyperModel
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
diff --git a/ruby/hyper-model/lib/reactive_record/active_record/class_methods.rb b/ruby/hyper-model/lib/reactive_record/active_record/class_methods.rb
index 4e7a75b79..e4977b83e 100644
--- a/ruby/hyper-model/lib/reactive_record/active_record/class_methods.rb
+++ b/ruby/hyper-model/lib/reactive_record/active_record/class_methods.rb
@@ -197,14 +197,18 @@ def alias_attribute(new_name, old_name)
]
def method_missing(name, *args, &block)
- if name == 'human_attribute_name'
+ # In MRI Ruby we would never get to this point with a nil name argument,
+ # but currently in Opal we do, so we will mimic MRI Ruby and throw a TypeError.
+ raise TypeError, "nil is not a symbol nor a string" if name.nil?
+
+ if name == "human_attribute_name"
opts = args[1] || {}
opts[:default] || args[0]
elsif args.count == 1 && name.start_with?("find_by_") && !block
- find_by(name.sub(/^find_by_/, '') => args[0])
+ find_by(name.sub(/^find_by_/, "") => args[0])
elsif [].respond_to?(name)
all.send(name, *args, &block)
- elsif name.end_with?('!')
+ elsif name.end_with?("!")
send(name.chop, *args, &block).send(:reload_from_db) rescue nil
elsif !SERVER_METHODS.include?(name)
raise "#{self.name}.#{name}(#{args}) (called class method missing)"
diff --git a/ruby/hyper-model/spec/batch1/active_record/class_methods_spec.rb b/ruby/hyper-model/spec/batch1/active_record/class_methods_spec.rb
new file mode 100644
index 000000000..a33a52b85
--- /dev/null
+++ b/ruby/hyper-model/spec/batch1/active_record/class_methods_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+describe "ActiveRecord::ClassMethods", js: true do
+ context "method_missing" do
+ it "should return a TypeError if name is nil" do
+ expect_evaluate_ruby do
+ error = nil
+
+ begin
+ User.send(nil)
+ rescue StandardError => e
+ error = e
+ end
+
+ error
+ end.to eq("nil is not a symbol nor a string")
+ end
+ end
+end
diff --git a/ruby/hyper-model/spec/batch3/has_and_belongs_to_many_spec.rb b/ruby/hyper-model/spec/batch3/has_and_belongs_to_many_spec.rb
index 6b2e2d073..be2fc20e7 100644
--- a/ruby/hyper-model/spec/batch3/has_and_belongs_to_many_spec.rb
+++ b/ruby/hyper-model/spec/batch3/has_and_belongs_to_many_spec.rb
@@ -88,6 +88,7 @@ class Patient < ActiveRecord::Base
expect { Physician.first.patients.count }.on_client_to eq(1)
Patient.create(name: 'Spock').physicians << mccoy
+ sleep 0.2
expect { Hyperstack::Model.load { Physician.first.patients.count } }.on_client_to eq(2)
on_client { Patient.create(name: 'Uhuru') }
diff --git a/ruby/hyper-model/spec/spec_helper.rb b/ruby/hyper-model/spec/spec_helper.rb
index b860162e1..28c895a47 100644
--- a/ruby/hyper-model/spec/spec_helper.rb
+++ b/ruby/hyper-model/spec/spec_helper.rb
@@ -176,7 +176,7 @@ def finished_all_ajax_requests?
module CheckErrors
def check_errors
- logs = page.driver.browser.manage.logs.get(:browser)
+ logs = page.driver.browser.logs.get(:browser)
errors = logs.select { |e| e.level == "SEVERE" && e.message.present? }
.map { |m| m.message.gsub(/\\n/, "\n") }.to_a
puts "WARNING - FOUND UNEXPECTED ERRORS #{errors}" if errors.present?
@@ -308,7 +308,7 @@ class << self
class JavaScriptError < StandardError; end
config.after(:each, js: true) do |spec|
- logs = page.driver.browser.manage.logs.get(:browser)
+ logs = page.driver.browser.logs.get(:browser)
if spec.exception
all_messages = logs.select { |e| e.message.present? }
.map { |m| m.message.gsub(/\\n/, "\n") }.to_a
@@ -336,7 +336,7 @@ class JavaScriptError < StandardError; end
# Capybara.register_driver :chrome do |app|
# #caps = Selenium::WebDriver::Remote::Capabilities.chrome("chromeOptions" => {"excludeSwitches" => [ "ignore-certificate-errors" ]})
# caps = Selenium::WebDriver::Remote::Capabilities.chrome("chromeOptions" => {"args" => [ "--window-size=200,200" ]})
- # Capybara::Selenium::Driver.new(app, :browser => :chrome, :desired_capabilities => caps)
+ # Capybara::Selenium::Driver.new(app, :browser => :chrome, :capabilities => caps)
# end
# Use legacy hyper-spec on_client behavior
diff --git a/ruby/hyper-model/spec/test_app/app/assets/config/manifest.js b/ruby/hyper-model/spec/test_app/app/assets/config/manifest.js
new file mode 100644
index 000000000..9c361e667
--- /dev/null
+++ b/ruby/hyper-model/spec/test_app/app/assets/config/manifest.js
@@ -0,0 +1,2 @@
+ //= link_directory ../javascripts .js
+ //= link_directory ../stylesheets .css
\ No newline at end of file
diff --git a/ruby/hyper-model/spec/test_app/db/schema.rb b/ruby/hyper-model/spec/test_app/db/schema.rb
deleted file mode 100644
index 82639473f..000000000
--- a/ruby/hyper-model/spec/test_app/db/schema.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-# This file is auto-generated from the current state of the database. Instead
-# of editing this file, please use the migrations feature of Active Record to
-# incrementally modify your database, and then regenerate this schema definition.
-#
-# This file is the source Rails uses to define your schema when running `rails
-# db:schema:load`. When creating a new database, `rails db:schema:load` tends to
-# be faster and is potentially less error prone than running all of your
-# migrations from scratch. Old migrations may fail to apply correctly if those
-# migrations use external dependencies or application code.
-#
-# It's strongly recommended that you check this file into your version control system.
-
-ActiveRecord::Schema.define(version: 2021_02_28_200459) do
-
- # These are extensions that must be enabled in order to support this database
- enable_extension "plpgsql"
-
- create_table "addresses", force: :cascade do |t|
- t.string "street"
- t.string "city"
- t.string "state"
- t.string "zip"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- create_table "bones", force: :cascade do |t|
- t.integer "dog_id"
- end
-
- create_table "child_models", force: :cascade do |t|
- t.string "child_attribute"
- t.bigint "test_model_id"
- t.index ["test_model_id"], name: "index_child_models_on_test_model_id"
- end
-
- create_table "comments", force: :cascade do |t|
- t.text "comment"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.bigint "todo_id"
- t.bigint "author_id"
- t.integer "user_id"
- t.integer "todo_item_id"
- t.index ["author_id"], name: "index_comments_on_author_id"
- t.index ["todo_id"], name: "index_comments_on_todo_id"
- end
-
- create_table "hyperstack_connections", force: :cascade do |t|
- t.string "channel"
- t.string "session"
- t.datetime "created_at"
- t.datetime "expires_at"
- t.datetime "refresh_at"
- end
-
- create_table "hyperstack_queued_messages", force: :cascade do |t|
- t.text "data"
- t.integer "connection_id"
- end
-
- create_table "pets", force: :cascade do |t|
- t.integer "owner_id"
- end
-
- create_table "scratching_posts", force: :cascade do |t|
- t.integer "cat_id"
- end
-
- create_table "test_models", force: :cascade do |t|
- t.string "test_attribute"
- t.boolean "completed"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- end
-
- create_table "todo_items", force: :cascade do |t|
- t.string "title"
- t.text "description"
- t.boolean "complete"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.integer "user_id"
- t.integer "comment_id"
- end
-
- create_table "todos", force: :cascade do |t|
- t.string "title"
- t.text "description"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.boolean "completed", default: false, null: false
- t.bigint "created_by_id"
- t.bigint "owner_id"
- t.index ["created_by_id"], name: "index_todos_on_created_by_id"
- t.index ["owner_id"], name: "index_todos_on_owner_id"
- end
-
- create_table "users", force: :cascade do |t|
- t.string "role"
- t.bigint "manager_id"
- t.string "first_name"
- t.string "last_name"
- t.string "email"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "address_street"
- t.string "address_city"
- t.string "address_state"
- t.string "address_zip"
- t.integer "address_id"
- t.string "address2_street"
- t.string "address2_city"
- t.string "address2_state"
- t.string "address2_zip"
- t.string "data_string"
- t.integer "data_times"
- t.integer "test_enum"
- t.index ["manager_id"], name: "index_users_on_manager_id"
- end
-
-end
diff --git a/ruby/hyper-operation/hyper-operation.gemspec b/ruby/hyper-operation/hyper-operation.gemspec
index d4bec9065..98358a6d8 100644
--- a/ruby/hyper-operation/hyper-operation.gemspec
+++ b/ruby/hyper-operation/hyper-operation.gemspec
@@ -10,12 +10,8 @@ Gem::Specification.new do |spec|
spec.email = ['mitch@catprint.com', 'jan@kursator.com']
spec.summary = 'HyperOperations are the swiss army knife of the Hyperstack'
spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = 'MIT'
- # spec.metadata = {
- # "homepage_uri" => 'http://ruby-hyperstack.org',
- # "source_code_uri" => 'https://github.com/ruby-hyperstack/hyper-component'
- # }
-
spec.files = `git ls-files -z`
.split("\x0")
.reject { |f| f.match(%r{^(gemfiles|examples|spec)/}) }
@@ -34,11 +30,11 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'database_cleaner'
spec.add_development_dependency 'hyper-spec', Hyperstack::Operation::VERSION
spec.add_development_dependency 'mysql2'
- spec.add_development_dependency 'opal-browser', '~> 0.2.0'
- spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0'
+ # spec.add_development_dependency 'opal-browser', '~> 0.2.0'
+ spec.add_development_dependency 'opal-rails'
spec.add_development_dependency 'pry-rescue'
spec.add_development_dependency 'pry-stack_explorer'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'pusher'
spec.add_development_dependency 'pusher-fake'
spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
diff --git a/ruby/hyper-operation/lib/hyper-operation/transport/hyperstack.rb b/ruby/hyper-operation/lib/hyper-operation/transport/hyperstack.rb
index 1d78cc26b..31de6917e 100644
--- a/ruby/hyper-operation/lib/hyper-operation/transport/hyperstack.rb
+++ b/ruby/hyper-operation/lib/hyper-operation/transport/hyperstack.rb
@@ -70,7 +70,7 @@ def self.reset_operations
if connection[:adapter] == :redis
require 'redis'
- connection[:redis_url] ||= 'redis://127.0.0.1:6379/hyperstack'
+ connection[:redis_url] ||= 'redis://127.0.0.1:6379/0'
end
end
diff --git a/ruby/hyper-operation/lib/hyper-operation/version.rb b/ruby/hyper-operation/lib/hyper-operation/version.rb
index 503992a35..2a0e07d81 100644
--- a/ruby/hyper-operation/lib/hyper-operation/version.rb
+++ b/ruby/hyper-operation/lib/hyper-operation/version.rb
@@ -1,5 +1,5 @@
module Hyperstack
class Operation
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
end
diff --git a/ruby/hyper-operation/spec/spec_helper.rb b/ruby/hyper-operation/spec/spec_helper.rb
index c773c3b06..c6d3924da 100644
--- a/ruby/hyper-operation/spec/spec_helper.rb
+++ b/ruby/hyper-operation/spec/spec_helper.rb
@@ -125,7 +125,7 @@ def self.on_server?
# class JavaScriptError < StandardError; end
# config.after(:each, js: true) do |spec|
- # errors = page.driver.browser.manage.logs.get(:browser)
+ # errors = page.driver.browser.logs.get(:browser)
# .select { |e| e.level == "SEVERE" && e.message.present? }
# #.map { |m| m.message.gsub(/\\n/, "\n") }.to_a
# #.reject { |e| e =~ /Unexpected response code: 200/ }
diff --git a/ruby/hyper-operation/spec/test_app/app/assets/config/manifest.js b/ruby/hyper-operation/spec/test_app/app/assets/config/manifest.js
new file mode 100644
index 000000000..9c361e667
--- /dev/null
+++ b/ruby/hyper-operation/spec/test_app/app/assets/config/manifest.js
@@ -0,0 +1,2 @@
+ //= link_directory ../javascripts .js
+ //= link_directory ../stylesheets .css
\ No newline at end of file
diff --git a/ruby/hyper-operation/spec/test_app/config/application.rb b/ruby/hyper-operation/spec/test_app/config/application.rb
index 424c42ada..b763a19e4 100644
--- a/ruby/hyper-operation/spec/test_app/config/application.rb
+++ b/ruby/hyper-operation/spec/test_app/config/application.rb
@@ -23,6 +23,7 @@ class Application < Rails::Application
config.opal.enable_specs = true
config.opal.spec_location = 'spec-opal'
config.hyperstack.auto_config = false
+ config.active_record.yaml_column_permitted_classes = [Symbol, ActiveSupport::HashWithIndifferentAccess]
config.assets.cache_store = :null_store
# Settings in config/environments/* take precedence over those specified here.
diff --git a/ruby/hyper-router/hyper-router.gemspec b/ruby/hyper-router/hyper-router.gemspec
index 2418fc684..c6d186d38 100644
--- a/ruby/hyper-router/hyper-router.gemspec
+++ b/ruby/hyper-router/hyper-router.gemspec
@@ -7,7 +7,8 @@ Gem::Specification.new do |spec|
spec.version = HyperRouter::VERSION
spec.authors = ['Adam George', 'Jan Biedermann']
spec.email = ['adamgeorge.31@gmail.com', 'jan@kursator.com']
- spec.homepage = 'http://hyperstack.org'
+ spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = 'MIT'
spec.summary = 'hyper-router for Opal, part of the hyperstack framework'
@@ -16,18 +17,18 @@ Gem::Specification.new do |spec|
spec.add_dependency 'hyper-component', HyperRouter::VERSION
spec.add_dependency 'hyper-state', HyperRouter::VERSION
- spec.add_dependency 'opal-browser', '~> 0.2.0'
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'chromedriver-helper'
spec.add_development_dependency 'hyper-spec', HyperRouter::VERSION
spec.add_development_dependency 'hyper-store', HyperRouter::VERSION
spec.add_development_dependency 'listen'
- spec.add_development_dependency 'mini_racer'
- spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0.0'
+ spec.add_development_dependency 'mini_racer', '< 0.4.0' # something is busted with 0.4.0 and its libv8-node dependency
+ spec.add_development_dependency 'opal-rails'
+ spec.add_development_dependency 'opal-jquery'
spec.add_development_dependency 'pry-rescue'
spec.add_development_dependency 'pry-stack_explorer'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rspec-collection_matchers'
diff --git a/ruby/hyper-router/lib/hyperstack/router/version.rb b/ruby/hyper-router/lib/hyperstack/router/version.rb
index aa74b24fb..b386e5e32 100644
--- a/ruby/hyper-router/lib/hyperstack/router/version.rb
+++ b/ruby/hyper-router/lib/hyperstack/router/version.rb
@@ -1,3 +1,3 @@
module HyperRouter
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
diff --git a/ruby/hyper-router/spec/test_app/app/assets/config/manifest.js b/ruby/hyper-router/spec/test_app/app/assets/config/manifest.js
new file mode 100644
index 000000000..92bfa3059
--- /dev/null
+++ b/ruby/hyper-router/spec/test_app/app/assets/config/manifest.js
@@ -0,0 +1,3 @@
+ //= link_tree ../images
+ //= link_directory ../javascripts .js
+ //= link_directory ../stylesheets .css
\ No newline at end of file
diff --git a/ruby/hyper-spec/Gemfile b/ruby/hyper-spec/Gemfile
index c0e97c691..12fbd76fc 100644
--- a/ruby/hyper-spec/Gemfile
+++ b/ruby/hyper-spec/Gemfile
@@ -4,4 +4,5 @@ gem 'hyper-store', path: '../hyper-store'
gem 'hyper-state', path: '../hyper-state'
gem 'hyperstack-config', path: '../hyperstack-config'
#gem 'unparser', path: '../../../unparser'
+gem 'opal', '1.0.5'
gemspec
diff --git a/ruby/hyper-spec/hyper-spec.gemspec b/ruby/hyper-spec/hyper-spec.gemspec
index 0b1d645f5..2e11da315 100644
--- a/ruby/hyper-spec/hyper-spec.gemspec
+++ b/ruby/hyper-spec/hyper-spec.gemspec
@@ -12,7 +12,8 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
spec.description = 'A Hyperstack application consists of isomorphic React Components, '\
'Active Record Models, Stores, Operations and Policiespec. '\
'Test them all from Rspec, regardless if the code runs on the client or server.'
- spec.homepage = 'http://hyperstack.org'
+ spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(gemfiles|spec)/}) }
spec.bindir = 'exe'
@@ -35,12 +36,11 @@ Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'hyper-component', HyperSpec::VERSION
- spec.add_development_dependency 'mini_racer'
- spec.add_development_dependency 'opal-browser', '~> 0.2.0'
+ spec.add_development_dependency 'mini_racer', '< 0.4.0' # something is busted with 0.4.0 and its libv8-node dependency
spec.add_development_dependency 'opal-rails', '>= 0.9.4'
spec.add_development_dependency 'pry-rescue'
spec.add_development_dependency 'pry-stack_explorer'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'react-rails', '>= 2.3.0', '< 2.5.0'
diff --git a/ruby/hyper-spec/lib/hyper-spec.rb b/ruby/hyper-spec/lib/hyper-spec.rb
index ba89a70e5..f1ab52569 100644
--- a/ruby/hyper-spec/lib/hyper-spec.rb
+++ b/ruby/hyper-spec/lib/hyper-spec.rb
@@ -4,6 +4,8 @@
require 'unparser'
require 'method_source'
require 'filecache'
+require 'webdrivers'
+
require 'capybara/rspec'
require 'hyper-spec/internal/client_execution'
@@ -84,9 +86,11 @@ module Selenium
module WebDriver
module Chrome
module Bridge
- COMMANDS = remove_const(:COMMANDS).dup
- COMMANDS[:get_log] = [:post, 'session/:session_id/log']
- COMMANDS.freeze
+ if const_defined?(:COMMANDS)
+ COMMANDS = remove_const(:COMMANDS).dup
+ COMMANDS[:get_log] = [:post, 'session/:session_id/log']
+ COMMANDS.freeze
+ end
def log(type)
data = execute :get_log, {}, type: type.to_s
@@ -191,19 +195,44 @@ def self.on_server?
Capybara.default_max_wait_time = 10
- Capybara.register_driver :chrome do |app|
- options = {}
- options.merge!(
- w3c: false,
- args: %w[auto-open-devtools-for-tabs]
+ Capybara.register_driver :chrome_undocked do |app|
+ opts = Selenium::WebDriver::Chrome::Options.new(args: %w[auto-open-devtools-for-tabs])
+ opts.add_preference(
+ 'devtools',
+ 'preferences' => {
+ 'currentDockState' => '"undocked"', # Or '"bottom"', '"right"', etc.
+ 'panel-selectedTab' => '"console"'
+ }
)
- options['mobileEmulation'] = { 'deviceName' => ENV['DEVICE'].tr('-', ' ') } if ENV['DEVICE']
- capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
- chromeOptions: options, 'goog:loggingPrefs' => { browser: 'ALL' }
+ caps = Selenium::WebDriver::Remote::Capabilities.chrome
+ caps["goog:loggingPrefs"] = { browser: 'ALL' }
+
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: opts, desired_capabilities: caps)
+ end
+
+ Capybara.register_driver :chrome_docked do |app|
+ opts = Selenium::WebDriver::Chrome::Options.new(args: %w[auto-open-devtools-for-tabs])
+ opts.add_preference(
+ 'devtools',
+ 'preferences' => {
+ 'currentDockState' => '"right"', # Or '"bottom"', '"undocked"', etc.
+ 'panel-selectedTab' => '"console"'
+ }
)
- Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities)
+ caps = Selenium::WebDriver::Remote::Capabilities.chrome
+ caps["goog:loggingPrefs"] = { browser: 'ALL' }
+
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: opts, desired_capabilities: caps)
end
+ Capybara.register_driver :chrome do |app|
+ caps = Selenium::WebDriver::Remote::Capabilities.chrome
+
+ caps["goog:loggingPrefs"] = { browser: 'ALL' } # if ENV['LOG_JS']
+
+ Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: caps)
+ end
+
Capybara.register_driver :firefox do |app|
Capybara::Selenium::Driver.new(app, browser: :firefox)
end
@@ -238,6 +267,8 @@ def self.on_server?
Capybara.javascript_driver =
case ENV['DRIVER']
when 'beheaded' then :firefox_headless
+ when 'chrome_undocked' then :chrome_undocked
+ when 'chrome_docked' then :chrome_docked
when 'chrome' then :chrome
when 'ff' then :selenium_with_firebug
when 'firefox' then :firefox
diff --git a/ruby/hyper-spec/lib/hyper-spec/component_test_helpers working.rbx b/ruby/hyper-spec/lib/hyper-spec/component_test_helpers working.rbx
new file mode 100644
index 000000000..f41fbe740
--- /dev/null
+++ b/ruby/hyper-spec/lib/hyper-spec/component_test_helpers working.rbx
@@ -0,0 +1,365 @@
+# see component_test_helpers_spec.rb for examples
+require 'parser/current'
+require 'unparser'
+require 'hyper-spec/unparser_patch'
+require 'method_source'
+require_relative '../../lib/hyper-spec/time_cop.rb'
+
+Parser::Builders::Default.emit_procarg0 = true
+
+module HyperSpec
+ module ComponentTestHelpers
+ TOP_LEVEL_COMPONENT_PATCH =
+ Opal.compile(File.read(File.expand_path('../../sources/top_level_rails_component.rb', __FILE__)))
+ TIME_COP_CLIENT_PATCH =
+ Opal.compile(File.read(File.expand_path('../../hyper-spec/time_cop.rb', __FILE__))) +
+ "\n#{File.read(File.expand_path('../../sources/lolex.js', __FILE__))}"
+
+ class << self
+ attr_accessor :current_example
+ attr_accessor :description_displayed
+
+ def display_example_description
+ ""
+ end
+ end
+
+ def build_test_url_for(controller)
+ unless controller
+ unless defined?(::HyperstackTestController)
+ Object.const_set('HyperstackTestController', Class.new(::ActionController::Base))
+ end
+
+ controller = ::HyperstackTestController
+ end
+
+ route_root = controller.name.gsub(/Controller$/, '').underscore
+
+ unless controller.method_defined?(:test)
+ controller.class_eval do
+ define_method(:test) do
+ route_root = self.class.name.gsub(/Controller$/, '').underscore
+ test_params = ::Rails.cache.read("/#{route_root}/#{params[:id]}")
+ @component_name = test_params[0]
+ @component_params = test_params[1]
+ render_params = test_params[2]
+ render_on = render_params.delete(:render_on) || :client_only
+ _mock_time = render_params.delete(:mock_time)
+ style_sheet = render_params.delete(:style_sheet)
+ javascript = render_params.delete(:javascript)
+ code = render_params.delete(:code)
+
+ page = '<%= react_component @component_name, @component_params, '\
+ "{ prerender: #{render_on != :client_only} } %>"
+ unless render_on == :server_only
+ page = "\n#{page}"
+ page = "\n#{page}" if code
+ end
+
+ if render_on != :server_only || Lolex.initialized?
+ page = "\n#{page}"
+ end
+
+ if (render_on != :server_only && !render_params[:layout]) || javascript
+ page = "<%= javascript_include_tag '#{javascript || 'application'}' %>\n#{page}"
+ end
+
+ if !render_params[:layout] || style_sheet
+ page = "<%= stylesheet_link_tag '#{style_sheet || 'application'}' %>\n#{page}"
+ end
+ page = "\n#{page}"
+
+ title = view_context.escape_javascript(ComponentTestHelpers.current_example.description)
+ title = "#{title}...continued." if ComponentTestHelpers.description_displayed
+
+ page = "\n#{page}"
+
+ ComponentTestHelpers.description_displayed = true
+ render_params[:inline] = page
+ render render_params
+ end
+ end
+
+ begin
+ routes = ::Rails.application.routes
+ routes.disable_clear_and_finalize = true
+ routes.clear!
+ routes.draw do
+ get "/#{route_root}/:id", to: "#{route_root}#test"
+ end
+ ::Rails.application.routes_reloader.paths.each { |path| load(path) }
+ routes.finalize!
+ ActiveSupport.on_load(:action_controller) { routes.finalize! }
+ ensure
+ routes.disable_clear_and_finalize = false
+ end
+ end
+
+ "/#{route_root}/#{@test_id = (@test_id || 0) + 1}"
+ end
+
+ def isomorphic(&block)
+ yield
+ on_client(&block)
+ end
+
+ def evaluate_ruby(str = '', opts = {}, &block)
+ insure_mount
+ if block
+ str = "#{str}\n#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.last}"
+ end
+ js = Opal.compile(str).gsub("// Prepare super implicit arguments\n", "")
+ .delete("\n").gsub('(Opal);', '(Opal)')
+ # workaround for firefox 58 and geckodriver 0.19.1, because firefox is unable to find .$to_json:
+ # JSON.parse(evaluate_script("(function(){var a=Opal.Array.$new(); a[0]=#{js}; return a.$to_json();})();"), opts).first
+ JSON.parse(evaluate_script("[#{js}].$to_json()"), opts).first
+ end
+
+ def expect_evaluate_ruby(str = '', opts = {}, &block)
+ insure_mount
+ expect(evaluate_ruby(add_opal_block(str, block), opts))
+ end
+
+ def add_opal_block(str, block)
+ # big assumption here is that we are going to follow this with a .to
+ # hence .children.first followed by .children.last
+ # probably should do some kind of "search" to make this work nicely
+ return str unless block
+ "#{str}\n"\
+ "#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.first.children.last}"
+ end
+
+ def evaluate_promise(str = '', opts = {}, &block)
+ insure_mount
+ str = "#{str}\n#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.last}" if block
+ str = "#{str}.then { |args| args = [args]; `window.hyper_spec_promise_result = args` }"
+ js = Opal.compile(str).gsub("\n","").gsub("(Opal);","(Opal)")
+ page.evaluate_script("window.hyper_spec_promise_result = false")
+ page.execute_script(js)
+ Timeout.timeout(Capybara.default_max_wait_time) do
+ loop do
+ sleep 0.25
+ break if page.evaluate_script("!!window.hyper_spec_promise_result")
+ end
+ end
+ JSON.parse(page.evaluate_script("window.hyper_spec_promise_result.$to_json()"), opts).first
+ end
+
+ def expect_promise(str = '', opts = {}, &block)
+ insure_mount
+ expect(evaluate_promise(add_opal_block(str, block), opts))
+ end
+
+ def ppr(str)
+ js = Opal.compile(str).delete("\n").gsub('(Opal);', '(Opal)')
+ execute_script("console.log(#{js})")
+ end
+
+ def on_client(&block)
+ @client_code =
+ "#{@client_code}#{Unparser.unparse Parser::CurrentRuby.parse(block.source).children.last}\n"
+ end
+
+ def debugger
+ `debugger`
+ nil
+ end
+
+ def insure_mount
+ # rescue in case page is not defined...
+ mount unless page.instance_variable_get('@hyper_spec_mounted')
+ end
+
+ def client_option(opts = {})
+ @client_options ||= {}
+ @client_options.merge! opts
+ end
+
+ alias client_options client_option
+
+ def mount(component_name = nil, params = nil, opts = {}, &block)
+ unless params
+ params = opts
+ opts = {}
+ end
+
+ opts = client_options opts
+ test_url = build_test_url_for(opts.delete(:controller))
+
+ if block || @client_code || component_name.nil?
+ block_with_helpers = <<-code
+ module ComponentHelpers
+ def self.js_eval(s)
+ `eval(s)`
+ end
+ def self.dasherize(s)
+ res = %x{
+ s.replace(/[-_\\s]+/g, '-')
+ .replace(/([A-Z\\d]+)([A-Z][a-z])/g, '$1-$2')
+ .replace(/([a-z\\d])([A-Z])/g, '$1-$2')
+ .toLowerCase()
+ }
+ res
+ end
+ def self.add_class(class_name, styles={})
+ style = styles.collect { |attr, value| "\#{dasherize(attr)}:\#{value}" }.join("; ")
+ cs = class_name.to_s
+ %x{
+ var style_el = document.createElement("style");
+ var css = "." + cs + " { " + style + " }";
+ style_el.type = "text/css";
+ if (style_el.styleSheet){
+ style_el.styleSheet.cssText = css;
+ } else {
+ style_el.appendChild(document.createTextNode(css));
+ }
+ document.head.appendChild(style_el);
+ }
+ end
+ end
+ class Hyperstack::Internal::Component::TestDummy
+ include Hyperstack::Component
+ render {}
+ end
+ #{@client_code}
+ #{Unparser.unparse(Parser::CurrentRuby.parse(block.source).children.last) if block}
+ code
+ opts[:code] = Opal.compile(block_with_helpers)
+ end
+
+ component_name ||= 'Hyperstack::Internal::Component::TestDummy'
+ ::Rails.cache.write(test_url, [component_name, params, opts])
+ test_code_key = "hyper_spec_prerender_test_code.js"
+ @@original_server_render_files ||= ::Rails.configuration.react.server_renderer_options[:files]
+ if opts[:render_on] == :both || opts[:render_on] == :server_only
+ unless opts[:code].blank?
+ ::Rails.cache.write(test_code_key, opts[:code])
+ ::Rails.configuration.react.server_renderer_options[:files] = @@original_server_render_files + [test_code_key]
+ ::React::ServerRendering.reset_pool # make sure contexts are reloaded so they dont use code from cache, as the rails filewatcher doesnt look for cache changes
+ else
+ ::Rails.cache.delete(test_code_key)
+ ::Rails.configuration.react.server_renderer_options[:files] = @@original_server_render_files
+ ::React::ServerRendering.reset_pool # make sure contexts are reloaded so they dont use code from cache, as the rails filewatcher doesnt look for cache changes
+ end
+ end
+ visit test_url
+ wait_for_ajax unless opts[:no_wait]
+ page.instance_variable_set('@hyper_spec_mounted', true)
+ Lolex.init(self, client_options[:time_zone], client_options[:clock_resolution])
+ end
+
+ [:callback_history_for, :last_callback_for, :clear_callback_history_for,
+ :event_history_for, :last_event_for, :clear_event_history_for].each do |method|
+ define_method(method) do |event_name|
+ evaluate_ruby("Hyperstack::Internal::Component::TopLevelRailsComponent.#{method}('#{event_name}')")
+ end
+ end
+
+ def run_on_client(&block)
+ script = Opal.compile(Unparser.unparse(Parser::CurrentRuby.parse(block.source).children.last))
+ execute_script(script)
+ end
+
+ def add_class(class_name, style)
+ @client_code = "#{@client_code}ComponentHelpers.add_class('#{class_name}', #{style})\n"
+ end
+
+ def open_in_chrome
+ if false && ['linux', 'freebsd'].include?(`uname`.downcase)
+ `google-chrome http://#{page.server.host}:#{page.server.port}#{page.current_path}`
+ else
+ `open http://#{page.server.host}:#{page.server.port}#{page.current_path}`
+ end
+
+ while true
+ sleep 1.hour
+ end
+ end
+
+ def pause(message = nil)
+ if message
+ puts message
+ page.evaluate_script "console.log('#{message} (type go() to continue)')"
+ end
+
+ page.evaluate_script('window.hyper_spec_waiting_for_go = true')
+ page.evaluate_script('go = function() {window.hyper_spec_waiting_for_go = false}')
+ loop do
+ sleep 0.25
+ break unless page.evaluate_script('window.hyper_spec_waiting_for_go')
+ end
+ end
+
+ def wait_for_size(width, height)
+ start_time = Capybara::Helpers.monotonic_time
+ stable_count_w = 0
+ stable_count_h = 0
+ prev_size = [0, 0]
+ begin
+ sleep 0.05
+ curr_size = Capybara.current_session.current_window.size
+ return if [width, height] == curr_size
+ # some maximum or minimum is reached and size doesnt change anymore
+ stable_count_w += 1 if prev_size[0] == curr_size[0]
+ stable_count_h += 1 if prev_size[1] == curr_size[1]
+ return if stable_count_w > 2 || stable_count_h > 2
+ prev_size = curr_size
+ end while (Capybara::Helpers.monotonic_time - start_time) < Capybara.current_session.config.default_max_wait_time
+ raise Capybara::WindowError, "Window size not stable within #{Capybara.current_session.config.default_max_wait_time} seconds."
+ end
+
+ def size_window(width = nil, height = nil)
+ # return if @window_cannot_be_resized
+ # original_width = evaluate_script('window.innerWidth')
+ # original_height = evaluate_script('window.innerHeight')
+ width, height = [height, width] if width == :portrait
+ width, height = width if width.is_a? Array
+ portrait = true if height == :portrait
+
+ case width
+ when :small
+ width, height = [480, 320]
+ when :mobile
+ width, height = [640, 480]
+ when :tablet
+ width, height = [960, 640]
+ when :large
+ width, height = [1920, 6000]
+ when :default, nil
+ width, height = [1024, 768]
+ end
+
+ width, height = [height, width] if portrait
+
+ unless RSpec.configuration.debugger_width
+ Capybara.current_session.current_window.resize_to(1000, 500)
+ wait_for_size(1000, 500)
+ inner_width = evaluate_script('window.innerWidth')
+ RSpec.configuration.debugger_width = 1000 - inner_width
+ end
+ Capybara.current_session.current_window
+ .resize_to(width + RSpec.configuration.debugger_width, height)
+ wait_for_size(width + RSpec.configuration.debugger_width, height)
+ end
+ end
+
+ RSpec.configure do |config|
+ config.before(:each) do |example|
+ ComponentTestHelpers.current_example = example
+ ComponentTestHelpers.description_displayed = false
+ end
+
+ if defined?(ActiveRecord)
+ config.before(:all) do
+ ActiveRecord::Base.class_eval do
+ def attributes_on_client(page)
+ page.evaluate_ruby("#{self.class.name}.find(#{id}).attributes", symbolize_names: true)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/ruby/hyper-spec/lib/hyper-spec/helpers.rb b/ruby/hyper-spec/lib/hyper-spec/helpers.rb
index c5d05df04..e86104f20 100644
--- a/ruby/hyper-spec/lib/hyper-spec/helpers.rb
+++ b/ruby/hyper-spec/lib/hyper-spec/helpers.rb
@@ -82,7 +82,11 @@ def before_mount(&block)
def isomorphic(&block)
yield
- before_mount(&block)
+ if page.instance_variable_get('@hyper_spec_mounted')
+ internal_evaluate_ruby(&block)
+ else
+ before_mount(&block)
+ end
end
# Allows options to the mount method to be specified globally
diff --git a/ruby/hyper-spec/lib/hyper-spec/version.rb b/ruby/hyper-spec/lib/hyper-spec/version.rb
index 60e2f4f6e..59df37dbd 100644
--- a/ruby/hyper-spec/lib/hyper-spec/version.rb
+++ b/ruby/hyper-spec/lib/hyper-spec/version.rb
@@ -1,3 +1,3 @@
module HyperSpec
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
diff --git a/ruby/hyper-spec/spec/hyper_spec.rb b/ruby/hyper-spec/spec/hyper_spec.rb
index beff868f9..d1e2af1d6 100644
--- a/ruby/hyper-spec/spec/hyper_spec.rb
+++ b/ruby/hyper-spec/spec/hyper_spec.rb
@@ -108,6 +108,20 @@ def factorial(n)
expect(evaluate_ruby('factorial(5)')).to eq(factorial(5))
end
+ it "can load isomorphic code after loading" do
+ on_client do
+ CONSTANT = 1
+ end
+ CONSTANT = 1
+ isomorphic do
+ def factorial(n)
+ n==CONSTANT ? CONSTANT : n * factorial(n-CONSTANT)
+ end
+ nil
+ end
+ expect(evaluate_ruby('factorial(5)')).to eq(factorial(5))
+ end
+
context 'promise helpers' do
# just to demonstrate a few things:
# 1 - You can use methods like mount, isomorphic, on_client in before(:each) blocks
diff --git a/ruby/hyper-spec/spec/spec_helper.rb b/ruby/hyper-spec/spec/spec_helper.rb
index 2ed740a54..deee6f270 100644
--- a/ruby/hyper-spec/spec/spec_helper.rb
+++ b/ruby/hyper-spec/spec/spec_helper.rb
@@ -1,6 +1,5 @@
require 'hyper-spec'
require 'pry'
-require 'opal-browser'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path('../test_app/config/environment', __FILE__)
diff --git a/ruby/hyper-state/hyper-state.gemspec b/ruby/hyper-state/hyper-state.gemspec
index 9b1f0b8d1..1917a787a 100644
--- a/ruby/hyper-state/hyper-state.gemspec
+++ b/ruby/hyper-state/hyper-state.gemspec
@@ -9,7 +9,8 @@ Gem::Specification.new do |spec|
spec.authors = ['Mitch VanDuyn', 'Adam Creekroad', 'Jan Biedermann']
spec.email = ['mitch@catprint.com', 'jan@kursator.com']
spec.summary = 'Flux Stores and more for Hyperloop'
- spec.homepage = 'https://hyperstack.org'
+ spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(gemfiles|spec)/}) }
spec.bindir = 'exe'
@@ -23,12 +24,12 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'hyper-component', Hyperstack::State::VERSION
spec.add_development_dependency 'hyper-spec', Hyperstack::State::VERSION
spec.add_development_dependency 'listen'
- # spec.add_development_dependency 'mini_racer', '~> 0.2.4'
- spec.add_development_dependency 'opal-browser', '~> 0.2.0'
- spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0'
+ # spec.add_development_dependency 'mini_racer', '< 0.4.0' # something is busted with 0.4.0 and its libv8-node dependency, '~> 0.2.4'
+ # spec.add_development_dependency 'opal-browser', '~> 0.2.0'
+ spec.add_development_dependency 'opal-rails'
spec.add_development_dependency 'pry-rescue'
spec.add_development_dependency 'pry-stack_explorer'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'react-rails', '>= 2.4.0', '< 2.5.0'
diff --git a/ruby/hyper-state/lib/hyperstack/state/version.rb b/ruby/hyper-state/lib/hyperstack/state/version.rb
index 014a96712..b16fd1ced 100644
--- a/ruby/hyper-state/lib/hyperstack/state/version.rb
+++ b/ruby/hyper-state/lib/hyperstack/state/version.rb
@@ -1,5 +1,5 @@
module Hyperstack
module State
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
end
diff --git a/ruby/hyper-store/hyper-store.gemspec b/ruby/hyper-store/hyper-store.gemspec
index a0b621cef..7fb885a73 100644
--- a/ruby/hyper-store/hyper-store.gemspec
+++ b/ruby/hyper-store/hyper-store.gemspec
@@ -9,7 +9,8 @@ Gem::Specification.new do |spec|
spec.authors = ['Mitch VanDuyn', 'Adam Creekroad', 'Jan Biedermann']
spec.email = ['mitch@catprint.com', 'jan@kursator.com']
spec.summary = 'Flux Stores and more for Hyperloop'
- spec.homepage = 'https://hyperstack.org'
+ spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = 'MIT'
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(gemfiles|spec)/}) }
spec.bindir = 'exe'
@@ -24,12 +25,12 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'hyper-component', Hyperstack::Legacy::Store::VERSION
spec.add_development_dependency 'hyper-spec', Hyperstack::Legacy::Store::VERSION
spec.add_development_dependency 'listen'
- # spec.add_development_dependency 'mini_racer', '~> 0.2.6'
+ # spec.add_development_dependency 'mini_racer', '< 0.4.0' # something is busted with 0.4.0 and its libv8-node dependency, '~> 0.2.6'
spec.add_development_dependency 'opal-browser', '~> 0.2.0'
- spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0'
+ spec.add_development_dependency 'opal-rails'
spec.add_development_dependency 'pry-rescue'
spec.add_development_dependency 'pry-stack_explorer'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'react-rails', '>= 2.4.0', '< 2.5.0'
diff --git a/ruby/hyper-store/lib/hyperstack/legacy/store/version.rb b/ruby/hyper-store/lib/hyperstack/legacy/store/version.rb
index c5d9f089d..b6ba5bb77 100644
--- a/ruby/hyper-store/lib/hyperstack/legacy/store/version.rb
+++ b/ruby/hyper-store/lib/hyperstack/legacy/store/version.rb
@@ -1,7 +1,7 @@
module Hyperstack
module Legacy
module Store
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
end
end
diff --git a/ruby/hyper-trace/hyper-trace.gemspec b/ruby/hyper-trace/hyper-trace.gemspec
index 34ecd3095..0be02035e 100644
--- a/ruby/hyper-trace/hyper-trace.gemspec
+++ b/ruby/hyper-trace/hyper-trace.gemspec
@@ -10,7 +10,8 @@ Gem::Specification.new do |spec|
spec.email = ["mitch@catprint.com"]
spec.summary = %q{Method tracing and conditional breakpoints for Opal Ruby}
- spec.homepage = "https://github.com/reactrb/hyper-trace"
+ spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = "MIT"
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
diff --git a/ruby/hyper-trace/lib/hyper_trace/version.rb b/ruby/hyper-trace/lib/hyper_trace/version.rb
index f56801774..dff9a4eee 100644
--- a/ruby/hyper-trace/lib/hyper_trace/version.rb
+++ b/ruby/hyper-trace/lib/hyper_trace/version.rb
@@ -1,3 +1,3 @@
module HyperTrace
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
diff --git a/ruby/hyperstack-config/hyperstack-config.gemspec b/ruby/hyperstack-config/hyperstack-config.gemspec
index 3db9ce49c..584a25fd2 100644
--- a/ruby/hyperstack-config/hyperstack-config.gemspec
+++ b/ruby/hyperstack-config/hyperstack-config.gemspec
@@ -10,6 +10,7 @@ Gem::Specification.new do |spec|
spec.email = ['mitch@catprint.com', 'jan@kursator.com']
spec.summary = 'Provides a single point configuration module for hyperstack gems'
spec.homepage = 'http://ruby-hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = 'MIT'
# spec.metadata = {
# "homepage_uri" => 'http://ruby-hyperstack.org',
@@ -22,17 +23,17 @@ Gem::Specification.new do |spec|
spec.add_dependency 'listen', '~> 3.0' # for hot loader
# spec.add_dependency 'mini_racer', '~> 0.2.6'
- spec.add_dependency 'opal', ENV['OPAL_VERSION'] || '>= 0.11.0', '< 2.0'
- spec.add_dependency 'opal-browser', '~> 0.2.0'
+ spec.add_dependency 'opal', ENV['OPAL_VERSION'] || '>= 0.11.0', '< 1.1'
+ spec.add_dependency 'opal-browser' # this is needed everywhere else so its loaded here
spec.add_dependency 'uglifier'
spec.add_dependency 'websocket' # for hot loader
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'chromedriver-helper'
- spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0'
+ spec.add_development_dependency 'opal-rails' #, '>= 0.9.4', '< 2.0'
spec.add_development_dependency 'pry-rescue'
spec.add_development_dependency 'pry-stack_explorer'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rspec', '~> 3.7.0'
diff --git a/ruby/hyperstack-config/lib/hyperstack-config.rb b/ruby/hyperstack-config/lib/hyperstack-config.rb
index a10902fe6..f7bca1555 100644
--- a/ruby/hyperstack-config/lib/hyperstack-config.rb
+++ b/ruby/hyperstack-config/lib/hyperstack-config.rb
@@ -15,9 +15,14 @@ def self.naming_convention
require 'hyperstack/active_support_string_inquirer.rb'
require 'hyperstack_env'
require 'hyperstack/hotloader/stub'
+ require 'promise'
+ # uncommenting these lines breaks prerendering
+ # require 'opal-browser'
else
require 'opal'
+ # because promises and features in opal-browsers are used everywhere we load them here
require 'opal-browser'
+
# We need opal-rails to be loaded for Gem code to be properly included by sprockets.
begin
require 'opal-rails' if defined? Rails
@@ -41,7 +46,13 @@ def self.naming_convention
Hyperstack.define_setting :hotloader_ping, nil
Hyperstack.define_setting :hotloader_ignore_callback_mapping, false
Hyperstack.import 'opal', gem: true
+
+ # because promises and features in opal-browsers are used everywhere we load them here
+ Hyperstack.import 'promise', client_only: true
Hyperstack.import 'browser', client_only: true
+ Hyperstack.import 'browser/delay', client_only: true
+ Hyperstack.import 'browser/interval', client_only: true
+
Hyperstack.import 'hyperstack-config', gem: true
Hyperstack.import 'hyperstack/autoloader'
Hyperstack.import 'hyperstack/autoloader_starter'
diff --git a/ruby/hyperstack-config/lib/hyperstack/config/version.rb b/ruby/hyperstack-config/lib/hyperstack/config/version.rb
index 09c21e7b8..923640f12 100644
--- a/ruby/hyperstack-config/lib/hyperstack/config/version.rb
+++ b/ruby/hyperstack-config/lib/hyperstack/config/version.rb
@@ -1,5 +1,5 @@
module Hyperstack
module Config
- VERSION = '1.0.alpha1.7'
+ VERSION = '1.0.alpha1.8'
end
end
diff --git a/ruby/hyperstack-config/lib/hyperstack/native_wrapper_compatibility.rb b/ruby/hyperstack-config/lib/hyperstack/native_wrapper_compatibility.rb
index fbb775f19..b8dc25507 100644
--- a/ruby/hyperstack-config/lib/hyperstack/native_wrapper_compatibility.rb
+++ b/ruby/hyperstack-config/lib/hyperstack/native_wrapper_compatibility.rb
@@ -1,7 +1,7 @@
# allows hyperstack to include Native::Wrapper even if running Opal 0.11
module Native
module Wrapper
- def self.included(klass)
+ def self.includedx(klass)
if Native.instance_methods.include? :to_n
klass.include Native
else
diff --git a/ruby/hyperstack-config/spec/test_app/app/assets/config/manifest.js b/ruby/hyperstack-config/spec/test_app/app/assets/config/manifest.js
new file mode 100644
index 000000000..6f71952ea
--- /dev/null
+++ b/ruby/hyperstack-config/spec/test_app/app/assets/config/manifest.js
@@ -0,0 +1 @@
+ //= link_directory ../javascripts .js
diff --git a/ruby/rails-hyperstack/.ruby-version b/ruby/rails-hyperstack/.ruby-version
deleted file mode 100644
index 37c2961c2..000000000
--- a/ruby/rails-hyperstack/.ruby-version
+++ /dev/null
@@ -1 +0,0 @@
-2.7.2
diff --git a/ruby/rails-hyperstack/Gemfile b/ruby/rails-hyperstack/Gemfile
index cbc05abe0..bb2b68734 100644
--- a/ruby/rails-hyperstack/Gemfile
+++ b/ruby/rails-hyperstack/Gemfile
@@ -8,4 +8,5 @@ gem 'hyper-router', path: '../hyper-router'
gem 'hyper-spec', path: '../hyper-spec'
gem 'webpacker' # TODO: figure out why these two are necessary!
gem 'turbolinks'
+gem "selenium-webdriver", '3.142.7'
gemspec
diff --git a/ruby/rails-hyperstack/Rakefile b/ruby/rails-hyperstack/Rakefile
index 70271475f..9e31d53fd 100644
--- a/ruby/rails-hyperstack/Rakefile
+++ b/ruby/rails-hyperstack/Rakefile
@@ -21,11 +21,15 @@ namespace :spec do
sh('spring stop')
sh('bundle exec rails g hyperstack:install')
sh('bundle exec rails generate model Sample name:string description:text')
+ sleep 1
+ sh('pwd')
+ sh('ls app/models')
sh('mv app/models/sample.rb app/hyperstack/models/sample.rb')
sh("cat ../server_side_sample.rb >> app/models/sample.rb")
sh('bundle exec rake db:migrate')
sh('RAILS_ENV=test bundle exec rake db:setup')
# sh('bundle exec rails dev:cache') # not tested yet...
+ sh('RAILS_ENV=test bundle exec rails webpacker:compile')
end
end
end
diff --git a/ruby/rails-hyperstack/lib/hyperstack/server_side_auto_require.rb b/ruby/rails-hyperstack/lib/hyperstack/server_side_auto_require.rb
index a3388d127..ee500361c 100644
--- a/ruby/rails-hyperstack/lib/hyperstack/server_side_auto_require.rb
+++ b/ruby/rails-hyperstack/lib/hyperstack/server_side_auto_require.rb
@@ -1,4 +1,17 @@
-Rails.configuration.autoloader = :classic
+# require "hyperstack/server_side_auto_require.rb" in your hyperstack initializer
+# to autoload shadowed server side files that match files
+# in the hyperstack directory
+
+if Rails.configuration.try(:autoloader) == :zeitwerk
+ Rails.autoloaders.each do |loader|
+ loader.on_load do |_cpath, _value, abspath|
+ ActiveSupport::Dependencies.add_server_side_dependency(abspath) do |load_path|
+ loader.send(:log, "Hyperstack loading server side shadowed file: #{load_path}") if loader&.logger
+ require("#{load_path}.rb")
+ end
+ end
+ end
+end
module ActiveSupport
module Dependencies
@@ -11,7 +24,7 @@ class << self
# and add that as a dependency
def require_or_load(file_name, const_path = nil)
- add_server_side_dependency(file_name)
+ add_server_side_dependency(file_name) { |load_path| require_dependency load_path }
original_require_or_load(file_name, const_path)
end
@@ -20,7 +33,7 @@ def require_or_load(file_name, const_path = nil)
# the filename, and if a ruby file exists at that location then
# add it as a dependency
- def add_server_side_dependency(file_name)
+ def add_server_side_dependency(file_name, loader = nil)
path = File.expand_path(file_name.chomp(".rb"))
.split(File::SEPARATOR).reverse
hs_index = path.find_index(HYPERSTACK_DIR)
@@ -32,7 +45,7 @@ def add_server_side_dependency(file_name)
return unless File.exist? "#{load_path}.rb"
- require_dependency load_path
+ yield load_path
end
end
end
diff --git a/ruby/rails-hyperstack/lib/hyperstack/version.rb b/ruby/rails-hyperstack/lib/hyperstack/version.rb
index 72cbb55eb..4c001ab78 100644
--- a/ruby/rails-hyperstack/lib/hyperstack/version.rb
+++ b/ruby/rails-hyperstack/lib/hyperstack/version.rb
@@ -1,3 +1,3 @@
module Hyperstack
- ROUTERVERSION = VERSION = '1.0.alpha1.7'
+ ROUTERVERSION = VERSION = '1.0.alpha1.8'
end
diff --git a/ruby/rails-hyperstack/rails-hyperstack.gemspec b/ruby/rails-hyperstack/rails-hyperstack.gemspec
index 123f59b83..498118adc 100644
--- a/ruby/rails-hyperstack/rails-hyperstack.gemspec
+++ b/ruby/rails-hyperstack/rails-hyperstack.gemspec
@@ -11,6 +11,7 @@ Gem::Specification.new do |spec|
spec.authors = ['Loic Boutet', 'Adam George', 'Mitch VanDuyn', 'Jan Biedermann']
spec.email = ['loic@boutet.com', 'jan@kursator.com']
spec.homepage = 'http://hyperstack.org'
+ spec.metadata = { 'documentation_uri' => 'https://docs.hyperstack.org/' }
spec.license = 'MIT'
# spec.metadata = {
# "homepage_uri" => 'http://hyperstack.org',
@@ -57,9 +58,8 @@ You can control how much of the stack gets installed as well:
spec.add_dependency 'hyper-model', Hyperstack::VERSION
spec.add_dependency 'hyper-router', Hyperstack::ROUTERVERSION
spec.add_dependency 'hyperstack-config', Hyperstack::VERSION
- spec.add_dependency 'opal-rails' #, '~> 2.0'
-
- spec.add_dependency 'opal-browser', '~> 0.2.0'
+ spec.add_dependency 'opal-rails'
+ spec.add_dependency 'opal', ENV['OPAL_VERSION'] || '>= 0.11.0', '< 1.1'
spec.add_dependency 'react-rails', '>= 2.4.0', '< 2.5.0'
# spec.add_dependency 'mini_racer', '~> 0.2.6'
# spec.add_dependency 'libv8', '~> 7.3.492.27.1'
@@ -69,7 +69,7 @@ You can control how much of the stack gets installed as well:
spec.add_development_dependency 'chromedriver-helper'
spec.add_development_dependency 'hyper-spec', Hyperstack::VERSION
spec.add_development_dependency 'pry'
- spec.add_development_dependency 'puma'
+ spec.add_development_dependency 'puma', '<= 5.4.0'
spec.add_development_dependency 'bootsnap'
spec.add_development_dependency 'rspec-rails'
spec.add_development_dependency 'rubocop' #, '~> 0.51.0'