hyper-component 0.99.6 → 1.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -3
  3. data/Gemfile +4 -3
  4. data/Gemfile.lock +51 -36
  5. data/{misc/how-component-name-lookup-works.md → how-component-name-lookup-works.md} +1 -1
  6. data/hyper-component.gemspec +9 -8
  7. data/lib/hyper-component.rb +31 -43
  8. data/lib/hyperstack/component.rb +145 -0
  9. data/lib/hyperstack/component/auto-import.rb +44 -0
  10. data/lib/hyperstack/component/children.rb +40 -0
  11. data/lib/hyperstack/component/element.rb +129 -0
  12. data/lib/hyperstack/component/event.rb +78 -0
  13. data/lib/hyperstack/component/haml.rb +18 -0
  14. data/lib/hyperstack/component/isomorphic_helpers.rb +235 -0
  15. data/lib/hyperstack/component/jquery.rb +2 -0
  16. data/lib/hyperstack/component/native_library.rb +92 -0
  17. data/lib/hyperstack/component/react_api.rb +142 -0
  18. data/lib/hyperstack/component/server.rb +21 -0
  19. data/lib/hyperstack/component/version.rb +5 -0
  20. data/lib/hyperstack/ext/component/boolean.rb +14 -0
  21. data/lib/{react/ext/opal-jquery → hyperstack/ext/component}/element.rb +17 -12
  22. data/lib/{react/ext → hyperstack/ext/component}/hash.rb +0 -0
  23. data/lib/{react/to_key.rb → hyperstack/ext/component/number.rb} +0 -12
  24. data/lib/hyperstack/ext/component/object.rb +32 -0
  25. data/lib/{reactive-ruby → hyperstack/ext/component}/serializers.rb +0 -0
  26. data/lib/{react/ext → hyperstack/ext/component}/string.rb +0 -0
  27. data/lib/hyperstack/internal/component.rb +16 -0
  28. data/lib/hyperstack/internal/component/class_methods.rb +212 -0
  29. data/lib/hyperstack/internal/component/haml.rb +56 -0
  30. data/lib/hyperstack/internal/component/instance_methods.rb +92 -0
  31. data/lib/hyperstack/internal/component/props_wrapper.rb +125 -0
  32. data/lib/hyperstack/internal/component/rails.rb +11 -0
  33. data/lib/hyperstack/internal/component/rails/component_loader.rb +49 -0
  34. data/lib/hyperstack/internal/component/rails/component_mount.rb +52 -0
  35. data/lib/{reactive-ruby → hyperstack/internal/component}/rails/controller_helper.rb +0 -0
  36. data/lib/hyperstack/internal/component/rails/railtie.rb +24 -0
  37. data/lib/hyperstack/internal/component/rails/server_rendering/contextual_renderer.rb +52 -0
  38. data/lib/hyperstack/internal/component/rails/server_rendering/hyper_asset_container.rb +52 -0
  39. data/lib/hyperstack/internal/component/react_wrapper.rb +308 -0
  40. data/lib/hyperstack/internal/component/rendering_context.rb +165 -0
  41. data/lib/hyperstack/internal/component/should_component_update.rb +101 -0
  42. data/lib/hyperstack/internal/component/tags.rb +109 -0
  43. data/lib/hyperstack/internal/component/top_level_rails_component.rb +83 -0
  44. data/lib/hyperstack/internal/component/validator.rb +149 -0
  45. data/lib/react/react-source.rb +2 -2
  46. data/unmounting-objects.md +78 -0
  47. metadata +73 -85
  48. data/DOCS.md +0 -1515
  49. data/LICENSE +0 -19
  50. data/README.md +0 -49
  51. data/lib/hyper-component/jquery.rb +0 -2
  52. data/lib/rails-helpers/top_level_rails_component.rb +0 -79
  53. data/lib/react/api.rb +0 -272
  54. data/lib/react/callbacks.rb +0 -42
  55. data/lib/react/children.rb +0 -38
  56. data/lib/react/component.rb +0 -189
  57. data/lib/react/component/api.rb +0 -70
  58. data/lib/react/component/base.rb +0 -13
  59. data/lib/react/component/class_methods.rb +0 -175
  60. data/lib/react/component/dsl_instance_methods.rb +0 -23
  61. data/lib/react/component/params.rb +0 -6
  62. data/lib/react/component/props_wrapper.rb +0 -90
  63. data/lib/react/component/should_component_update.rb +0 -99
  64. data/lib/react/component/tags.rb +0 -116
  65. data/lib/react/config.rb +0 -5
  66. data/lib/react/element.rb +0 -167
  67. data/lib/react/event.rb +0 -76
  68. data/lib/react/native_library.rb +0 -87
  69. data/lib/react/object.rb +0 -15
  70. data/lib/react/ref_callback.rb +0 -31
  71. data/lib/react/rendering_context.rb +0 -149
  72. data/lib/react/server.rb +0 -19
  73. data/lib/react/state_wrapper.rb +0 -23
  74. data/lib/react/test.rb +0 -16
  75. data/lib/react/test/dsl.rb +0 -17
  76. data/lib/react/test/matchers/render_html_matcher.rb +0 -56
  77. data/lib/react/test/rspec.rb +0 -15
  78. data/lib/react/test/session.rb +0 -37
  79. data/lib/react/test/utils.rb +0 -71
  80. data/lib/react/top_level.rb +0 -110
  81. data/lib/react/top_level_render.rb +0 -30
  82. data/lib/react/validator.rb +0 -132
  83. data/lib/reactive-ruby/component_loader.rb +0 -43
  84. data/lib/reactive-ruby/isomorphic_helpers.rb +0 -233
  85. data/lib/reactive-ruby/rails.rb +0 -8
  86. data/lib/reactive-ruby/rails/component_mount.rb +0 -48
  87. data/lib/reactive-ruby/rails/railtie.rb +0 -20
  88. data/lib/reactive-ruby/server_rendering/contextual_renderer.rb +0 -46
  89. data/lib/reactive-ruby/server_rendering/hyper_asset_container.rb +0 -46
  90. data/lib/reactive-ruby/version.rb +0 -5
  91. data/lib/reactrb/auto-import.rb +0 -27
  92. data/misc/generators/reactive_ruby/test_app/templates/assets/javascripts/components.rb +0 -3
  93. data/misc/generators/reactive_ruby/test_app/templates/assets/javascripts/server_rendering.js +0 -5
  94. data/misc/generators/reactive_ruby/test_app/templates/assets/javascripts/test_application.rb +0 -2
  95. data/misc/generators/reactive_ruby/test_app/templates/boot.rb.erb +0 -6
  96. data/misc/generators/reactive_ruby/test_app/templates/script/rails +0 -5
  97. data/misc/generators/reactive_ruby/test_app/templates/test_application.rb.erb +0 -13
  98. data/misc/generators/reactive_ruby/test_app/templates/views/components/hello_world.rb +0 -11
  99. data/misc/generators/reactive_ruby/test_app/templates/views/components/todo.rb +0 -14
  100. data/misc/generators/reactive_ruby/test_app/templates/views/layouts/test_layout.html.erb +0 -0
  101. data/misc/generators/reactive_ruby/test_app/test_app_generator.rb +0 -121
  102. data/misc/hyperloop-logo-small-pink.png +0 -0
  103. data/misc/logo1.png +0 -0
  104. data/misc/logo2.png +0 -0
  105. data/misc/logo3.png +0 -0
  106. data/path_release_steps.md +0 -9
