hyper-react 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +27 -0
  3. data/.gitignore +36 -0
  4. data/.rubocop.yml +1159 -0
  5. data/.travis.yml +29 -0
  6. data/Appraisals +20 -0
  7. data/CHANGELOG.md +93 -0
  8. data/Gemfile +6 -0
  9. data/LICENSE +19 -0
  10. data/README.md +121 -0
  11. data/Rakefile +33 -0
  12. data/UPGRADING.md +24 -0
  13. data/component-name-lookup.md +145 -0
  14. data/config.ru +25 -0
  15. data/gemfiles/opal_0.8_react_13.gemfile +13 -0
  16. data/gemfiles/opal_0.8_react_14.gemfile +13 -0
  17. data/gemfiles/opal_0.8_react_15.gemfile +13 -0
  18. data/gemfiles/opal_0.9_react_13.gemfile +13 -0
  19. data/gemfiles/opal_0.9_react_14.gemfile +13 -0
  20. data/gemfiles/opal_0.9_react_15.gemfile +13 -0
  21. data/hyper-react.gemspec +43 -0
  22. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +4 -0
  23. data/lib/generators/reactive_ruby/test_app/templates/assets/javascripts/test_application.rb +2 -0
  24. data/lib/generators/reactive_ruby/test_app/templates/boot.rb.erb +6 -0
  25. data/lib/generators/reactive_ruby/test_app/templates/script/rails +5 -0
  26. data/lib/generators/reactive_ruby/test_app/templates/test_application.rb.erb +13 -0
  27. data/lib/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +11 -0
  28. data/lib/generators/reactive_ruby/test_app/templates/views/components/todo.rb +14 -0
  29. data/lib/generators/reactive_ruby/test_app/templates/views/layouts/test_layout.html.erb +0 -0
  30. data/lib/generators/reactive_ruby/test_app/test_app_generator.rb +109 -0
  31. data/lib/hyper-react.rb +52 -0
  32. data/lib/rails-helpers/top_level_rails_component.rb +54 -0
  33. data/lib/react-sources/react-server.js +2 -0
  34. data/lib/react/api.rb +162 -0
  35. data/lib/react/callbacks.rb +42 -0
  36. data/lib/react/children.rb +30 -0
  37. data/lib/react/component.rb +139 -0
  38. data/lib/react/component/api.rb +50 -0
  39. data/lib/react/component/base.rb +9 -0
  40. data/lib/react/component/class_methods.rb +214 -0
  41. data/lib/react/component/dsl_instance_methods.rb +27 -0
  42. data/lib/react/component/params.rb +6 -0
  43. data/lib/react/component/props_wrapper.rb +83 -0
  44. data/lib/react/component/should_component_update.rb +98 -0
  45. data/lib/react/component/tags.rb +144 -0
  46. data/lib/react/element.rb +168 -0
  47. data/lib/react/event.rb +76 -0
  48. data/lib/react/ext/hash.rb +9 -0
  49. data/lib/react/ext/string.rb +8 -0
  50. data/lib/react/hash.rb +13 -0
  51. data/lib/react/native_library.rb +92 -0
  52. data/lib/react/object.rb +15 -0
  53. data/lib/react/observable.rb +29 -0
  54. data/lib/react/react-source.rb +9 -0
  55. data/lib/react/rendering_context.rb +142 -0
  56. data/lib/react/state.rb +190 -0
  57. data/lib/react/test.rb +16 -0
  58. data/lib/react/test/dsl.rb +17 -0
  59. data/lib/react/test/matchers/render_html_matcher.rb +49 -0
  60. data/lib/react/test/rspec.rb +15 -0
  61. data/lib/react/test/session.rb +46 -0
  62. data/lib/react/top_level.rb +132 -0
  63. data/lib/react/validator.rb +136 -0
  64. data/lib/reactive-ruby/component_loader.rb +49 -0
  65. data/lib/reactive-ruby/isomorphic_helpers.rb +197 -0
  66. data/lib/reactive-ruby/rails.rb +7 -0
  67. data/lib/reactive-ruby/rails/component_mount.rb +46 -0
  68. data/lib/reactive-ruby/rails/controller_helper.rb +15 -0
  69. data/lib/reactive-ruby/rails/railtie.rb +14 -0
  70. data/lib/reactive-ruby/serializers.rb +15 -0
  71. data/lib/reactive-ruby/server_rendering/contextual_renderer.rb +42 -0
  72. data/lib/reactive-ruby/version.rb +3 -0
  73. data/lib/reactrb/auto-import.rb +32 -0
  74. data/lib/reactrb/deep-compare.rb +24 -0
  75. data/lib/reactrb/new-event-name-convention.rb +11 -0
  76. data/lib/sources/react-latest.js +21169 -0
  77. data/lib/sources/react-v13.js +21645 -0
  78. data/lib/sources/react-v14.js +20821 -0
  79. data/lib/sources/react-v15.js +21170 -0
  80. data/logo1.png +0 -0
  81. data/logo2.png +0 -0
  82. data/logo3.png +0 -0
  83. data/path_release_steps.md +9 -0
  84. data/spec/controller_helper_spec.rb +34 -0
  85. data/spec/index.html.erb +10 -0
  86. data/spec/react/callbacks_spec.rb +106 -0
  87. data/spec/react/children_spec.rb +76 -0
  88. data/spec/react/component/base_spec.rb +32 -0
  89. data/spec/react/component_spec.rb +872 -0
  90. data/spec/react/dsl_spec.rb +296 -0
  91. data/spec/react/element_spec.rb +136 -0
  92. data/spec/react/event_spec.rb +24 -0
  93. data/spec/react/native_library_spec.rb +344 -0
  94. data/spec/react/observable_spec.rb +7 -0
  95. data/spec/react/opal_jquery_extensions_spec.rb +66 -0
  96. data/spec/react/param_declaration_spec.rb +258 -0
  97. data/spec/react/react_spec.rb +209 -0
  98. data/spec/react/state_spec.rb +55 -0
  99. data/spec/react/test/dsl_spec.rb +43 -0
  100. data/spec/react/test/matchers/render_html_matcher_spec.rb +83 -0
  101. data/spec/react/test/rspec_spec.rb +62 -0
  102. data/spec/react/test/session_spec.rb +100 -0
  103. data/spec/react/test/utils_spec.rb +45 -0
  104. data/spec/react/top_level_component_spec.rb +96 -0
  105. data/spec/react/tutorial/tutorial_spec.rb +36 -0
  106. data/spec/react/validator_spec.rb +124 -0
  107. data/spec/reactive-ruby/component_loader_spec.rb +71 -0
  108. data/spec/reactive-ruby/isomorphic_helpers_spec.rb +155 -0
  109. data/spec/reactive-ruby/rails/asset_pipeline_spec.rb +10 -0
  110. data/spec/reactive-ruby/rails/component_mount_spec.rb +66 -0
  111. data/spec/reactive-ruby/server_rendering/contextual_renderer_spec.rb +35 -0
  112. data/spec/spec_helper.rb +115 -0
  113. data/spec/support/react/spec_helpers.rb +64 -0
  114. data/spec/vendor/es5-shim.min.js +6 -0
  115. data/spec/vendor/jquery-2.2.4.min.js +4 -0
  116. metadata +387 -0
