#### Notes on how component names are looked up Given: ```ruby class Blat < React::Component::Base render do Bar() Foo::Bar() end end class Bar < React::Component::Base end module Foo class Bar < React::Component::Base render do Blat() Baz() end end class Baz < React::Component::Base end end ``` The problem is that method lookup is different than constant lookup. We can prove it by running this code: ```ruby def try_it(test, &block) puts "trying #{test}" result = yield puts "success#{': '+result.to_s if result}" rescue Exception => e puts "failed: #{e}" ensure puts "---------------------------------" end module Boom Bar = 12 def self.Bar puts " Boom::Bar says hi" end class Baz def doit try_it("Bar()") { Bar() } try_it("Boom::Bar()") {Boom::Bar()} try_it("Bar") { Bar } try_it("Boom::Bar") { Boom::Bar } end end end Boom::Baz.new.doit ``` which prints: ```text trying Bar() failed: Bar: undefined method `Bar' for # --------------------------------- trying Boom::Bar() Boom::Bar says hi success --------------------------------- trying Bar success: 12 --------------------------------- trying Boom::Bar success: 12 --------------------------------- ``` [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) What we need to do is: 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. 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. #### details To define `self.Foo` in the same scope level as the class `Foo`, we need code like this: ```ruby def register_component_dsl_method(component) split_name = component.name && component.name.split('::') return unless split_name && split_name.length > 2 component_name = split_name.last parent = split_name.inject([Module]) { |nesting, next_const| nesting + [nesting.last.const_get(next_const)] }[-2] class << parent define_method component_name do |*args, &block| React::RenderingContext.render(name, *args, &block) end define_method "#{component_name}_as_node" do |*args, &block| React::Component.deprecation_warning("..._as_node is deprecated. Render component and then use the .node method instead") send(component_name, *args, &block).node end end end module React module Component def self.included(base) ... register_component_dsl_method(base.name) end end end ``` The component's method_missing function will look like this: ```ruby def method_missing(name, *args, &block) if name =~ /_as_node$/ React::Component.deprecation_warning("..._as_node is deprecated. Render component and then use the .node method instead") method_missing(name.gsub(/_as_node$/,""), *args, &block).node else component = const_get name if defined? name React::RenderingContext.render(nil, component, *args, &block) end end ``` ### other related issues The Kernel#p method conflicts with the

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.