data/LICENSE DELETED
@@ -1,19 +0,0 @@
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.
data/README.md DELETED
@@ -1,49 +0,0 @@
1
- <div class="githubhyperloopheader">
2
-
3
- <p align="center">
4
-
5
- <a href="http://ruby-hyperloop.org/" alt="Hyperloop" title="Hyperloop">
6
- <img width="350px" src="http://ruby-hyperloop.org/images/hyperloop-github-logo.png">
7
- </a>
8
-
9
- </p>
10
-
11
- <h2 align="center">The Complete Isomorphic Ruby Framework</h2>
12
-
13
- <br>
14
-
15
- <a href="http://ruby-hyperloop.org/" alt="Hyperloop" title="Hyperloop">
16
- <img src="http://ruby-hyperloop.org/images/githubhyperloopbadge.png">
17
- </a>
18
-
19
- <a href="https://gitter.im/ruby-hyperloop/chat" alt="Gitter chat" title="Gitter chat">
20
- <img src="http://ruby-hyperloop.org/images/githubgitterbadge.png">
21
- </a>
22
-
23
- [![Build Status](https://travis-ci.org/ruby-hyperloop/hyper-react.svg?branch=master)](https://travis-ci.org/ruby-hyperloop/hyper-react)
24
- [![Gem Version](https://badge.fury.io/rb/hyper-react.svg)](https://badge.fury.io/rb/hyper-react)
25
-
26
- <p align="center">
27
- <img src="http://ruby-hyperloop.org/images/HyperComponents.png" width="100" alt="Hyper-components">
28
- </p>
29
-
30
- </div>
31
-
32
- ## Hyper-React GEM is part of Hyperloop GEMS family
33
-
34
- Hyper-react GEM comes with the Hyperloop GEM.
35
-
36
- But if you want to install it separately, please install the [Hyper-component GEM](https://github.com/ruby-hyperloop/hyper-component).
37
-
38
- ## Community
39
-
40
- #### Getting Help
41
- Please **do not post** usage questions to GitHub Issues. For these types of questions use our [Gitter chatroom](https://gitter.im/ruby-hyperloop/chat) or [StackOverflow](http://stackoverflow.com/questions/tagged/hyperloop).
42
-
43
- #### Submitting Bugs and Enhancements
44
- [GitHub Issues](https://github.com/ruby-hyperloop/hyperloop/issues) is for suggesting enhancements and reporting bugs. Before submiting a bug make sure you do the following:
45
- * Check out our [contributing guide](https://github.com/ruby-hyperloop/hyperloop/blob/master/CONTRIBUTING.md) for info on our release cycle.
46
-
47
- ## License
48
-
49
- Hyperloop is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -1,2 +0,0 @@
1
- require 'opal-jquery' # remove this line if you don't need jquery'
2
- require 'react/ext/opal-jquery/element'
@@ -1,79 +0,0 @@
1
- module React
2
- class TopLevelRailsComponent
3
- include Hyperloop::Component::Mixin
4
-
5
- def self.search_path
6
- @search_path ||= [Object]
7
- end
8
-
9
- export_component
10
-
11
- param :component_name
12
- param :controller
13
- param :render_params
14
-
15
- backtrace :off
16
-
17
- def render
18
- top_level_render
19
- end
20
-
21
- def top_level_render
22
- paths_searched = []
23
- component = nil
24
- if params.component_name.start_with?('::')
25
- # if absolute path of component is given, look it up and fail if not found
26
- paths_searched << params.component_name
27
- component = begin
28
- Object.const_get(params.component_name)
29
- rescue NameError
30
- nil
31
- end
32
- else
33
- # if relative path is given, look it up like this
34
- # 1) we check each path + controller-name + component-name
35
- # 2) if we can't find it there we check each path + component-name
36
- # if we can't find it we just try const_get
37
- # so (assuming controller name is Home)
38
- # ::Foo::Bar will only resolve to some component named ::Foo::Bar
39
- # but Foo::Bar will check (in this order) ::Home::Foo::Bar, ::Components::Home::Foo::Bar, ::Foo::Bar, ::Components::Foo::Bar
40
- self.class.search_path.each do |scope|
41
- paths_searched << "#{scope.name}::#{params.controller}::#{params.component_name}"
42
- component = begin
43
- scope.const_get(params.controller, false).const_get(params.component_name, false)
44
- rescue NameError
45
- nil
46
- end
47
- break if component != nil
48
- end
49
- unless component
50
- self.class.search_path.each do |scope|
51
- paths_searched << "#{scope.name}::#{params.component_name}"
52
- component = begin
53
- scope.const_get(params.component_name, false)
54
- rescue NameError
55
- nil
56
- end
57
- break if component != nil
58
- end
59
- end
60
- end
61
- return React::RenderingContext.render(component, params.render_params) if component && component.method_defined?(:render)
62
- raise "Could not find component class '#{params.component_name}' for params.controller '#{params.controller}' in any component directory. Tried [#{paths_searched.join(", ")}]"
63
- end
64
- end
65
- end
66
-
67
- class Module
68
- def add_to_react_search_path(replace_search_path = nil)
69
- if replace_search_path
70
- React::TopLevelRailsComponent.search_path = [self]
71
- elsif !React::TopLevelRailsComponent.search_path.include? self
72
- React::TopLevelRailsComponent.search_path << self
73
- end
74
- end
75
- end
76
-
77
- module Components
78
- add_to_react_search_path
79
- end
@@ -1,272 +0,0 @@
1
- require 'react/native_library'
2
-
3
- module React
4
- # Provides the internal mechanisms to interface between reactrb and native components
5
- # the code will attempt to create a js component wrapper on any rb class that has a
6
- # render (or possibly _render_wrapper) method. The mapping between rb and js components
7
- # is kept in the @@component_classes hash.
8
-
9
- # Also provides the mechanism to build react elements
10
-
11
- # TOOO - the code to deal with components should be moved to a module that will be included
12
- # in a class which will then create the JS component for that class. That module will then
13
- # be included in React::Component, but can be used by any class wanting to become a react
14
- # component (but without other DSL characteristics.)
15
- class API
16
- @@component_classes = {}
17
-
18
- def self.import_native_component(opal_class, native_class)
19
- opal_class.instance_variable_set("@native_import", true)
20
- @@component_classes[opal_class] = native_class
21
- end
22
-
23
- def self.eval_native_react_component(name)
24
- component = `eval(name)`
25
- raise "#{name} is not defined" if `#{component} === undefined`
26
- is_component_class = `#{component}.prototype !== undefined` &&
27
- (`!!#{component}.prototype.isReactComponent` ||
28
- `!!#{component}.prototype.render`)
29
- is_functional_component = `typeof #{component} === "function"`
30
- unless is_component_class || is_functional_component
31
- raise 'does not appear to be a native react component'
32
- end
33
- component
34
- end
35
-
36
- def self.native_react_component?(name = nil)
37
- return false unless name
38
- eval_native_react_component(name)
39
- rescue
40
- nil
41
- end
42
-
43
- def self.add_after_error_hook(klass)
44
- add_after_error_hook_to_native(@@component_classes[klass])
45
- end
46
-
47
- def self.add_after_error_hook_to_native(native_comp)
48
- return unless native_comp
49
- %x{
50
- native_comp.prototype.componentDidCatch = function(error, info) {
51
- this.__opalInstanceSyncSetState = false;
52
- this.__opalInstance.$component_did_catch(error, Opal.Hash.$new(info));
53
- }
54
- }
55
- end
56
-
57
- def self.create_native_react_class(type)
58
- raise "Provided class should define `render` method" if !(type.method_defined? :render)
59
- render_fn = (type.method_defined? :_render_wrapper) ? :_render_wrapper : :render
60
- # this was hashing type.to_s, not sure why but .to_s does not work as it Foo::Bar::View.to_s just returns "View"
61
-
62
- @@component_classes[type] ||= begin
63
- comp = %x{
64
- class extends React.Component {
65
- constructor(props) {
66
- super(props);
67
- this.mixins = #{type.respond_to?(:native_mixins) ? type.native_mixins : `[]`};
68
- this.statics = #{type.respond_to?(:static_call_backs) ? type.static_call_backs.to_n : `{}`};
69
- this.state = {};
70
- this.__opalInstanceInitializedState = false;
71
- this.__opalInstanceSyncSetState = true;
72
- this.__opalInstance = #{type.new(`this`)};
73
- this.__opalInstanceInitializedState = true;
74
- this.__opalInstanceSyncSetState = false;
75
- this.__name = #{type.name};
76
- }
77
- static get displayName() {
78
- if (typeof this.__name != "undefined") {
79
- return this.__name;
80
- } else {
81
- return #{type.name};
82
- }
83
- }
84
- static set displayName(name) {
85
- this.__name = name;
86
- }
87
- static get defaultProps() {
88
- return #{type.respond_to?(:default_props) ? type.default_props.to_n : `{}`};
89
- }
90
- static get propTypes() {
91
- return #{type.respond_to?(:prop_types) ? type.prop_types.to_n : `{}`};
92
- }
93
- componentWillMount() {
94
- if (#{type.method_defined? :component_will_mount}) {
95
- this.__opalInstanceSyncSetState = true;
96
- this.__opalInstance.$component_will_mount();
97
- this.__opalInstanceSyncSetState = false;
98
- }
99
- }
100
- componentDidMount() {
101
- this.__opalInstance.is_mounted = true
102
- if (#{type.method_defined? :component_did_mount}) {
103
- this.__opalInstanceSyncSetState = false;
104
- this.__opalInstance.$component_did_mount();
105
- }
106
- }
107
- componentWillReceiveProps(next_props) {
108
- if (#{type.method_defined? :component_will_receive_props}) {
109
- this.__opalInstanceSyncSetState = true;
110
- this.__opalInstance.$component_will_receive_props(Opal.Hash.$new(next_props));
111
- this.__opalInstanceSyncSetState = false;
112
- }
113
- }
114
- shouldComponentUpdate(next_props, next_state) {
115
- if (#{type.method_defined? :should_component_update?}) {
116
- this.__opalInstanceSyncSetState = false;
117
- return this.__opalInstance["$should_component_update?"](Opal.Hash.$new(next_props), Opal.Hash.$new(next_state));
118
- } else { return true; }
119
- }
120
- componentWillUpdate(next_props, next_state) {
121
- if (#{type.method_defined? :component_will_update}) {
122
- this.__opalInstanceSyncSetState = false;
123
- this.__opalInstance.$component_will_update(Opal.Hash.$new(next_props), Opal.Hash.$new(next_state));
124
- }
125
- }
126
- componentDidUpdate(prev_props, prev_state) {
127
- if (#{type.method_defined? :component_did_update}) {
128
- this.__opalInstanceSyncSetState = false;
129
- this.__opalInstance.$component_did_update(Opal.Hash.$new(prev_props), Opal.Hash.$new(prev_state));
130
- }
131
- }
132
- componentWillUnmount() {
133
- if (#{type.method_defined? :component_will_unmount}) {
134
- this.__opalInstanceSyncSetState = false;
135
- this.__opalInstance.$component_will_unmount();
136
- }
137
- this.__opalInstance.is_mounted = false;
138
- }
139
-
140
- render() {
141
- this.__opalInstanceSyncSetState = false;
142
- return this.__opalInstance.$send(render_fn).$to_n();
143
- }
144
- }
145
- }
146
- # check to see if there is an after_error callback. If there is add a
147
- # componentDidCatch handler. Because legacy behavior is to allow any object
148
- # that responds to render to act as a component we have to make sure that
149
- # we have a callbacks_for method. This all becomes much easier once issue
150
- # #270 is resolved.
151
- if type.respond_to?(:callbacks_for) && type.callbacks_for(:after_error) != []
152
- add_after_error_hook_to_native comp
153
- end
154
- comp
155
- end
156
- end
157
-
158
- def self.create_element(type, *args, &block)
159
- params = []
160
-
161
- # Component Spec, Normal DOM, String or Native Component
162
- ncc = @@component_classes[type]
163
- if ncc
164
- params << ncc
165
- elsif type.is_a?(Class)
166
- params << create_native_react_class(type)
167
- elsif block_given? || React::Component::Tags::HTML_TAGS.include?(type)
168
- params << type
169
- elsif type.is_a?(String)
170
- return React::Element.new(type)
171
- else
172
- raise "#{type} not implemented"
173
- end
174
-
175
- # Convert Passed in properties
176
- properties = convert_props(args)
177
- params << properties.shallow_to_n
178
-
179
- # Children Nodes
180
- if block_given?
181
- a = [yield].flatten
182
- %x{
183
- for(var i=0, l=a.length; i<l; i++) {
184
- params.push(a[i].$to_n());
185
- }
186
- }
187
- end
188
- React::Element.new(`React.createElement.apply(null, #{params})`, type, properties, block)
189
- end
190
-
191
- def self.clear_component_class_cache
192
- @@component_classes = {}
193
- end
194
-
195
- def self.convert_props(args)
196
- # merge args together into a single properties hash
197
- properties = {}
198
- args.each do |arg|
199
- if arg.is_a? String
200
- properties[arg] = true
201
- elsif arg.is_a? Hash
202
- arg.each do |key, value|
203
- if ['class', 'className', 'class_name'].include? key
204
- next unless value
205
-
206
- if value.is_a?(String)
207
- value = value.split(' ')
208
- elsif !value.is_a?(Array)
209
- raise "The class param must be a string or array of strings"
210
- end
211
-
212
- properties['className'] = [*properties['className'], *value]
213
- elsif key == 'style'
214
- next unless value
215
-
216
- if !value.is_a?(Hash)
217
- raise "The style param must be a Hash"
218
- end
219
-
220
- properties['style'] = (properties['style'] || {}).merge(value)
221
- elsif React::HASH_ATTRIBUTES.include?(key) && value.is_a?(Hash)
222
- properties[key] = (properties[key] || {}).merge(value)
223
- else
224
- properties[key] = value
225
- end
226
- end
227
- end
228
- end
229
- # process properties according to react rules
230
- props = {}
231
- properties.each do |key, value|
232
- if ["style", "dangerously_set_inner_HTML"].include? key
233
- props[lower_camelize(key)] = value.to_n
234
-
235
- elsif key == "className"
236
- props[key] = value.join(' ')
237
-
238
- elsif key == "key"
239
- props["key"] = value.to_key
240
-
241
- elsif key == 'ref' && value.respond_to?(:call)
242
- # currently react still accepts the syntax ref: :foo meaning set refs.foo to the ref.
243
- # in hyperstack release 0.1 we can put this behavior on a switch or use the notation `ref_key: :foo` for old school
244
- props[key] = %x{
245
- function(dom_node){
246
- if (dom_node !== null && dom_node.__opalInstance !== undefined && dom_node.__opalInstance !== null) {
247
- #{ value.call(`dom_node.__opalInstance`) };
248
- } else if(dom_node !== null && ReactDOM.findDOMNode !== undefined && dom_node.nodeType === undefined) {
249
- #{ value.call(`ReactDOM.findDOMNode(dom_node)`) };
250
- } else {
251
- #{ value.call(`dom_node`) };
252
- }
253
- }
254
- }
255
- elsif React::HASH_ATTRIBUTES.include?(key) && value.is_a?(Hash)
256
- value.each { |k, v| props["#{key}-#{k.gsub(/__|_/, '__' => '_', '_' => '-')}"] = v.to_n }
257
- else
258
- props[React.html_attr?(lower_camelize(key)) ? lower_camelize(key) : key] = value
259
- end
260
- end
261
- props
262
- end
263
-
264
- private
265
-
266
- def self.lower_camelize(snake_cased_word)
267
- words = snake_cased_word.split('_')
268
- result = [words.first]
269
- result.concat(words[1..-1].map {|word| word[0].upcase + word[1..-1] }).join('')
270
- end
271
- end
272
- end
@@ -1,42 +0,0 @@
1
- require 'hyperloop-config'
2
-
3
- module React
4
- module Callbacks
5
- def self.included(base)
6
- base.extend(ClassMethods)
7
- end
8
-
9
- def run_callback(name, *args)
10
- self.class.callbacks_for(name).each do |callback|
11
- if callback.is_a?(Proc)
12
- instance_exec(*args, &callback)
13
- else
14
- send(callback, *args)
15
- end
16
- end
17
- end
18
-
19
- module ClassMethods
20
- def define_callback(callback_name, &after_define_hook)
21
- wrapper_name = "_#{callback_name}_callbacks"
22
- define_singleton_method(wrapper_name) do
23
- Hyperloop::Context.set_var(self, "@#{wrapper_name}", force: true) { [] }
24
- end
25
- define_singleton_method(callback_name) do |*args, &block|
26
- send(wrapper_name).concat(args)
27
- send(wrapper_name).push(block) if block_given?
28
- after_define_hook.call(*args, &block) if after_define_hook
29
- end
30
- end
31
-
32
- def callbacks_for(callback_name)
33
- wrapper_name = "_#{callback_name}_callbacks"
34
- if superclass.respond_to? :callbacks_for
35
- superclass.callbacks_for(callback_name)
36
- else
37
- []
38
- end + send(wrapper_name)
39
- end
40
- end
41
- end
42
- end