@@ -0,0 +1,29 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1
6
+ - jruby-19mode
7
+ before_script:
8
+ - phantomjs --version
9
+ script:
10
+ - bundle exec rake test_app
11
+ - bundle exec rake
12
+ gemfile:
13
+ - gemfiles/opal_0.8_react_13.gemfile
14
+ - gemfiles/opal_0.8_react_14.gemfile
15
+ - gemfiles/opal_0.8_react_15.gemfile
16
+ - gemfiles/opal_0.9_react_13.gemfile
17
+ - gemfiles/opal_0.9_react_14.gemfile
18
+ - gemfiles/opal_0.9_react_15.gemfile
19
+
20
+ # These two setup seems to run indefinitely long
21
+ # further investigation required.
22
+ matrix:
23
+ exclude:
24
+ - rvm: jruby-19mode
25
+ gemfile: gemfiles/opal_0.9_react_13.gemfile
26
+ - rvm: jruby-19mode
27
+ gemfile: gemfiles/opal_0.9_react_14.gemfile
28
+ - rvm: jruby-19mode
29
+ gemfile: gemfiles/opal_0.9_react_15.gemfile
@@ -0,0 +1,20 @@
1
+ opal_versions = ['0.8', '0.9']
2
+ react_versions_map = {
3
+ '13' => '~> 1.3.3',
4
+ '14' => '~> 1.6.2',
5
+ '15' => '~> 1.8.2'
6
+ }
7
+ opal_rails_versions_map = {
8
+ '0.8' => '~> 0.8.1',
9
+ '0.9' => '~> 0.9.0',
10
+ }
11
+
12
+ opal_versions.each do |opal_v|
13
+ react_versions_map.each do |react_v, react_rails_v|
14
+ appraise "opal-#{opal_v}-react-#{react_v}" do
15
+ gem 'opal', "~> #{opal_v}.0"
16
+ gem 'opal-rails', opal_rails_versions_map[opal_v]
17
+ gem 'react-rails', react_rails_v, require: false
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,93 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file starting with v0.8.6.
4
+ This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
+
6
+ Changes are grouped as follows:
7
+ - **Added** for new features.
8
+ - **Changed** for changes in existing functionality.
9
+ - **Deprecated** for once-stable features to be removed in upcoming releases.
10
+ - **Removed** for deprecated features removed in this release.
11
+ - **Fixed** for any bug fixes.
12
+ - **Security** to invite users to upgrade in case of vulnerabilities.
13
+
14
+ <!--
15
+ Whitespace conventions:
16
+ - 4 spaces before ## titles
17
+ - 2 spaces before ### titles
18
+ - 1 spaces before normal text
19
+ -->
20
+
21
+ ## [0.10.0] - 2016-10-30
22
+
23
+ ### Changed
24
+
25
+ - This gem is now renamed to `hyper-react`, see [UPGRADING](UPGRADING.md) for details.
26
+
27
+ ### Fixed
28
+
29
+ - ReactJS functional stateless component could not be imported from `NativeLibrary`. Note that functional component is only supported in React v14+. (#162)
30
+ - Prerender log got accumulated between reqeusts. (#176)
31
+
32
+ ## [0.9.0] - 2016-10-19
33
+
34
+ ### Added
35
+
36
+ - `react/react-source` is the suggested way to include ReactJS sources now. Simply require `react/react-source` immediately before the `require "reactrb"` in your Opal code will make it work.
37
+
38
+ ### Deprecated
39
+
40
+ - `react-latest` & `react-v1x` is deprecated. Use `react/react-source` instead.
41
+
42
+ ### Removed
43
+
44
+ - `opal-browser` is removed from runtime dependency. (#133) You will have to add `gem 'opal-browser'` to your gemfile (recommended) or remove all references to opal-browser from your manifest files.
45
+
46
+ ### Fixed
47
+
48
+ - `$window#on` in `opal-jquery` is broken. (#166)
49
+ - `Element#render` trigger unnecessary re-mounts when called multiple times. (#170)
50
+ - Gets rid of react warnings about updating state during render (#155)
51
+ - Multiple HAML classes (i.e. div.foo.bar) was not working (regression introduced in 0.8.8)
52
+ - Don't send nil (null) to form components as the value string (#157)
53
+ - Process `params` (props) correctly when using `Element#on` or `Element#render` (#158)
54
+ - Deprecate shallow param compare (#156)
55
+
56
+
57
+ ## [0.8.8] - 2016-07-13
58
+
59
+ ### Added
60
+
61
+ - More helpful error messages on render failures (#152)
62
+ - `Element#on('<my_event_name>')` subscribes to `my_event_name` (#153)
63
+
64
+ ### Changed
65
+
66
+ - `Element#on(:event)` subscribes to `on_event` for reactrb components and `onEvent` for native components. (#153)
67
+
68
+ ### Deprecated
69
+
70
+ - `Element#on(:event)` subscription to `_onEvent` is deprecated. Once you have changed params named `_on...` to `on_...` you can `require 'reactrb/new-event-name-convention.rb'` to avoid spurious react warning messages. (#153)
71
+
72
+
73
+ ### Fixed
74
+
75
+ - The `Element['#container'].render...` method generates a spurious react error (#154)
76
+
77
+
78
+
79
+
80
+ ## [0.8.7] - 2016-07-08
81
+
82
+
83
+ ### Fixed
84
+
85
+ - Opal 0.10.x compatibility
86
+
87
+
88
+ ## [0.8.6] - 2016-06-30
89
+
90
+
91
+ ### Fixed
92
+
93
+ - Method missing within a component was being reported as `incorrect const name` (#151)
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ group :development do
5
+ gem "appraisal"
6
+ end
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2015 Yi-Cheng Chang (http://github.com/zetachang)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,121 @@
1
+ # hyper-react
2
+
3
+ [![Join the chat at https://gitter.im/reactrb/chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/reactrb/chat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
+ [![Build Status](https://travis-ci.org/ruby-hyperloop/reactrb.svg?branch=master)](https://travis-ci.org/reactrb/reactrb)
5
+ [![Code Climate](https://codeclimate.com/github/reactrb/reactrb/badges/gpa.svg)](https://codeclimate.com/github/reactrb/reactrb)
6
+ [![Gem Version](https://badge.fury.io/rb/reactrb.svg)](https://badge.fury.io/rb/reactrb)
7
+
8
+ **hyper-react is an [Opal Ruby](http://opalrb.org) wrapper of
9
+ [React.js library](https://facebook.github.io/react)**.
10
+
11
+ It lets you write reactive UI components, with Ruby's elegance using the tried
12
+ and true React.js engine. :heart:
13
+
14
+ Visit [ruby-hyperloop.io](http://ruby-hyperloop.io) for the full story.
15
+
16
+ ### Important: `react.rb`, `reactive-ruby` and `reactrb` gems are **deprecated**. See [**UPGRADING**](UPGRADING.md) for details.
17
+
18
+ ## Installation
19
+
20
+ Install the gem, or load the js library
21
+
22
+ 1. Add `gem 'hyper-react'` to your **Gemfile**
23
+ 2. Or `gem install hyper-react`
24
+ 3. Or install (or load via cdn) from [reactrb-express.js](http://github.com/ruby-hyperloop/reactrb-express)
25
+
26
+ For gem installation it is highly recommended to read the [getting started](http://ruby-hyperloop.io/get_started/) and [installation](http://ruby-hyperloop.io/installation/) guides at [ruby-hyperloop.io.](http://ruby-hyperloop.io)
27
+
28
+ ## Quick Overview
29
+
30
+ A component is a plain ruby class with a `#render` method defined.
31
+
32
+ ```ruby
33
+ class HelloMessage
34
+ def render
35
+ React.create_element("div") { "Hello World!" }
36
+ end
37
+ end
38
+
39
+ puts React.render_to_static_markup(React.create_element(HelloMessage))
40
+
41
+ # => '<div>Hello World!</div>'
42
+ ```
43
+
44
+ ### React::Component
45
+
46
+ You can simply include `React::Component` to get the power of a complete DSL to generate html markup, event handlers and it also provides a full set of class macros to define states, parameters, and lifecycle callbacks.
47
+
48
+ As events occur, components update their state, which causes them to rerender, and perhaps pass new parameters to lower level components, thus causing them to rerender.
49
+
50
+ ```ruby
51
+ class HelloWorld < React::Component::Base
52
+ param :time, type: Time
53
+ render do
54
+ p do
55
+ span { "Hello, " }
56
+ input(type: :text, placeholder: "Your Name Here")
57
+ span { "! It is #{params.time}"}
58
+ end
59
+ end
60
+ end
61
+
62
+ every(1) do
63
+ Element["#example"].render do
64
+ HelloWorld(time: Time.now)
65
+ end
66
+ end
67
+ ```
68
+
69
+ hyper-react components are *isomorphic* (or *univeral*) meaning they can run on the server as well as the client.
70
+
71
+ hyper-react integrates well with Rails, Sinatra, and simple static sites, and can be added to existing web pages very easily.
72
+
73
+ Under the hood the actual work is effeciently done by the [React.js](https://facebook.github.io/react) engine.
74
+
75
+
76
+ ## Why ?
77
+
78
+ + *Single Language:* Use Ruby everywhere, no JS, markup languages, or JSX
79
+ + *Powerful DSL:* Describe HTML and event handlers with a minimum of fuss
80
+ + *Ruby Goodness:* Use all the features of Ruby to create reusable, maintainable UI code
81
+ + *React Simplicity:* Nothing is taken away from the React.js model
82
+ + *Enhanced Features:* Enhanced parameter and state management and other new features
83
+ + *Plays well with Others:* Works with other frameworks, React.js components, Rails, Sinatra and static web pages
84
+
85
+ ## Problems, Questions, Issues
86
+
87
+ + [Stack Overflow](http://stackoverflow.com/questions/tagged/react.rb) tag `react.rb` for specific problems.
88
+ + [Gitter.im](https://gitter.im/reactrb/chat) for general questions, discussion, and interactive help.
89
+ + [Github Issues](https://github.com/reactrb/reactrb/issues) for bugs, feature enhancements, etc.
90
+
91
+
92
+ ## Roadmap
93
+
94
+ Version 0.10.x **will not be** 100% backward compatible with 0.3.0 (`react.rb`) or 0.7.x (`reactive-ruby`).
95
+
96
+ Please let us know either at [Gitter.im](https://gitter.im/reactrb/chat) or [via an issue](https://github.com/reactrb/reactrb/issues) if you have specific concerns with the upgrade from 0.3.0 to 0.10.x.
97
+
98
+ ## Developing
99
+
100
+ `git clone` the project.
101
+
102
+ To play with some live examples, refer to https://github.com/ruby-hyperloop/reactrb-examples.
103
+
104
+ Note that these are very simple examples, for the purpose of showing how to configure the gem in various server environments. For more examples and information see [ruby-hyperloop.io.](http://ruby-hyperloop.io)
105
+
106
+ ## Testing
107
+
108
+ 1. Run `bundle exec rake test_app` to generate a dummy test app.
109
+ 2. `bundle exec appraisal install` to generate separate gemfiles for different environments.
110
+ 2. `bundle exec appraisal opal-0.9-react-15 rake` to run test for opal-0.9 & react-v0.15.
111
+
112
+ ## Contributions
113
+
114
+ This project is still in early stage, so discussion, bug reports and PRs are
115
+ really welcome :wink:.
116
+
117
+
118
+ ## License
119
+
120
+ In short, hyper-react is available under the MIT license. See the LICENSE file for
121
+ more info.
@@ -0,0 +1,33 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+ Bundler::GemHelper.install_tasks
4
+
5
+ # Store the BUNDLE_GEMFILE env, since rake or rspec seems to clean it
6
+ # while invoking task.
7
+ ENV['REAL_BUNDLE_GEMFILE'] = ENV['BUNDLE_GEMFILE']
8
+
9
+ require 'rspec/core/rake_task'
10
+ require 'opal/rspec/rake_task'
11
+
12
+ RSpec::Core::RakeTask.new('ruby:rspec')
13
+
14
+ Opal::RSpec::RakeTask.new('opal:rspec') do |s, task|
15
+ s.append_path 'spec/vendor'
16
+ s.index_path = 'spec/index.html.erb'
17
+ task.timeout = 80000 if task
18
+ end
19
+
20
+ task :test do
21
+ Rake::Task['ruby:rspec'].invoke
22
+ Rake::Task['opal:rspec'].invoke
23
+ end
24
+
25
+ require 'generators/reactive_ruby/test_app/test_app_generator'
26
+ desc "Generates a dummy app for testing"
27
+ task :test_app do
28
+ ReactiveRuby::TestAppGenerator.start
29
+ puts "Setting up test app database..."
30
+ system("bundle exec rake db:drop db:create db:migrate > #{File::NULL}")
31
+ end
32
+
33
+ task default: [ :test ]
@@ -0,0 +1,24 @@
1
+ ## Upgrading to hyper-react from Reactrb
2
+
3
+ Follow these steps to upgrade:
4
+
5
+ 1. Replace `reactrb` with `hyper-react` both in **Gemfile** and any `require`s in your code.
6
+ 2. To include the React.js source, the suggested way is to add `require 'react/react-source'` before `require 'hyper-react'`. This will use the copy of React.js source from `react-rails` gem.
7
+
8
+ ## Upgrading to Reactrb
9
+
10
+ The original gem `react.rb` was superceeded by `reactive-ruby`, which has had over 15,000 downloads. This name has now been superceeded by `reactrb` (see #144 for detailed discussion on why.)
11
+
12
+ Going forward the name `reactrb` will be used consistently as the organization name, the gem name, the domain name, the twitter handle, etc.
13
+
14
+ The first initial version of `reactrb` is 0.8.x.
15
+
16
+ It is very unlikely that there will be any more releases of the `reactive-ruby` gem, so users should upgrade to `reactrb`.
17
+
18
+ There are no syntactic or semantic breaking changes between `reactrb` v 0.8.x and
19
+ previous versions, however the `reactrb` gem does *not* include the react-js source as previous versions did. This allows you to pick the react js source compatible with other gems and react js components you may be using.
20
+
21
+ Follow these steps to upgrade:
22
+
23
+ 1. Replace `reactive-ruby` with `reactrb` both in **Gemfile** and any `require`s in your code.
24
+ 2. To include the React.js source, the suggested way is to add `require 'react/react-source'` before `require 'reactrb'`. This will use the copy of React.js source from `react-rails` gem.
@@ -0,0 +1,145 @@
1
+ #### Notes on how component names are looked up
2
+
3
+ Given:
4
+
5
+ ```ruby
6
+
7
+ class Blat < React::Component::Base
8
+
9
+ render do
10
+ Bar()
11
+ Foo::Bar()
12
+ end
13
+
14
+ end
15
+
16
+ class Bar < React::Component::Base
17
+ end
18
+
19
+ module Foo
20
+
21
+ class Bar < React::Component::Base
22
+
23
+ render do
24
+ Blat()
25
+ Baz()
26
+ end
27
+ end
28
+
29
+ class Baz < React::Component::Base
30
+ end
31
+
32
+ end
33
+ ```
34
+
35
+ The problem is that method lookup is different than constant lookup. We can prove it by running this code:
36
+
37
+ ```ruby
38
+ def try_it(test, &block)
39
+ puts "trying #{test}"
40
+ result = yield
41
+ puts "success#{': '+result.to_s if result}"
42
+ rescue Exception => e
43
+ puts "failed: #{e}"
44
+ ensure
45
+ puts "---------------------------------"
46
+ end
47
+
48
+ module Boom
49
+
50
+ Bar = 12
51
+
52
+ def self.Bar
53
+ puts " Boom::Bar says hi"
54
+ end
55
+
56
+ class Baz
57
+ def doit
58
+ try_it("Bar()") { Bar() }
59
+ try_it("Boom::Bar()") {Boom::Bar()}
60
+ try_it("Bar") { Bar }
61
+ try_it("Boom::Bar") { Boom::Bar }
62
+ end
63
+ end
64
+ end
65
+
66
+
67
+
68
+ Boom::Baz.new.doit
69
+ ```
70
+
71
+ which prints:
72
+
73
+ ```text
74
+ trying Bar()
75
+ failed: Bar: undefined method `Bar' for #<Boom::Baz:0x774>
76
+ ---------------------------------
77
+ trying Boom::Bar()
78
+ Boom::Bar says hi
79
+ success
80
+ ---------------------------------
81
+ trying Bar
82
+ success: 12
83
+ ---------------------------------
84
+ trying Boom::Bar
85
+ success: 12
86
+ ---------------------------------
87
+ ```
88
+
89
+ [try-it](http://opalrb.org/try/?code:def%20try_it(test%2C%20%26block)%0A%20%20puts%20%22trying%20%23%7Btest%7D%22%0A%20%20result%20%3D%20yield%0A%20%20puts%20%22success%23%7B%27%3A%20%27%2Bresult.to_s%20if%20result%7D%22%0Arescue%20Exception%20%3D%3E%20e%0A%20%20puts%20%22failed%3A%20%23%7Be%7D%22%0Aensure%0A%20%20puts%20%22---------------------------------%22%0Aend%0A%0Amodule%20Boom%0A%20%20%0A%20%20Bar%20%3D%2012%0A%20%20%0A%20%20def%20self.Bar%0A%20%20%20%20puts%20%22%20%20%20Boom%3A%3ABar%20says%20hi%22%0A%20%20end%0A%0A%20%20class%20Baz%0A%20%20%20%20def%20doit%0A%20%20%20%20%20%20try_it(%22Bar()%22)%20%7B%20Bar()%20%7D%0A%20%20%20%20%20%20try_it(%22Boom%3A%3ABar()%22)%20%7BBoom%3A%3ABar()%7D%0A%20%20%20%20%20%20try_it(%22Bar%22)%20%7B%20Bar%20%7D%0A%20%20%20%20%20%20try_it(%22Boom%3A%3ABar%22)%20%7B%20Boom%3A%3ABar%20%7D%0A%20%20%20%20end%0A%20%20end%0Aend%0A%20%20%0A%0A%0ABoom%3A%3ABaz.new.doit)
90
+
91
+
92
+ What we need to do is:
93
+
94
+ 1. when defining a component class `Foo`, also define in the same scope that Foo is being defined a method `self.Foo` that will accept Foo's params and child block, and render it.
95
+
96
+ 2. As long as a name is qualified with at least one scope (i.e. `ModName::Foo()`) everything will work out, but if we say just `Foo()` then the only way I believe out of this is to handle it via method_missing, and let method_missing do a const_get on the method_name (which will return the class) and then render that component.
97
+
98
+ #### details
99
+
100
+ To define `self.Foo` in the same scope level as the class `Foo`, we need code like this:
101
+
102
+ ```ruby
103
+ def register_component_dsl_method(component)
104
+ split_name = component.name && component.name.split('::')
105
+ return unless split_name && split_name.length > 2
106
+ component_name = split_name.last
107
+ parent = split_name.inject([Module]) { |nesting, next_const| nesting + [nesting.last.const_get(next_const)] }[-2]
108
+ class << parent
109
+ define_method component_name do |*args, &block|
110
+ React::RenderingContext.render(name, *args, &block)
111
+ end
112
+ define_method "#{component_name}_as_node" do |*args, &block|
113
+ React::Component.deprecation_warning("..._as_node is deprecated. Render component and then use the .node method instead")
114
+ send(component_name, *args, &block).node
115
+ end
116
+ end
117
+ end
118
+
119
+ module React
120
+ module Component
121
+ def self.included(base)
122
+ ...
123
+ register_component_dsl_method(base.name)
124
+ end
125
+ end
126
+ end
127
+ ```
128
+
129
+ The component's method_missing function will look like this:
130
+
131
+ ```ruby
132
+ def method_missing(name, *args, &block)
133
+ if name =~ /_as_node$/
134
+ React::Component.deprecation_warning("..._as_node is deprecated. Render component and then use the .node method instead")
135
+ method_missing(name.gsub(/_as_node$/,""), *args, &block).node
136
+ else
137
+ component = const_get name if defined? name
138
+ React::RenderingContext.render(nil, component, *args, &block)
139
+ end
140
+ end
141
+ ```
142
+
143
+ ### other related issues
144
+
145
+ The Kernel#p method conflicts with the <p> tag. However the p method can be invoked on any object so we are going to go ahead and use it, and deprecate the para method.