hyper-component 1.0.alpha1.3 → 1.0.alpha1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/Gemfile +5 -0
  4. data/hyper-component.gemspec +8 -16
  5. data/lib/hyper-component.rb +8 -1
  6. data/lib/hyperstack/component.rb +46 -10
  7. data/lib/hyperstack/component/children.rb +1 -1
  8. data/lib/hyperstack/component/element.rb +93 -21
  9. data/lib/hyperstack/component/event.rb +1 -1
  10. data/lib/hyperstack/component/free_render.rb +21 -0
  11. data/lib/hyperstack/component/isomorphic_helpers.rb +13 -10
  12. data/lib/hyperstack/component/version.rb +1 -1
  13. data/lib/hyperstack/component/while_loading.rb +1 -1
  14. data/lib/hyperstack/ext/component/array.rb +20 -0
  15. data/lib/hyperstack/ext/component/element.rb +5 -7
  16. data/lib/hyperstack/ext/component/enumerable.rb +18 -0
  17. data/lib/hyperstack/ext/component/kernel.rb +7 -0
  18. data/lib/hyperstack/ext/component/time.rb +5 -0
  19. data/lib/hyperstack/internal/component/class_methods.rb +4 -3
  20. data/lib/hyperstack/internal/component/haml.rb +3 -12
  21. data/lib/hyperstack/internal/component/props_wrapper.rb +13 -11
  22. data/lib/hyperstack/internal/component/rails/component_mount.rb +12 -0
  23. data/lib/hyperstack/internal/component/rails/controller_helper.rb +1 -1
  24. data/lib/hyperstack/internal/component/rails/railtie.rb +3 -2
  25. data/lib/hyperstack/internal/component/rails/server_rendering/contextual_renderer.rb +5 -1
  26. data/lib/hyperstack/internal/component/rails/server_rendering/hyper_asset_container.rb +4 -2
  27. data/lib/hyperstack/internal/component/react_wrapper.rb +77 -60
  28. data/lib/hyperstack/internal/component/rendering_context.rb +80 -44
  29. data/lib/hyperstack/internal/component/rescue_wrapper.rb +1 -1
  30. data/lib/hyperstack/internal/component/tags.rb +12 -3
  31. data/lib/react/react-source.rb +2 -2
  32. metadata +51 -89
  33. data/Gemfile.lock +0 -364
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42dc80deeb92bd2de37632efacae8b8d4a801c530d65937b7535018a2d3bc91a
4
- data.tar.gz: 142a8df3b61e46f55d0d56766cddff7e734fc01b5f7f594ea6a57900bc4e9e4c
3
+ metadata.gz: 13c80256aa3fb40fd4026676823e8c3cb9045c54187b0150fc7819f739763230
4
+ data.tar.gz: 9813a2ea1cd8c7fd228060fcc0386375dbc59f1b7d90ca6f6eeeebd7f90ac574
5
5
  SHA512:
6
- metadata.gz: 5306b0fd124bee54d7873b2b6a0f4d6713fd346e2efa3bf9ba9f0467df1348a919daf07aecedb55983e26f95076f8df67981774c3288d6eda3af346036fea791
7
- data.tar.gz: ea657f7f9aae7884b5602f3be778452f9088bf9a34ca2afef10ce98e10428412a2e53d5dad6abf55a65f7edc2041460b598b5bd12c6422cb608a29423b8d12ee
6
+ metadata.gz: c44b8960612a69f1df270a146ef9bee5ee053aaf1084cf866d7f4593622c8d655afd0d6b089678ac9c15b01054b532f4f89a9a5e3a7cfbb7dab4800b40da7b58
7
+ data.tar.gz: bff7455afd5528f0fec49ab76efc591b5e3297c8e2158f1e20d6bb4b00ed60e0dbea86bf3f8b5baa3f0090c9b196e057619fc1ad82cdd726f1c8c472a382c19b
data/.gitignore CHANGED
@@ -41,3 +41,7 @@ spec/test_app/db
41
41
  # ignore IDE files
42
42
  .idea
43
43
  .vscode
