diff --git a/Gemfile.lock b/Gemfile.lock index c072fa6..878a075 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,7 +6,7 @@ PATH opal-activesupport (~> 0) react-jsx (~> 0.8.0) react-source (~> 0.13) - sprockets (~> 3.1) + sprockets (>= 2.2.3, < 3.1) therubyracer (~> 0) GEM @@ -16,15 +16,16 @@ GEM hike (1.2.3) json (1.8.3) libv8 (3.16.14.7) - opal (0.7.1) + multi_json (1.11.1) + opal (0.7.2) hike (~> 1.2) sourcemap (~> 0.1.0) - sprockets (>= 2.2.3, < 4.0.0) + sprockets (>= 2.2.3, < 3.0.0) tilt (~> 1.4) opal-activesupport (0.1.0) opal (>= 0.5.0, < 1.0.0) - opal-jquery (0.2.0) - opal (>= 0.5.0, < 1.0.0) + opal-jquery (0.3.0) + opal (~> 0.7.0) opal-rspec (0.4.2) opal (~> 0.7.0) rack (1.6.1) @@ -42,8 +43,11 @@ GEM rack-protection (~> 1.4) tilt (>= 1.3, < 3) sourcemap (0.1.1) - sprockets (3.2.0) + sprockets (2.12.3) + hike (~> 1.2) + multi_json (~> 1.0) rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) therubyracer (0.12.2) libv8 (~> 3.16.14.0) ref @@ -54,7 +58,10 @@ PLATFORMS DEPENDENCIES opal-jquery (~> 0) - opal-rspec (~> 0.4.2) + opal-rspec rake (~> 10) react.rb! sinatra (~> 1) + +BUNDLED WITH + 1.10.2 diff --git a/opal/react/component.rb b/opal/react/component.rb index c18d6e7..aa7760d 100644 --- a/opal/react/component.rb +++ b/opal/react/component.rb @@ -20,6 +20,14 @@ def self.included(base) end base.extend(ClassMethods) end + + def _render_wrapper + render + rescue Exception => e + message = "Exception raised while rendering #{self.class.name}: #{e}" + `console.error(#{message})` rescue nil + React.create_element("div") # return a valid element so error does not propogate, and we can keep rendering + end def params Hash.new(`#{self}.props`).inject({}) do |memo, (k,v)| diff --git a/opal/react/component_factory.rb b/opal/react/component_factory.rb index f0c5795..6216592 100644 --- a/opal/react/component_factory.rb +++ b/opal/react/component_factory.rb @@ -22,6 +22,7 @@ def self.native_component_class(klass) optional_native_alias[:componentDidUpdate, :component_did_update] optional_native_alias[:componentWillUnmount, :component_will_unmount] native_alias :render, :render + optional_native_alias[:render, :_render_wrapper] end %x{ if (!Object.assign) { diff --git a/react.rb.gemspec b/react.rb.gemspec index 326549f..e734e45 100644 --- a/react.rb.gemspec +++ b/react.rb.gemspec @@ -20,10 +20,10 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'opal-activesupport', '~> 0' s.add_runtime_dependency 'therubyracer', '~> 0' s.add_runtime_dependency 'react-jsx', '~> 0.8.0' - s.add_runtime_dependency 'sprockets', '~> 3.1' + s.add_runtime_dependency 'sprockets', '>= 2.2.3', '< 3.1' s.add_runtime_dependency 'react-source', '~> 0.13' - s.add_development_dependency 'opal-rspec', '~> 0.4.2' + s.add_development_dependency 'opal-rspec' s.add_development_dependency 'sinatra', '~> 1' s.add_development_dependency 'opal-jquery', '~> 0' s.add_development_dependency 'rake', '~> 10' diff --git a/spec/component_factory_spec.rb b/spec/component_factory_spec.rb index 71b1085..1adb458 100644 --- a/spec/component_factory_spec.rb +++ b/spec/component_factory_spec.rb @@ -2,7 +2,7 @@ describe React::ComponentFactory do describe "native_component_class" do - it "should bridge the defined life cycle methods" do + it "should bridge the defined life cycle methods and the render method" do stub_const 'Foo', Class.new Foo.class_eval do def component_will_mount; end @@ -12,6 +12,7 @@ def should_component_update?; end def component_will_update; end def component_did_update; end def component_will_unmount; end + def render; end end ctor = React::ComponentFactory.native_component_class(Foo) @@ -23,6 +24,7 @@ def component_will_unmount; end expect(`instance.$component_will_update`).to be(`instance.componentWillUpdate`) expect(`instance.$component_did_update`).to be(`instance.componentDidUpdate`) expect(`instance.$component_will_unmount`).to be(`instance.componentWillUnmount`) + expect(`instance.$render`).to be(`instance.render`) end end end diff --git a/spec/exception_handling_spec.rb b/spec/exception_handling_spec.rb new file mode 100644 index 0000000..aa84259 --- /dev/null +++ b/spec/exception_handling_spec.rb @@ -0,0 +1,28 @@ +describe "displaying helpful warning and error messages" do + + before(:all) do + %x{ + window.old_error_console = console.error + console.error = function(m) { window.last_error_message = m; } + } + end + + after(:all) do + %x{ + console.error = window.old_error_console + } + end + + it "should print and exception message" do + stub_const 'Foo', Class.new + Foo.class_eval do + include React::Component + def render + raise "error happened" + end + end + React.render_to_static_markup(React.create_element(Foo)) + expect(`window.last_error_message`).to include("error happened") + end + +end \ No newline at end of file diff --git a/upgradetodos.txt b/upgradetodos.txt new file mode 100644 index 0000000..9a39501 --- /dev/null +++ b/upgradetodos.txt @@ -0,0 +1,49 @@ + +observable_spec.rb + +native_library_spec.rb <- no big interaction, just hooks into @@component_classes - but depends on RenderingContext + + importing native react components (like bootstrap) + + +export_component_spec.rb <- completely stand alone + export_component + + +rendering_context_spec.rb + NOTE: rendering context primarily exists so that we can say Foo::Bar in the dsl, because we have no way of knowing the caller, so we have to track it via RenderingContext + NOTE: put the component lookup method in here I think + components can be directly named in the dsl (i.e. if class Foo, then you can just say Foo) + _as_node will return the native node without pushing into the buffer + if element returned from the child block is a string it is added to the buffer + test to make sure subclassing components works + +exception_handling_spec.rb + you don't have to have render method, if you just want to export state <- not sure what is going on here, but there is a render method now in the component, that raises an error unless its subclassed + catch and print rendering method if rendering fails. + I'm figuring that there will more exception cases (like misnamed components) that can go in this file. + +state_spec.rb + states all get methods - states define methods foo, foo= and foo! + export / import states + states can be defined from within components instances (i.e. before_mount) + define_state extended syntax: strings/symbols are initialized to the default initializer (nil or provided by block), the hash gives name => value pairs + if default initializer excepts params then it is considered a state listener and will receive |state_name, current_value, new_value| on state changes + + +params_spec.rb + NOTE: probably updates validator + can require param on a single line: required_param or optional_param + can require param of type Proc + params get methods + proc params automatically call + ReactObserver params interact with the observer + + +depends on react-source <- does it have to (i.e. perhaps for react-rails to work?, if not then do a separate PR at end) + +Branch map... + +v13_base is synced with v13 BUT already has observable.rb added. (todo if possible, shuffle this around) + <- exception_handling branched fro v13_base + <- export_component branched from v13_base \ No newline at end of file