hyper-model 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +42 -0
  3. data/CODE_OF_CONDUCT.md +49 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +358 -0
  6. data/LICENSE +21 -0
  7. data/README.md +2 -0
  8. data/Rakefile +2 -0
  9. data/examples/chat-app/.gitignore +21 -0
  10. data/examples/chat-app/Gemfile +62 -0
  11. data/examples/chat-app/Gemfile.lock +309 -0
  12. data/examples/chat-app/README.md +3 -0
  13. data/examples/chat-app/Rakefile +6 -0
  14. data/examples/chat-app/app/assets/config/manifest.js +3 -0
  15. data/examples/chat-app/app/assets/images/.keep +0 -0
  16. data/examples/chat-app/app/assets/javascripts/application.js +3 -0
  17. data/examples/chat-app/app/assets/stylesheets/application.scss +33 -0
  18. data/examples/chat-app/app/controllers/application_controller.rb +3 -0
  19. data/examples/chat-app/app/controllers/home_controller.rb +5 -0
  20. data/examples/chat-app/app/hyperloop/components/app.rb +12 -0
  21. data/examples/chat-app/app/hyperloop/components/formatted_div.rb +15 -0
  22. data/examples/chat-app/app/hyperloop/components/input_box.rb +26 -0
  23. data/examples/chat-app/app/hyperloop/components/message.rb +29 -0
  24. data/examples/chat-app/app/hyperloop/components/messages.rb +8 -0
  25. data/examples/chat-app/app/hyperloop/components/nav.rb +30 -0
  26. data/examples/chat-app/app/hyperloop/models/application_record.rb +3 -0
  27. data/examples/chat-app/app/hyperloop/models/message.rb +6 -0
  28. data/examples/chat-app/app/hyperloop/operations/operations.rb +13 -0
  29. data/examples/chat-app/app/hyperloop/stores/message_store.rb +17 -0
  30. data/examples/chat-app/app/policies/application_policy.rb +9 -0
  31. data/examples/chat-app/app/views/layouts/application.html.erb +12 -0
  32. data/examples/chat-app/bin/bundle +3 -0
  33. data/examples/chat-app/bin/rails +9 -0
  34. data/examples/chat-app/bin/rake +9 -0
  35. data/examples/chat-app/bin/setup +34 -0
  36. data/examples/chat-app/bin/spring +17 -0
  37. data/examples/chat-app/bin/update +29 -0
  38. data/examples/chat-app/config.ru +5 -0
  39. data/examples/chat-app/config/application.rb +12 -0
  40. data/examples/chat-app/config/boot.rb +3 -0
  41. data/examples/chat-app/config/cable.yml +9 -0
  42. data/examples/chat-app/config/database.yml +25 -0
  43. data/examples/chat-app/config/environment.rb +5 -0
  44. data/examples/chat-app/config/environments/development.rb +56 -0
  45. data/examples/chat-app/config/environments/production.rb +86 -0
  46. data/examples/chat-app/config/environments/test.rb +42 -0
  47. data/examples/chat-app/config/initializers/application_controller_renderer.rb +6 -0
  48. data/examples/chat-app/config/initializers/assets.rb +11 -0
  49. data/examples/chat-app/config/initializers/backtrace_silencers.rb +7 -0
  50. data/examples/chat-app/config/initializers/cookies_serializer.rb +5 -0
  51. data/examples/chat-app/config/initializers/filter_parameter_logging.rb +4 -0
  52. data/examples/chat-app/config/initializers/hyperloop.rb +6 -0
  53. data/examples/chat-app/config/initializers/inflections.rb +16 -0
  54. data/examples/chat-app/config/initializers/mime_types.rb +4 -0
  55. data/examples/chat-app/config/initializers/new_framework_defaults.rb +24 -0
  56. data/examples/chat-app/config/initializers/session_store.rb +3 -0
  57. data/examples/chat-app/config/initializers/wrap_parameters.rb +14 -0
  58. data/examples/chat-app/config/locales/en.yml +23 -0
  59. data/examples/chat-app/config/puma.rb +47 -0
  60. data/examples/chat-app/config/routes.rb +5 -0
  61. data/examples/chat-app/config/secrets.yml +22 -0
  62. data/examples/chat-app/config/spring.rb +6 -0
  63. data/examples/chat-app/db/migrate/20170319194429_create_message.rb +9 -0
  64. data/examples/chat-app/db/schema.rb +48 -0
  65. data/examples/chat-app/db/seeds.rb +7 -0
  66. data/examples/chat-app/lib/assets/.keep +0 -0
  67. data/examples/chat-app/lib/tasks/.keep +0 -0
  68. data/examples/chat-app/log/.keep +0 -0
  69. data/examples/chat-app/public/404.html +67 -0
  70. data/examples/chat-app/public/422.html +67 -0
  71. data/examples/chat-app/public/500.html +66 -0
  72. data/examples/chat-app/public/apple-touch-icon-precomposed.png +0 -0
  73. data/examples/chat-app/public/apple-touch-icon.png +0 -0
  74. data/examples/chat-app/public/favicon.ico +0 -0
  75. data/examples/chat-app/public/robots.txt +5 -0
  76. data/examples/chat-app/test/controllers/.keep +0 -0
  77. data/examples/chat-app/test/fixtures/.keep +0 -0
  78. data/examples/chat-app/test/fixtures/files/.keep +0 -0
  79. data/examples/chat-app/test/helpers/.keep +0 -0
  80. data/examples/chat-app/test/integration/.keep +0 -0
  81. data/examples/chat-app/test/mailers/.keep +0 -0
  82. data/examples/chat-app/test/models/.keep +0 -0
  83. data/examples/chat-app/test/test_helper.rb +10 -0
  84. data/examples/chat-app/tmp/.keep +0 -0
  85. data/examples/chat-app/vendor/assets/javascripts/.keep +0 -0
  86. data/examples/chat-app/vendor/assets/stylesheets/.keep +0 -0
  87. data/hyper-model.gemspec +43 -0
  88. data/lib/hyper-model.rb +14 -0
  89. data/lib/hyperloop/model/load.rb +7 -0
  90. data/lib/hyperloop/model/version.rb +5 -0
  91. metadata +385 -0