44
+
45
+ # ignore Gemfile.locks https://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/
46
+ /spec/test_app/Gemfile.lock
47
+ /Gemfile.lock
data/Gemfile CHANGED
@@ -4,5 +4,10 @@ gem 'hyper-spec', path: '../hyper-spec'
4
4
  gem 'hyperstack-config', path: '../hyperstack-config'
5
5
  gem 'hyper-store', path: '../hyper-store'
6
6
  gem 'hyper-state', path: '../hyper-state'
7
+ unless ENV['OPAL_VERSION']&.match("0.11")
8
+ gem 'opal-browser', git: 'https://github.com/opal/opal-browser'
9
+ end
10
+ gem 'hyper-trace', path: '../hyper-trace'
11
+
7
12
  #gem 'puma', '~> 3.11.0' # As of adding, version 3.12.0 isn't working so we are locking
8
13
  gemspec
@@ -8,45 +8,37 @@ Gem::Specification.new do |spec|
8
8
 
9
9
  spec.authors = ['David Chang', 'Adam Jahn', 'Mitch VanDuyn', 'Jan Biedermann', 'Adam Creekroad']
10
10
  spec.email = ['mitch@catprint.com']
11
- spec.homepage = 'http://ruby-hyperloop.org'
11
+ spec.homepage = 'http://hyperstack.org'
12
12
  spec.summary = 'Opal Ruby wrapper of React.js library.'
13
13
  spec.license = 'MIT'
14
14
  spec.description = 'Write React UI components in pure Ruby.'
15
- # spec.metadata = {
16
- # "homepage_uri" => 'http://ruby-hyperloop.org',
17
- # "source_code_uri" => 'https://github.com/ruby-hyperloop/hyper-component'
18
- # }
19
-
20
15
  spec.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(gemfiles|spec)/}) }
21
16
  spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
17
  spec.require_paths = ['lib']
23
18
 
24
19
  spec.add_dependency 'hyper-state', Hyperstack::Component::VERSION
25
20
  spec.add_dependency 'hyperstack-config', Hyperstack::Component::VERSION
26
- spec.add_dependency 'libv8', '~> 6.7.0'
27
- spec.add_dependency 'mini_racer', '~> 0.2.4'
28
- spec.add_dependency 'opal', '>= 0.11.0', '< 0.12.0'
29
21
  spec.add_dependency 'opal-activesupport', '~> 0.3.1'
30
22
  spec.add_dependency 'react-rails', '>= 2.4.0', '< 2.5.0'
31
23
 
32
- spec.add_development_dependency 'bundler', ['>= 1.17.3', '< 2.1']
24
+ spec.add_development_dependency 'bundler'
33
25
  spec.add_development_dependency 'chromedriver-helper'
34
26
  spec.add_development_dependency 'hyper-spec', Hyperstack::Component::VERSION
35
27
  spec.add_development_dependency 'jquery-rails'
36
28
  spec.add_development_dependency 'listen'
37
29
  spec.add_development_dependency 'mime-types'
30
+ spec.add_development_dependency 'mini_racer'
38
31
  spec.add_development_dependency 'nokogiri'
39
32
  spec.add_development_dependency 'opal-jquery'
40
- spec.add_development_dependency 'opal-rails', '~> 0.9.4'
41
- spec.add_development_dependency 'opal-rspec'
42
- spec.add_development_dependency 'pry'
33
+ spec.add_development_dependency 'opal-rails', '>= 0.9.4', '< 2.0'
43
34
  spec.add_development_dependency 'pry-rescue'
35
+ spec.add_development_dependency 'pry-stack_explorer'
44
36
  spec.add_development_dependency 'puma'
45
- spec.add_development_dependency 'rails', '>= 4.0.0'
37
+ spec.add_development_dependency 'rails', ENV['RAILS_VERSION'] || '>= 5.0.0', '< 7.0'
46
38
  spec.add_development_dependency 'rails-controller-testing'
47
39
  spec.add_development_dependency 'rake'
48
40
  spec.add_development_dependency 'rspec-rails'
49
- spec.add_development_dependency 'rubocop', '~> 0.51.0'
50
- spec.add_development_dependency 'sqlite3'
41
+ spec.add_development_dependency 'rubocop' #, '~> 0.51.0'
42
+ spec.add_development_dependency 'sqlite3', '~> 1.4.2'
51
43
  spec.add_development_dependency 'timecop', '~> 0.8.1'
52
44
  end
@@ -1,9 +1,9 @@
1
1
  require 'hyperstack/internal/component'
2
2
 
3
- Hyperstack.import 'hyper-state'
4
3
  Hyperstack.js_import 'react/react-source-browser', client_only: true, defines: %w[ReactDOM React]
5
4
  Hyperstack.js_import 'react/react-source-server', server_only: true, defines: 'React'
6
5
  Hyperstack.import 'browser/delay', client_only: true
6
+ Hyperstack.import 'browser/interval', client_only: true
7
7
  Hyperstack.js_import 'react_ujs', defines: 'ReactRailsUJS'
8
8
  Hyperstack.import 'hyper-component' # TODO: confirm this does not break anything. Added while converting hyperloop->hyperstack
9
9
  Hyperstack.import 'hyperstack/component/auto-import' # TODO: confirm we can cancel the import
@@ -12,6 +12,7 @@ if RUBY_ENGINE == 'opal'
12
12
  require 'hyperstack/internal/callbacks'
13
13
  require 'hyperstack/internal/auto_unmount'
14
14
  require 'native'
15
+ require 'json'
15
16
  require 'hyperstack/state/observer'
16
17
  require 'hyperstack/internal/component/validator'
17
18
  require 'hyperstack/component/element'
@@ -22,18 +23,24 @@ if RUBY_ENGINE == 'opal'
22
23
  require 'hyperstack/component/event'
23
24
  require 'hyperstack/internal/component/rendering_context'
24
25
  require 'hyperstack/ext/component/object'
26
+ require 'hyperstack/ext/component/kernel'
25
27
  require 'hyperstack/ext/component/number'
26
28
  require 'hyperstack/ext/component/boolean'
29
+ require 'hyperstack/ext/component/array'
30
+ require 'hyperstack/ext/component/enumerable'
31
+ require 'hyperstack/ext/component/time'
27
32
  require 'hyperstack/component/isomorphic_helpers'
28
33
  require 'hyperstack/component/react_api'
29
34
  require 'hyperstack/internal/component/top_level_rails_component'
30
35
  require 'hyperstack/component/while_loading'
36
+ require 'hyperstack/component/free_render'
31
37
  require 'hyperstack/internal/component/rescue_wrapper'
32
38
  require 'hyperstack/internal/component/while_loading_wrapper'
33
39
 
34
40
  require 'hyperstack/component/version'
35
41
  else
36
42
  require 'opal'
43
+ require 'hyper-state'
37
44
  require 'opal-activesupport'
38
45
  require 'hyperstack/component/version'
39
46
  require 'hyperstack/internal/component/rails'
@@ -1,7 +1,6 @@
1
1
  require 'hyperstack/ext/component/string'
2
2
  require 'hyperstack/ext/component/hash'
3
3
  require 'active_support/core_ext/class/attribute'
4
- require 'hyperstack/internal/auto_unmount'
5
4
  require 'hyperstack/internal/component/rendering_context'
6
5
  require 'hyperstack/internal/component'
7
6
  require 'hyperstack/internal/component/instance_methods'
@@ -19,15 +18,40 @@ module Hyperstack
19
18
  base.include(Hyperstack::Internal::Component::ShouldComponentUpdate)
20
19
  base.class_eval do
21
20
  class_attribute :initial_state
22
- define_callback :before_mount
21
+
22
+ method_args_deprecation_check = lambda do |name, sself, proc, *args|
23
+ if proc.arity.zero?
24
+ args = []
25
+ else
26
+ deprecation_warning "In the future #{name} callbacks will not receive any parameters."
27
+ end
28
+ sself.instance_exec(*args, &proc)
29
+ args
30
+ end
31
+
32
+ define_callback :before_mount, before_call_hook: method_args_deprecation_check
23
33
  define_callback :after_mount
24
- define_callback :before_new_params
25
- define_callback :before_update
34
+ define_callback(
35
+ :before_new_params,
36
+ after_define_hook: lambda do |klass|
37
+ klass.deprecation_warning "`before_new_params` has been deprecated. The base "\
38
+ "method componentWillReceiveProps is deprecated in React without replacement"
39
+ end
40
+ )
41
+ define_callback(:before_update, before_call_hook: method_args_deprecation_check)
26
42
  define_callback :after_update