@@ -0,0 +1,33 @@
1
+ @import "bootstrap-sprockets";
2
+ @import "bootstrap";
3
+
4
+ body {
5
+ padding-top: 50px;
6
+ padding-bottom: 60px;
7
+ }
8
+ div.alternating:nth-of-type(odd) {
9
+ background-color: #ddd;
10
+ }
11
+ div.alternating:nth-of-type(even) {
12
+ background-color: #ccc;
13
+ }
14
+ .input-box {
15
+ padding: 10px;
16
+ }
17
+ .white {
18
+ color: white;
19
+ }
20
+ .message {
21
+ padding-top: 10px;
22
+ }
23
+ textarea {
24
+ width: 100%;;
25
+ }
26
+ div.reactrb-icon {
27
+ float: left;
28
+ width: 50px;
29
+ height: 50px;
30
+ margin-right: 8px;
31
+ background-size: contain;
32
+ background-image: url("http://ruby-hyperloop.io/images/hyperloop_white.svg");
33
+ }
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery with: :exception
3
+ end
@@ -0,0 +1,5 @@
1
+ class HomeController < ApplicationController
2
+ def app
3
+ render_component
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ # The main app
2
+ class App < Hyperloop::Component
3
+ def render
4
+ DIV do
5
+ Nav()
6
+ if MessageStore.online?
7
+ Messages()
8
+ InputBox()
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ # formats a markdown string using 'marked'
2
+ class FormattedDiv < Hyperloop::Component
3
+ param :markdown, type: String
4
+ collect_other_params_as :attributes
5
+
6
+ render do
7
+ # send other attributes (such as css class) on to the outer div
8
+ DIV(params.attributes) do
9
+ DIV(
10
+ dangerously_set_inner_HTML:
11
+ { __html: `marked(#{params.markdown}, {sanitize: true })` }
12
+ )
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ # input box for entering mark down string
2
+ class InputBox < Hyperloop::Component
3
+
4
+ state composition: ''
5
+
6
+ render(DIV, class: 'row form-group input-box navbar navbar-inverse navbar-fixed-bottom') do
7
+ DIV(class: 'col-sm-1 white') { 'Say: ' }
8
+ TEXTAREA(class: 'col-sm-5', rows: rows, value: state.composition)
9
+ .on(:key_down) do |e|
10
+ next unless send_key?(e)
11
+ Operations::Send message: mutate.composition(''), user_name: MessageStore.user_name
12
+ end
13
+ .on(:change) do |e|
14
+ mutate.composition e.target.value
15
+ end
16
+ FormattedDiv class: 'col-sm-5 white', markdown: state.composition
17
+ end
18
+
19
+ def rows
20
+ [state.composition.count("\n") + 1, 20].min
21
+ end
22
+
23
+ def send_key?(e)
24
+ (e.char_code == 13 || e.key_code == 13) && (e.meta_key || e.ctrl_key)
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ require 'models/message'
2
+ # display a single message
3
+ class DisplayMessage < Hyperloop::Component
4
+ param :message, type: Message
5
+
6
+ after_mount :scroll_to_bottom
7
+ after_update :scroll_to_bottom
8
+
9
+ render(DIV, class: 'row alternating message') do
10
+ DIV(class: 'col-sm-2') { params.message[:from] }
11
+ FormattedDiv class: 'col-sm-8', markdown: params.message[:message]
12
+ DIV(class: 'col-sm-2') { formatted_time }
13
+ end
14
+
15
+ def scroll_to_bottom
16
+ Element['html, body'].animate({ scrollTop: Element[Document].height }, :slow)
17
+ end
18
+
19
+ def formatted_time
20
+ time = params.message[:time]
21
+ if Time.now < time + 1.day
22
+ time.strftime '%I:%M %p'
23
+ elsif Time.now < time + 7.days
24
+ time.strftime '%A'
25
+ else
26
+ time.strftime '%D %I:%M %p'
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,8 @@
1
+ # display all messages
2
+ class Messages < Hyperloop::Component
3
+ render(DIV, class: 'container') do
4
+ MessageStore.all.each do |message|
5
+ DisplayMessage message: message
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ class Nav < Hyperloop::Component
2
+
3
+ before_mount do
4
+ mutate.user_name_input ''
5
+ end
6
+
7
+ render do
8
+ div.navbar.navbar_inverse.navbar_fixed_top do
9
+ div.container do
10
+ div.collapse.navbar_collapse(id: 'navbar') do
11
+ form.navbar_form.navbar_left(role: :search) do
12
+ div.form_group do
13
+ input.form_control(type: :text, value: state.user_name_input, placeholder: "Enter Your Handle"
14
+ ).on(:change) do |e|
15
+ mutate.user_name_input e.target.value
16
+ end
17
+ button.btn.btn_default(type: :button) { "login!" }.on(:click) do
18
+ Operations::Join(user_name: state.user_name_input)
19
+ end if valid_new_input?
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ def valid_new_input?
28
+ state.user_name_input.present? && state.user_name_input != MessageStore.user_name
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationRecord < ActiveRecord::Base
2
+ self.abstract_class = true
3
+ end
@@ -0,0 +1,6 @@
1
+ require 'models/application_record'
2
+ class Message < ApplicationRecord
3
+ def time
4
+ created_at
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ module Operations
2
+ # add a message
3
+ class Send < Hyperloop::Operation
4
+ param :message
5
+ param :user_name
6
+
7
+ step { Message.create(message: params.message, from: params.user_name) }
8
+ end
9
+ # register user
10
+ class Join < Hyperloop::Operation
11
+ param :user_name
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ # Store for Messages and the current User Name
2
+ class MessageStore < Hyperloop::Store
3
+ state :user_name, scope: :class, reader: true
4
+
5
+ def self.online?
6
+ state.user_name
7
+ end
8
+
9
+ def self.all
10
+ Message.all
11
+ end
12
+
13
+ receives Operations::Join do |params|
14
+ puts "receiving Operations::Join(#{params})"
15
+ mutate.user_name params.user_name
16
+ end
17
+ end
@@ -0,0 +1,9 @@
1
+ # app/policies/application_policy
2
+ class Hyperloop::ApplicationPolicy
3
+ # Allow any session to connect:
4
+ always_allow_connection
5
+ # Send all attributes from all public models
6
+ regulate_all_broadcasts { |policy| policy.send_all }
7
+ # Allow all changes to public models
8
+ allow_change(to: :all, on: [:create, :update, :destroy]) { true }
9
+ end if Rails.env.development?
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>ChatApp</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
7
+ <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
8
+ </head>
9
+ <body>
10
+ <%= yield %>
11
+ </body>
12
+ </html>
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ load File.expand_path('../spring', __FILE__)
4
+ rescue LoadError => e
5
+ raise unless e.message.include?('spring')
6
+ end
7
+ APP_PATH = File.expand_path('../config/application', __dir__)
8
+ require_relative '../config/boot'
9
+ require 'rails/commands'
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ load File.expand_path('../spring', __FILE__)
4
+ rescue LoadError => e
5
+ raise unless e.message.include?('spring')
6
+ end
7
+ require_relative '../config/boot'
8
+ require 'rake'
9
+ Rake.application.run
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+ require 'fileutils'
4
+ include FileUtils
5
+
6
+ # path to your application root.
7
+ APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
8
+
9
+ def system!(*args)
10
+ system(*args) || abort("\n== Command #{args} failed ==")
11
+ end
12
+
13
+ chdir APP_ROOT do
14
+ # This script is a starting point to setup your application.
15
+ # Add necessary setup steps to this file.
16
+
17
+ puts '== Installing dependencies =='
18
+ system! 'gem install bundler --conservative'
19
+ system('bundle check') || system!('bundle install')
20
+
21
+ # puts "\n== Copying sample files =="
22
+ # unless File.exist?('config/database.yml')
23
+ # cp 'config/database.yml.sample', 'config/database.yml'
24
+ # end
25
+
26
+ puts "\n== Preparing database =="
27
+ system! 'bin/rails db:setup'
28
+
29
+ puts "\n== Removing old logs and tempfiles =="
30
+ system! 'bin/rails log:clear tmp:clear'
31
+
32
+ puts "\n== Restarting application server =="
33
+ system! 'bin/rails restart'
34
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This file loads spring without using Bundler, in order to be fast.
4
+ # It gets overwritten when you run the `spring binstub` command.
5
+
6
+ unless defined?(Spring)
7
+ require 'rubygems'
8
+ require 'bundler'
9
+
10
+ lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read)
11
+ spring = lockfile.specs.detect { |spec| spec.name == "spring" }
12
+ if spring
13
+ Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path
14
+ gem 'spring', spring.version
15
+ require 'spring/binstub'
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+ require 'fileutils'
4
+ include FileUtils
5
+
6
+ # path to your application root.
7
+ APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
8
+
9
+ def system!(*args)
10
+ system(*args) || abort("\n== Command #{args} failed ==")
11
+ end
12
+
13
+ chdir APP_ROOT do
14
+ # This script is a way to update your development environment automatically.
15
+ # Add necessary update steps to this file.
16
+
17
+ puts '== Installing dependencies =='
18
+ system! 'gem install bundler --conservative'
19
+ system('bundle check') || system!('bundle install')
20
+
21
+ puts "\n== Updating database =="
22
+ system! 'bin/rails db:migrate'
23
+
24
+ puts "\n== Removing old logs and tempfiles =="
25
+ system! 'bin/rails log:clear tmp:clear'
26
+
27
+ puts "\n== Restarting application server =="
28
+ system! 'bin/rails restart'
29
+ end
@@ -0,0 +1,5 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require_relative 'config/environment'
4
+
5
+ run Rails.application
@@ -0,0 +1,12 @@
1
+ require_relative 'boot'
2
+
3
+ require 'rails/all'
4
+
5
+ # Require the gems listed in Gemfile, including any gems
6
+ # you've limited to :test, :development, or :production.
7
+ Bundler.require(*Rails.groups)
8
+
9
+ module ChatApp
10
+ class Application < Rails::Application
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
2
+
3
+ require 'bundler/setup' # Set up gems listed in the Gemfile.
@@ -0,0 +1,9 @@
1
+ development:
2
+ adapter: async
3
+
4
+ test:
5
+ adapter: async
6
+
7
+ production:
8
+ adapter: redis
9
+ url: redis://localhost:6379/1
@@ -0,0 +1,25 @@
1
+ # SQLite version 3.x
2
+ # gem install sqlite3
3
+ #
4
+ # Ensure the SQLite 3 gem is defined in your Gemfile
5
+ # gem 'sqlite3'
6
+ #
7
+ default: &default
8
+ adapter: sqlite3
9
+ pool: 5
10
+ timeout: 5000
11
+
12
+ development:
13
+ <<: *default
14
+ database: db/development.sqlite3
15
+
16
+ # Warning: The database defined as "test" will be erased and
17
+ # re-generated from your development database when you run "rake".
18
+ # Do not set this db to the same as development or production.
19
+ test:
20
+ <<: *default
21
+ database: db/test.sqlite3
22
+
23
+ production:
24
+ <<: *default
25
+ database: db/production.sqlite3
@@ -0,0 +1,5 @@
1
+ # Load the Rails application.
2
+ require_relative 'application'
3
+
4
+ # Initialize the Rails application.
5
+ Rails.application.initialize!
@@ -0,0 +1,56 @@
1
+ Rails.application.configure do
2
+ config.react.variant = :development
3
+ config.watchable_files.concat Dir["#{config.root}/app/views/**/*.rb"]
4
+ # Settings specified here will take precedence over those in config/application.rb.
5
+
6
+ # In the development environment your application's code is reloaded on
7
+ # every request. This slows down response time but is perfect for development
8
+ # since you don't have to restart the web server when you make code changes.
9
+ config.cache_classes = false
10
+
11
+ # Do not eager load code on boot.
12
+ config.eager_load = false
13
+
14
+ # Show full error reports.
15
+ config.consider_all_requests_local = true
16
+
17
+ # Enable/disable caching. By default caching is disabled.
18
+ if true || Rails.root.join('tmp/caching-dev.txt').exist?
19
+ config.action_controller.perform_caching = true
20
+
21
+ config.cache_store = :memory_store
22
+ config.public_file_server.headers = {
23
+ 'Cache-Control' => 'public, max-age=172800'
24
+ }
25
+ else
26
+ config.action_controller.perform_caching = false
27
+
28
+ config.cache_store = :null_store
29
+ end
30
+
31
+ # Don't care if the mailer can't send.
32
+ config.action_mailer.raise_delivery_errors = false
33
+
34
+ config.action_mailer.perform_caching = false
35
+
36
+ # Print deprecation notices to the Rails logger.
37
+ config.active_support.deprecation = :log
38
+
39
+ # Raise an error on page load if there are pending migrations.
40
+ config.active_record.migration_error = :page_load
41
+
42
+ # Debug mode disables concatenation and preprocessing of assets.
43
+ # This option may cause significant delays in view rendering with a large
44
+ # number of complex assets.
45
+ config.assets.debug = false
46
+
47
+ # Suppress logger output for asset requests.
48
+ config.assets.quiet = true
49
+
50
+ # Raises error for missing translations
51
+ # config.action_view.raise_on_missing_translations = true
52
+
53
+ # Use an evented file watcher to asynchronously detect changes in source code,
54
+ # routes, locales, etc. This feature depends on the listen gem.
55
+ config.file_watcher = ActiveSupport::EventedFileUpdateChecker
56
+ end