27
- define_callback :__hyperstack_component_after_render_hook
28
- define_callback :__hyperstack_component_rescue_hook
29
- #define_callback :before_unmount defined already by Async module
30
- define_callback(:after_error) { Hyperstack::Internal::Component::ReactWrapper.add_after_error_hook(base) }
43
+ define_callback(
44
+ :__hyperstack_component_after_render_hook,
45
+ before_call_hook: ->(_, sself, proc, *args) { [*sself.instance_exec(*args, &proc)] }
46
+ )
47
+ define_callback(
48
+ :__hyperstack_component_rescue_hook,
49
+ before_call_hook: ->(_, sself, proc, *args) { sself.instance_exec(*args, &proc) }
50
+ )
51
+ define_callback(
52
+ :after_error,
53
+ after_define_hook: ->(klass) { Hyperstack::Internal::Component::ReactWrapper.add_after_error_hook(klass) }
54
+ )
31
55
  end
32
56
  base.extend(Hyperstack::Internal::Component::ClassMethods)
33
57
  unless `Opal.__hyperstack_component_original_defn`
@@ -165,13 +189,25 @@ module Hyperstack
165
189
  end
166
190
 
167
191
  def __hyperstack_component_run_post_render_hooks(element)
168
- run_callback(:__hyperstack_component_after_render_hook, element) { |*args| args }.first
192
+ run_callback(:__hyperstack_component_after_render_hook, element).first
169
193
  end
170
194
 
195
+ def _run_before_render_callbacks
196
+ # eventually add before_update if @__component_mounted
197
+ # but that will not perfectly match the current React behavior.
198
+ # However that behavior is deprecated, and so once we have
199
+ # given a chance for the code to be updated we can switch this over
200
+ # and switch the deprecation notice to an error.
201
+ component_will_mount unless @__component_mounted
202
+ @__component_mounted = true
203
+ end
204
+
205
+
171
206
  def _render_wrapper
207
+ _run_before_render_callbacks
172
208
  observing(rendering: true) do
173
209
  element = Hyperstack::Internal::Component::RenderingContext.render(nil) do
174
- render || ''
210
+ render || ""
175
211
  end
176
212
  @__hyperstack_component_waiting_on_resources =
177
213
  element.waiting_on_resources if element.respond_to? :waiting_on_resources
@@ -22,7 +22,7 @@ module Hyperstack
22
22
  %x{
23
23
  React.Children.forEach(#{@children}, function(context){
24
24
  #{
25
- element = Element.new(`context`)
25
+ element = Element.new(`context`, :wrap_child)
26
26
  block.call(element)
27
27
  collection << element
28
28
  }
@@ -15,29 +15,89 @@ module Hyperstack
15
15
  # by using method missing
16
16
  #
17
17
  class Element
18
- include Native
19
18
 
20
- alias_native :element_type, :type
21
- alias_native :props, :props
19
+ # $$typeof: Symbol(react.element)
20
+ # key: null
21
+ # props: {}
22
+ # ref: null
23
+ # type: "div"
24
+ # _ _owner: null
22
25
 
23
- attr_reader :type
26
+ attr_reader :type
27
+
28
+ attr_reader :element_type # change this so name does not conflict - change to element type
24
29
  attr_reader :properties
25
30
  attr_reader :block
31
+ attr_reader :to_n
26
32
 
27
33
  attr_accessor :waiting_on_resources
28
34
 
29
- def initialize(native_element, type = nil, properties = {}, block = nil)
30
- @type = type
35
+ def set_native_attributes(native_element)
36
+ @key = `native_element.key`
37
+ @props = `native_element.props`
38
+ @ref = `native_element.ref`
39
+ @type = `native_element.type`
40
+ @_owner = `native_element._owner`
41
+ @_props_as_hash = Hash.new(@props)
42
+ end
43
+
44
+ def props
45
+ @_props_as_hash
46
+ end
47
+
48
+ def convert_string(native_element, element_type, props, block)
49
+ return native_element unless `native_element['$is_a?']`
50
+ return native_element unless native_element.is_a? String
51
+ raise "Internal Error Element.new called with string, but non-nil props or block" if !props.empty? || block
52
+
53
+ if element_type == :wrap_child
54
+ `React.createElement(React.Fragment, null, [native_element])`
55
+ else
56
+ `React.createElement(native_element, null)`
57
+ end
58
+ end
59
+
60
+ def initialize(native_element, element_type = nil, properties = {}, block = nil)
61
+
62
+ native_element = convert_string(native_element, element_type, properties, block)
63
+ @element_type = element_type unless element_type == :wrap_child
31
64
  @properties = (`typeof #{properties} === 'undefined'` ? nil : properties) || {}
32
65
  @block = block
33
- @native = native_element
66
+ `#{self}.$$typeof = native_element.$$typeof`
67
+ @to_n = self
68
+ set_native_attributes(native_element)
69
+ rescue Exception
34
70
  end
35
71
 
36
- # Attach event handlers.
72
+ def children
73
+ `#{@props}.children`
74
+ end
75
+
76
+ def _update_ref(x)
77
+ @_ref = x
78
+ @_child_element._update_ref(x) if @_child_element
79
+ end
80
+
81
+ def ref # this will not conflict with React's on ref attribute okay because its $ref!!!
82
+ return @_ref if @_ref
83
+ raise("The instance of #{self.element_type} has not been mounted yet") if properties[:ref]
84
+ raise("Attempt to get a ref on #{self.element_type} which is a static component.")
85
+ end
86
+
87
+ def dom_node
88
+ `typeof #{ref}.$dom_node == 'function'` ? ref.dom_node : ref
89
+ end
90
+
91
+ # Attach event handlers. skip false, nil and blank event names
37
92
 
38
93
  def on(*event_names, &block)
39
- event_names.each { |event_name| merge_event_prop!(event_name, &block) }
40
- @native = `React.cloneElement(#{@native}, #{@properties.shallow_to_n})`
94
+ any_found = false
95
+ event_names.each do |event_name|
96
+ next unless event_name && event_name.strip != ''
97
+ merge_event_prop!(event_name, &block)
98
+ any_found = true
99
+ end
100
+ set_native_attributes(`React.cloneElement(#{self}, #{@properties.shallow_to_n})`) if any_found
41
101
  self
42
102
  end
43
103
 
@@ -45,14 +105,14 @@ module Hyperstack
45
105
  # Used for elements that are not yet in DOM, i.e. they are provided as children
46
106
  # or they have been explicitly removed from the rendering context using the delete method.
47
107
 
48
- def render(*props, &new_block)
108
+ def render(*props)
49
109
  if props.empty?
50
110
  Hyperstack::Internal::Component::RenderingContext.render(self)
51
111
  else
52
- props = Hyperstack::Internal::Component::ReactWrapper.convert_props(props)
53
- Hyperstack::Internal::Component::RenderingContext.render(
54
- Element.new(`React.cloneElement(#{@native}, #{props.shallow_to_n})`,
55
- type, @properties.merge(props), block)
112
+ props = Hyperstack::Internal::Component::ReactWrapper.convert_props(element_type, @properties, *props)
113
+ @_child_element = Hyperstack::Internal::Component::RenderingContext.render(
114
+ Element.new(`React.cloneElement(#{self}, #{props.shallow_to_n})`,
115
+ element_type, props, block)
56
116
  )
57
117
  end
58
118
  end
@@ -60,11 +120,12 @@ module Hyperstack
60
120
  # Delete (remove) element from rendering context, the element may later be added back in
61
121
  # using the render method.
62
122
 
63
- def delete
123
+ def ~
64
124
  Hyperstack::Internal::Component::RenderingContext.delete(self)
65
125
  end
66
126
  # Deprecated version of delete method
67
- alias as_node delete
127
+ alias as_node ~
128
+ alias delete ~
68
129
 
69
130
  private
70
131
 
@@ -89,26 +150,37 @@ module Hyperstack
89
150
  merge_built_in_event_prop! name, &block
90
151
  elsif event_name == :enter
91
152
  merge_built_in_event_prop!('onKeyDown') { |evt| yield(evt) if evt.key_code == 13 }
92
- elsif @type.instance_variable_get('@native_import')
153
+ elsif element_type.instance_variable_get('@native_import')
93
154
  merge_component_event_prop! name, &block
94
155
  else
95
156
  merge_component_event_prop! "on_#{event_name}", &block
96
157
  end
97
158
  end
98
159
 
99
- def merge_built_in_event_prop!(prop_name)
160
+ def merge_built_in_event_prop!(prop_name, &block)
100
161
  @properties.merge!(
101
162
  prop_name => %x{
102
163
  function(){
103
164
  var react_event = arguments[0];
165
+ if (arguments.length == 0 || !react_event.nativeEvent) {
166
+ return #{yield(*Array(`arguments`))}
167
+ }
104
168
  var all_args;
105
169
  var other_args;
106
170
  if (arguments.length > 1) {
107
171
  all_args = Array.prototype.slice.call(arguments);
108
172
  other_args = all_args.slice(1, arguments.length);
109
- return #{yield(Event.new(`react_event`), *(`other_args`))};
173
+ return #{
174
+ Internal::State::Mapper.ignore_bulk_updates(
175
+ Event.new(`react_event`), *(`other_args`), &block
176
+ )
177
+ };
110
178
  } else {
111
- return #{yield(Event.new(`react_event`))};
179
+ return #{
180
+ Internal::State::Mapper.ignore_bulk_updates(
181
+ Event.new(`react_event`), &block
182
+ )
183
+ };
112
184
  }
113
185
  }
114
186
  }
@@ -1,7 +1,7 @@
1
1
  module Hyperstack
2
2
  module Component
3
3
  class Event
4
- include Native
4
+ include Native::Wrapper
5
5
  alias_native :bubbles, :bubbles
6
6
  alias_native :cancelable, :cancelable
7
7
  alias_native :current_target, :currentTarget
@@ -0,0 +1,21 @@
1
+ module Hyperstack
2
+ module Component
3
+ module FreeRender
4
+ def self.included(base)
5
+ base.instance_eval do
6
+ alias :hyperstack_component_original_meth_missing method_missing
7
+ def method_missing(name, *args, &block)
8
+ if const_defined?(name) &&
9
+ (klass = const_get(name)) &&
10
+ ((klass.is_a?(Class) && klass.method_defined?(:render)) ||
11
+ Hyperstack::Internal::Component::Tags::HTML_TAGS.include?(klass))
12
+ render(klass, *args, &block)
13
+ else
14
+ hyperstack_component_original_meth_missing(name, *args, &block)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -18,16 +18,22 @@ module Hyperstack
18
18
  def self.load_context(unique_id = nil, name = nil)
19
19
  # can be called on the client to force re-initialization for testing purposes
20
20
  if !unique_id || !@context || @context.unique_id != unique_id
21
- if on_opal_server?
22
- `console.history = []` rescue nil
23
- message = "************************ React Prerendering Context Initialized #{name} ***********************"
24
- else
25
- message = "************************ React Browser Context Initialized ****************************"
26
- end
21
+ message =
22
+ if on_opal_server?
23
+ `console.history = []` rescue nil
24
+ "************************ React Prerendering Context Initialized #{name} ***********************"
25
+ else
26
+ '************************ React Browser Context Initialized ****************************'
27
+ end
28
+
27
29
  log(message)
30
+
28
31
  @context = Context.new(unique_id)
29
32
  end
30
- @context
33
+
34
+ # True is returned here because this method is evaluated by MiniRacer,
35
+ # and can cause TypeError: Converting circular structure to JSON to raise
36
+ true
31
37
  end
32
38
  end
33
39
 
@@ -139,7 +145,6 @@ module Hyperstack
139
145
 
140
146
  def send_to_opal(method_name, *args)
141
147
  return unless @ctx
142
- args = [1] if args.length == 0
143
148
  Hyperstack::Internal::Component::Rails::ComponentLoader.new(@ctx).load!
144
149
  method_args = args.collect do |arg|
145
150
  quarg = "#{arg}".tr('"', "'")
@@ -220,8 +225,6 @@ module Hyperstack
220
225
  end
221
226
  end
222
227
  else
223
- require 'json'
224
-
225
228
  def isomorphic_method(name, &block)
226
229
  self.class.send(:define_method, name) do | *args |
227
230
  IsomorphicHelpers::IsomorphicProcCall.new(name, block, self, *args).result