react.rb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +30 -0
 - data/Gemfile +2 -0
 - data/Gemfile.lock +48 -0
 - data/LICENSE +19 -0
 - data/README.md +166 -0
 - data/config.ru +15 -0
 - data/example/react-tutorial/Gemfile +6 -0
 - data/example/react-tutorial/Gemfile.lock +45 -0
 - data/example/react-tutorial/README.md +8 -0
 - data/example/react-tutorial/_comments.json +6 -0
 - data/example/react-tutorial/config.ru +55 -0
 - data/example/react-tutorial/example.rb +104 -0
 - data/example/react-tutorial/public/base.css +62 -0
 - data/example/todos/Gemfile +11 -0
 - data/example/todos/Gemfile.lock +84 -0
 - data/example/todos/README.md +37 -0
 - data/example/todos/Rakefile +8 -0
 - data/example/todos/app/application.rb +22 -0
 - data/example/todos/app/components/app.react.rb +61 -0
 - data/example/todos/app/components/footer.react.rb +31 -0
 - data/example/todos/app/components/todo_item.react.rb +46 -0
 - data/example/todos/app/components/todo_list.react.rb +25 -0
 - data/example/todos/app/models/todo.rb +19 -0
 - data/example/todos/config.ru +14 -0
 - data/example/todos/index.html.haml +16 -0
 - data/example/todos/spec/todo_spec.rb +28 -0
 - data/example/todos/vendor/base.css +410 -0
 - data/example/todos/vendor/bg.png +0 -0
 - data/example/todos/vendor/jquery.js +4 -0
 - data/lib/react.rb +16 -0
 - data/lib/react/api.rb +95 -0
 - data/lib/react/callbacks.rb +35 -0
 - data/lib/react/component.rb +197 -0
 - data/lib/react/element.rb +63 -0
 - data/lib/react/event.rb +76 -0
 - data/lib/react/ext/hash.rb +9 -0
 - data/lib/react/ext/string.rb +8 -0
 - data/lib/react/top_level.rb +50 -0
 - data/lib/react/validator.rb +65 -0
 - data/lib/react/version.rb +3 -0
 - data/react.rb.gemspec +24 -0
 - data/spec/callbacks_spec.rb +107 -0
 - data/spec/component_spec.rb +556 -0
 - data/spec/element_spec.rb +60 -0
 - data/spec/event_spec.rb +22 -0
 - data/spec/react_spec.rb +168 -0
 - data/spec/reactjs/index.html.erb +10 -0
 - data/spec/spec_helper.rb +29 -0
 - data/spec/validator_spec.rb +79 -0
 - data/vendor/active_support/core_ext/array/extract_options.rb +29 -0
 - data/vendor/active_support/core_ext/class/attribute.rb +127 -0
 - data/vendor/active_support/core_ext/kernel/singleton_class.rb +13 -0
 - data/vendor/active_support/core_ext/module/remove_method.rb +11 -0
 - metadata +189 -0
 
| 
         @@ -0,0 +1,60 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe React::Element do
         
     | 
| 
      
 4 
     | 
    
         
            +
              it "should bridge `type` of native React.Element attributes" do
         
     | 
| 
      
 5 
     | 
    
         
            +
                element = React.create_element('div')
         
     | 
| 
      
 6 
     | 
    
         
            +
                expect(element.element_type).to eq("div")
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              async "should be renderable" do
         
     | 
| 
      
 10 
     | 
    
         
            +
                element = React.create_element('span')
         
     | 
| 
      
 11 
     | 
    
         
            +
                div = `document.createElement("div")`
         
     | 
| 
      
 12 
     | 
    
         
            +
                React.render(element, div) do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  run_async {
         
     | 
| 
      
 14 
     | 
    
         
            +
                    expect(`div.children[0].tagName`).to eq("SPAN")
         
     | 
| 
      
 15 
     | 
    
         
            +
                  }
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              describe "Event subscription" do
         
     | 
| 
      
 20 
     | 
    
         
            +
                it "should be subscribable through `on(:event_name)` method" do
         
     | 
| 
      
 21 
     | 
    
         
            +
                  expect { |b|
         
     | 
| 
      
 22 
     | 
    
         
            +
                    element = React.create_element("div").on(:click, &b)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    instance = renderElementToDocument(element)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    simulateEvent(:click, instance)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  }.to yield_with_args(React::Event)
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  expect { |b|
         
     | 
| 
      
 28 
     | 
    
         
            +
                    element = React.create_element("div").on(:key_down, &b)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    instance = renderElementToDocument(element)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    simulateEvent(:keyDown, instance, {key: "Enter"})
         
     | 
| 
      
 31 
     | 
    
         
            +
                  }.to yield_control
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  expect { |b|
         
     | 
| 
      
 34 
     | 
    
         
            +
                    element = React.create_element("form").on(:submit, &b)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    instance = renderElementToDocument(element)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    simulateEvent(:submit, instance, {})
         
     | 
| 
      
 37 
     | 
    
         
            +
                  }.to yield_control
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                it "should return self for `on` method" do
         
     | 
| 
      
 41 
     | 
    
         
            +
                  element = React.create_element("div")
         
     | 
| 
      
 42 
     | 
    
         
            +
                  expect(element.on(:click){}).to eq(element)
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              describe "Children" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                it "should return a Enumerable" do
         
     | 
| 
      
 48 
     | 
    
         
            +
                  ele = React.create_element('div') { [React.create_element('a'), React.create_element('li')] }
         
     | 
| 
      
 49 
     | 
    
         
            +
                  nodes = ele.children.map {|ele| ele.element_type }
         
     | 
| 
      
 50 
     | 
    
         
            +
                  expect(nodes).to eq(["a", "li"])
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                it "should return a Enumerator when not providing a block" do
         
     | 
| 
      
 54 
     | 
    
         
            +
                  ele = React.create_element('div') { [React.create_element('a'), React.create_element('li')] }
         
     | 
| 
      
 55 
     | 
    
         
            +
                  nodes = ele.children.each
         
     | 
| 
      
 56 
     | 
    
         
            +
                  expect(nodes).to be_a(Enumerator)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  expect(nodes.size).to eq(2)
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/event_spec.rb
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe React::Event do
         
     | 
| 
      
 4 
     | 
    
         
            +
              it "should bridge attributes of native SyntheticEvent (see http://facebook.github.io/react/docs/events.html#syntheticevent)" do
         
     | 
| 
      
 5 
     | 
    
         
            +
                element = React.create_element('div').on(:click) do |event|
         
     | 
| 
      
 6 
     | 
    
         
            +
                  expect(event.bubbles).to eq(`#{event.to_n}.bubbles`)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  expect(event.cancelable).to eq(`#{event.to_n}.cancelable`)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  expect(event.current_target).to eq(`#{event.to_n}.currentTarget`)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  expect(event.default_prevented).to eq(`#{event.to_n}.defaultPrevented`)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  expect(event.event_phase).to eq(`#{event.to_n}.eventPhase`)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  expect(event.is_trusted?).to eq(`#{event.to_n}.isTrusted`)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  expect(event.native_event).to eq(`#{event.to_n}.nativeEvent`)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  expect(event.target).to eq(`#{event.to_n}.target`)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  expect(event.timestamp).to eq(`#{event.to_n}.timeStamp`)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  expect(event.event_type).to eq(`#{event.to_n}.type`)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  expect(event).to respond_to(:prevent_default)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  expect(event).to respond_to(:stop_propagation)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
                instance = renderElementToDocument(element)
         
     | 
| 
      
 20 
     | 
    
         
            +
                simulateEvent(:click, instance)
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/react_spec.rb
    ADDED
    
    | 
         @@ -0,0 +1,168 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe React do
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe "is_valid_element" do
         
     | 
| 
      
 5 
     | 
    
         
            +
                it "should return true if passed a valid element" do
         
     | 
| 
      
 6 
     | 
    
         
            +
                  element = React::Element.new(`React.createElement('div')`)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  expect(React.is_valid_element(element)).to eq(true)
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                it "should return false is passed a non React element" do
         
     | 
| 
      
 11 
     | 
    
         
            +
                  element = React::Element.new(`{}`)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  expect(React.is_valid_element(element)).to eq(false)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              describe "create_element" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                it "should create a valid element with only tag" do
         
     | 
| 
      
 18 
     | 
    
         
            +
                  element = React.create_element('div')
         
     | 
| 
      
 19 
     | 
    
         
            +
                  expect(React.is_valid_element(element)).to eq(true)
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                context "with block" do
         
     | 
| 
      
 23 
     | 
    
         
            +
                  it "should create a valid element with text as only child when block yield String" do
         
     | 
| 
      
 24 
     | 
    
         
            +
                    element = React.create_element('div') { "lorem ipsum" }
         
     | 
| 
      
 25 
     | 
    
         
            +
                    expect(React.is_valid_element(element)).to eq(true)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    expect(element.props.children).to eq("lorem ipsum")
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  it "should create a valid element with children as array when block yield Array of element" do
         
     | 
| 
      
 30 
     | 
    
         
            +
                    element = React.create_element('div') do
         
     | 
| 
      
 31 
     | 
    
         
            +
                      [React.create_element('span'), React.create_element('span'), React.create_element('span')]
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
                    expect(React.is_valid_element(element)).to eq(true)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    expect(element.props.children.length).to eq(3)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  it "should render element with children as array when block yield Array of element" do
         
     | 
| 
      
 38 
     | 
    
         
            +
                    element = React.create_element('div') do
         
     | 
| 
      
 39 
     | 
    
         
            +
                      [React.create_element('span'), React.create_element('span'), React.create_element('span')]
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                    instance = renderElementToDocument(element)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    expect(instance.getDOMNode.childNodes.length).to eq(3)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
                describe "custom element" do
         
     | 
| 
      
 46 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 47 
     | 
    
         
            +
                    stub_const 'Foo', Class.new
         
     | 
| 
      
 48 
     | 
    
         
            +
                    Foo.class_eval do
         
     | 
| 
      
 49 
     | 
    
         
            +
                      def render
         
     | 
| 
      
 50 
     | 
    
         
            +
                        React.create_element("div") { "lorem" }
         
     | 
| 
      
 51 
     | 
    
         
            +
                      end
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  it "should render element with only one children correctly" do
         
     | 
| 
      
 56 
     | 
    
         
            +
                    element = React.create_element(Foo) { React.create_element('span') }
         
     | 
| 
      
 57 
     | 
    
         
            +
                    instance = renderElementToDocument(element)
         
     | 
| 
      
 58 
     | 
    
         
            +
                    expect(instance.props.children).not_to be_a(Array)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    expect(instance.props.children.type).to eq("span")
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  it "should render element with more than one children correctly" do
         
     | 
| 
      
 63 
     | 
    
         
            +
                    element = React.create_element(Foo) { [React.create_element('span'), React.create_element('span')] }
         
     | 
| 
      
 64 
     | 
    
         
            +
                    instance = renderElementToDocument(element)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    expect(instance.props.children).to be_a(Array)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    expect(instance.props.children.length).to eq(2)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  it "should create a valid element provided class defined `render`" do
         
     | 
| 
      
 70 
     | 
    
         
            +
                    element = React.create_element(Foo)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    expect(React.is_valid_element(element)).to eq(true)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  it "should allow creating with properties" do
         
     | 
| 
      
 75 
     | 
    
         
            +
                    element = React.create_element(Foo, foo: "bar")
         
     | 
| 
      
 76 
     | 
    
         
            +
                    expect(element.props.foo).to eq("bar")
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  it "should raise error if provided class doesn't defined `render`" do
         
     | 
| 
      
 80 
     | 
    
         
            +
                    expect { React.create_element(Array) }.to raise_error
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                describe "create element with properties" do
         
     | 
| 
      
 85 
     | 
    
         
            +
                  it "should enforce snake-cased property name" do
         
     | 
| 
      
 86 
     | 
    
         
            +
                    element = React.create_element("div", class_name: "foo")
         
     | 
| 
      
 87 
     | 
    
         
            +
                    expect(element.props.className).to eq("foo")
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  it "should allow custom property" do
         
     | 
| 
      
 91 
     | 
    
         
            +
                    element = React.create_element("div", foo: "bar")
         
     | 
| 
      
 92 
     | 
    
         
            +
                    expect(element.props.foo).to eq("bar")
         
     | 
| 
      
 93 
     | 
    
         
            +
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                  it "should not camel-case custom property" do
         
     | 
| 
      
 96 
     | 
    
         
            +
                    element = React.create_element("div", foo_bar: "foo")
         
     | 
| 
      
 97 
     | 
    
         
            +
                    expect(element.props.foo_bar).to eq("foo")
         
     | 
| 
      
 98 
     | 
    
         
            +
                  end
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                describe "class_name helpers (React.addons.classSet)" do
         
     | 
| 
      
 102 
     | 
    
         
            +
                  it "should transform Hash provided to `class_name` props as string" do
         
     | 
| 
      
 103 
     | 
    
         
            +
                    classes = {foo: true, bar: false, lorem: true}
         
     | 
| 
      
 104 
     | 
    
         
            +
                    element = React.create_element("div", class_name: classes)
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                    expect(element.props.className).to eq("foo lorem")
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  it "should not alter behavior when passing a string" do
         
     | 
| 
      
 110 
     | 
    
         
            +
                    element = React.create_element("div", class_name: "foo bar")
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                    expect(element.props.className).to eq("foo bar")
         
     | 
| 
      
 113 
     | 
    
         
            +
                  end
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
              describe "render" do
         
     | 
| 
      
 119 
     | 
    
         
            +
                async "should render element to DOM" do
         
     | 
| 
      
 120 
     | 
    
         
            +
                  div = `document.createElement("div")`
         
     | 
| 
      
 121 
     | 
    
         
            +
                  React.render(React.create_element('span') { "lorem" }, div) do
         
     | 
| 
      
 122 
     | 
    
         
            +
                    run_async {
         
     | 
| 
      
 123 
     | 
    
         
            +
                      expect(`div.children[0].tagName`).to eq("SPAN")
         
     | 
| 
      
 124 
     | 
    
         
            +
                      expect(`div.textContent`).to eq("lorem")
         
     | 
| 
      
 125 
     | 
    
         
            +
                    }
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                it "should work without providing a block" do
         
     | 
| 
      
 130 
     | 
    
         
            +
                  div = `document.createElement("div")`
         
     | 
| 
      
 131 
     | 
    
         
            +
                  React.render(React.create_element('span') { "lorem" }, div)
         
     | 
| 
      
 132 
     | 
    
         
            +
                end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                it "should return a React::Component::API compatible object" do
         
     | 
| 
      
 135 
     | 
    
         
            +
                  div = `document.createElement("div")`
         
     | 
| 
      
 136 
     | 
    
         
            +
                  component = React.render(React.create_element('span') { "lorem" }, div)
         
     | 
| 
      
 137 
     | 
    
         
            +
                  React::Component::API.public_instance_methods(true).each do |method_name|
         
     | 
| 
      
 138 
     | 
    
         
            +
                    expect(component).to respond_to(method_name)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                pending "should return nil to prevent abstraction leakage" do
         
     | 
| 
      
 143 
     | 
    
         
            +
                  div = `document.createElement("div")`
         
     | 
| 
      
 144 
     | 
    
         
            +
                  expect {
         
     | 
| 
      
 145 
     | 
    
         
            +
                    React.render(React.create_element('span') { "lorem" }, div)
         
     | 
| 
      
 146 
     | 
    
         
            +
                  }.to be_nil
         
     | 
| 
      
 147 
     | 
    
         
            +
                end
         
     | 
| 
      
 148 
     | 
    
         
            +
              end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
              describe "render_to_string" do
         
     | 
| 
      
 151 
     | 
    
         
            +
                it "should render a React.Element to string" do
         
     | 
| 
      
 152 
     | 
    
         
            +
                  ele = React.create_element('span') { "lorem" }
         
     | 
| 
      
 153 
     | 
    
         
            +
                  expect(React.render_to_string(ele)).to be_kind_of(String)
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
              end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
              describe "unmount_component_at_node" do
         
     | 
| 
      
 158 
     | 
    
         
            +
                async "should unmount component at node" do
         
     | 
| 
      
 159 
     | 
    
         
            +
                  div = `document.createElement("div")`
         
     | 
| 
      
 160 
     | 
    
         
            +
                  React.render(React.create_element('span') { "lorem" }, div ) do
         
     | 
| 
      
 161 
     | 
    
         
            +
                    run_async {
         
     | 
| 
      
 162 
     | 
    
         
            +
                      expect(React.unmount_component_at_node(div)).to eq(true)
         
     | 
| 
      
 163 
     | 
    
         
            +
                    }
         
     | 
| 
      
 164 
     | 
    
         
            +
                  end
         
     | 
| 
      
 165 
     | 
    
         
            +
                end
         
     | 
| 
      
 166 
     | 
    
         
            +
              end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec_helper.rb
    ADDED
    
    | 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'react'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module ReactTestHelpers
         
     | 
| 
      
 4 
     | 
    
         
            +
              `var ReactTestUtils = React.addons.TestUtils`
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def renderToDocument(type, options = {})
         
     | 
| 
      
 7 
     | 
    
         
            +
                element = React.create_element(type, options)
         
     | 
| 
      
 8 
     | 
    
         
            +
                return renderElementToDocument(element)
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              def renderElementToDocument(element)
         
     | 
| 
      
 12 
     | 
    
         
            +
                instance = Native(`ReactTestUtils.renderIntoDocument(#{element.to_n})`)
         
     | 
| 
      
 13 
     | 
    
         
            +
                instance.class.include(React::Component::API)
         
     | 
| 
      
 14 
     | 
    
         
            +
                return instance
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def simulateEvent(event, element, params = {})
         
     | 
| 
      
 18 
     | 
    
         
            +
                simulator = Native(`ReactTestUtils.Simulate`)
         
     | 
| 
      
 19 
     | 
    
         
            +
                simulator[event.to_s].call(`#{element.to_n}.getDOMNode()`, params)
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              def isElementOfType(element, type)
         
     | 
| 
      
 23 
     | 
    
         
            +
                `React.addons.TestUtils.isElementOfType(#{element.to_n}, #{type.cached_component_class})`
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            RSpec.configure do |config|
         
     | 
| 
      
 28 
     | 
    
         
            +
              config.include ReactTestHelpers
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,79 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe React::Validator do
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe "validate" do
         
     | 
| 
      
 5 
     | 
    
         
            +
                describe "Presence validation" do
         
     | 
| 
      
 6 
     | 
    
         
            +
                  it "should check if required props provided" do
         
     | 
| 
      
 7 
     | 
    
         
            +
                    validator = React::Validator.build do
         
     | 
| 
      
 8 
     | 
    
         
            +
                      requires :foo
         
     | 
| 
      
 9 
     | 
    
         
            +
                      requires :bar
         
     | 
| 
      
 10 
     | 
    
         
            +
                    end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    expect(validator.validate({})).to eq(["Required prop `foo` was not specified", "Required prop `bar` was not specified"])
         
     | 
| 
      
 13 
     | 
    
         
            +
                    expect(validator.validate({foo: 1, bar: 3})).to eq([])
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  it "should check if passed non specified prop" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                    validator = React::Validator.build do
         
     | 
| 
      
 18 
     | 
    
         
            +
                      optional :foo
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    expect(validator.validate({bar: 10})).to eq(["Provided prop `bar` not specified in spec"])
         
     | 
| 
      
 22 
     | 
    
         
            +
                    expect(validator.validate({foo: 10})).to eq([])
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                describe "Type validation" do
         
     | 
| 
      
 27 
     | 
    
         
            +
                  it "should check if passed value with wrong type" do
         
     | 
| 
      
 28 
     | 
    
         
            +
                    validator = React::Validator.build do
         
     | 
| 
      
 29 
     | 
    
         
            +
                      requires :foo, type: String
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    expect(validator.validate({foo: 10})).to eq(["Provided prop `foo` was not the specified type `String`"])
         
     | 
| 
      
 33 
     | 
    
         
            +
                    expect(validator.validate({foo: "10"})).to eq([])
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  it "should check if passed value with wrong custom type" do
         
     | 
| 
      
 37 
     | 
    
         
            +
                    stub_const 'Bar', Class.new
         
     | 
| 
      
 38 
     | 
    
         
            +
                    validator = React::Validator.build do
         
     | 
| 
      
 39 
     | 
    
         
            +
                      requires :foo, type: Bar
         
     | 
| 
      
 40 
     | 
    
         
            +
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    expect(validator.validate({foo: 10})).to eq(["Provided prop `foo` was not the specified type `Bar`"])
         
     | 
| 
      
 43 
     | 
    
         
            +
                    expect(validator.validate({foo: Bar.new})).to eq([])
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  it "should support Array[Class] validation" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                    validator = React::Validator.build do
         
     | 
| 
      
 48 
     | 
    
         
            +
                      requires :foo, type: Array[Hash]
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    expect(validator.validate({foo: [1,'2',3]})).to eq(["Provided prop `foo` was not an Array of the specified type `Hash`"])
         
     | 
| 
      
 52 
     | 
    
         
            +
                    expect(validator.validate({foo: [{},{},{}]})).to eq([])
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                describe "Limited values" do
         
     | 
| 
      
 57 
     | 
    
         
            +
                  it "should check if passed value is not one of the specified values" do
         
     | 
| 
      
 58 
     | 
    
         
            +
                    validator = React::Validator.build do
         
     | 
| 
      
 59 
     | 
    
         
            +
                      requires :foo, values: [4,5,6]
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                    expect(validator.validate({foo: 3})).to eq(["Value `3` for prop `foo` is not an allowed value"])
         
     | 
| 
      
 63 
     | 
    
         
            +
                    expect(validator.validate({foo: 4})).to eq([])
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              describe "default_props" do
         
     | 
| 
      
 69 
     | 
    
         
            +
                it "should return specified default values" do
         
     | 
| 
      
 70 
     | 
    
         
            +
                  validator = React::Validator.build do
         
     | 
| 
      
 71 
     | 
    
         
            +
                    requires :foo, default: 10
         
     | 
| 
      
 72 
     | 
    
         
            +
                    requires :bar
         
     | 
| 
      
 73 
     | 
    
         
            +
                    optional :lorem, default: 20
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  expect(validator.default_props).to eq({foo: 10, lorem: 20})
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Hash
         
     | 
| 
      
 2 
     | 
    
         
            +
              # By default, only instances of Hash itself are extractable.
         
     | 
| 
      
 3 
     | 
    
         
            +
              # Subclasses of Hash may implement this method and return
         
     | 
| 
      
 4 
     | 
    
         
            +
              # true to declare themselves as extractable. If a Hash
         
     | 
| 
      
 5 
     | 
    
         
            +
              # is extractable, Array#extract_options! pops it from
         
     | 
| 
      
 6 
     | 
    
         
            +
              # the Array when it is the last element of the Array.
         
     | 
| 
      
 7 
     | 
    
         
            +
              def extractable_options?
         
     | 
| 
      
 8 
     | 
    
         
            +
                instance_of?(Hash)
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
            end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            class Array
         
     | 
| 
      
 13 
     | 
    
         
            +
              # Extracts options from a set of arguments. Removes and returns the last
         
     | 
| 
      
 14 
     | 
    
         
            +
              # element in the array if it's a hash, otherwise returns a blank hash.
         
     | 
| 
      
 15 
     | 
    
         
            +
              #
         
     | 
| 
      
 16 
     | 
    
         
            +
              #   def options(*args)
         
     | 
| 
      
 17 
     | 
    
         
            +
              #     args.extract_options!
         
     | 
| 
      
 18 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 19 
     | 
    
         
            +
              #
         
     | 
| 
      
 20 
     | 
    
         
            +
              #   options(1, 2)           # => {}
         
     | 
| 
      
 21 
     | 
    
         
            +
              #   options(1, 2, :a => :b) # => {:a=>:b}
         
     | 
| 
      
 22 
     | 
    
         
            +
              def extract_options!
         
     | 
| 
      
 23 
     | 
    
         
            +
                if last.is_a?(Hash) && last.extractable_options?
         
     | 
| 
      
 24 
     | 
    
         
            +
                  pop
         
     | 
| 
      
 25 
     | 
    
         
            +
                else
         
     | 
| 
      
 26 
     | 
    
         
            +
                  {}
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,127 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'active_support/core_ext/kernel/singleton_class'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'active_support/core_ext/module/remove_method'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'active_support/core_ext/array/extract_options'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class Class
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Declare a class-level attribute whose value is inheritable by subclasses.
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Subclasses can change their own value and it will not impact parent class.
         
     | 
| 
      
 8 
     | 
    
         
            +
              #
         
     | 
| 
      
 9 
     | 
    
         
            +
              #   class Base
         
     | 
| 
      
 10 
     | 
    
         
            +
              #     class_attribute :setting
         
     | 
| 
      
 11 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 12 
     | 
    
         
            +
              #
         
     | 
| 
      
 13 
     | 
    
         
            +
              #   class Subclass < Base
         
     | 
| 
      
 14 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 15 
     | 
    
         
            +
              #
         
     | 
| 
      
 16 
     | 
    
         
            +
              #   Base.setting = true
         
     | 
| 
      
 17 
     | 
    
         
            +
              #   Subclass.setting            # => true
         
     | 
| 
      
 18 
     | 
    
         
            +
              #   Subclass.setting = false
         
     | 
| 
      
 19 
     | 
    
         
            +
              #   Subclass.setting            # => false
         
     | 
| 
      
 20 
     | 
    
         
            +
              #   Base.setting                # => true
         
     | 
| 
      
 21 
     | 
    
         
            +
              #
         
     | 
| 
      
 22 
     | 
    
         
            +
              # In the above case as long as Subclass does not assign a value to setting
         
     | 
| 
      
 23 
     | 
    
         
            +
              # by performing <tt>Subclass.setting = _something_ </tt>, <tt>Subclass.setting</tt>
         
     | 
| 
      
 24 
     | 
    
         
            +
              # would read value assigned to parent class. Once Subclass assigns a value then
         
     | 
| 
      
 25 
     | 
    
         
            +
              # the value assigned by Subclass would be returned.
         
     | 
| 
      
 26 
     | 
    
         
            +
              #
         
     | 
| 
      
 27 
     | 
    
         
            +
              # This matches normal Ruby method inheritance: think of writing an attribute
         
     | 
| 
      
 28 
     | 
    
         
            +
              # on a subclass as overriding the reader method. However, you need to be aware
         
     | 
| 
      
 29 
     | 
    
         
            +
              # when using +class_attribute+ with mutable structures as +Array+ or +Hash+.
         
     | 
| 
      
 30 
     | 
    
         
            +
              # In such cases, you don't want to do changes in places but use setters:
         
     | 
| 
      
 31 
     | 
    
         
            +
              #
         
     | 
| 
      
 32 
     | 
    
         
            +
              #   Base.setting = []
         
     | 
| 
      
 33 
     | 
    
         
            +
              #   Base.setting                # => []
         
     | 
| 
      
 34 
     | 
    
         
            +
              #   Subclass.setting            # => []
         
     | 
| 
      
 35 
     | 
    
         
            +
              #
         
     | 
| 
      
 36 
     | 
    
         
            +
              #   # Appending in child changes both parent and child because it is the same object:
         
     | 
| 
      
 37 
     | 
    
         
            +
              #   Subclass.setting << :foo
         
     | 
| 
      
 38 
     | 
    
         
            +
              #   Base.setting               # => [:foo]
         
     | 
| 
      
 39 
     | 
    
         
            +
              #   Subclass.setting           # => [:foo]
         
     | 
| 
      
 40 
     | 
    
         
            +
              #
         
     | 
| 
      
 41 
     | 
    
         
            +
              #   # Use setters to not propagate changes:
         
     | 
| 
      
 42 
     | 
    
         
            +
              #   Base.setting = []
         
     | 
| 
      
 43 
     | 
    
         
            +
              #   Subclass.setting += [:foo]
         
     | 
| 
      
 44 
     | 
    
         
            +
              #   Base.setting               # => []
         
     | 
| 
      
 45 
     | 
    
         
            +
              #   Subclass.setting           # => [:foo]
         
     | 
| 
      
 46 
     | 
    
         
            +
              #
         
     | 
| 
      
 47 
     | 
    
         
            +
              # For convenience, an instance predicate method is defined as well.
         
     | 
| 
      
 48 
     | 
    
         
            +
              # To skip it, pass <tt>instance_predicate: false</tt>.
         
     | 
| 
      
 49 
     | 
    
         
            +
              #
         
     | 
| 
      
 50 
     | 
    
         
            +
              #   Subclass.setting?       # => false
         
     | 
| 
      
 51 
     | 
    
         
            +
              #
         
     | 
| 
      
 52 
     | 
    
         
            +
              # Instances may overwrite the class value in the same way:
         
     | 
| 
      
 53 
     | 
    
         
            +
              #
         
     | 
| 
      
 54 
     | 
    
         
            +
              #   Base.setting = true
         
     | 
| 
      
 55 
     | 
    
         
            +
              #   object = Base.new
         
     | 
| 
      
 56 
     | 
    
         
            +
              #   object.setting          # => true
         
     | 
| 
      
 57 
     | 
    
         
            +
              #   object.setting = false
         
     | 
| 
      
 58 
     | 
    
         
            +
              #   object.setting          # => false
         
     | 
| 
      
 59 
     | 
    
         
            +
              #   Base.setting            # => true
         
     | 
| 
      
 60 
     | 
    
         
            +
              #
         
     | 
| 
      
 61 
     | 
    
         
            +
              # To opt out of the instance reader method, pass <tt>instance_reader: false</tt>.
         
     | 
| 
      
 62 
     | 
    
         
            +
              #
         
     | 
| 
      
 63 
     | 
    
         
            +
              #   object.setting          # => NoMethodError
         
     | 
| 
      
 64 
     | 
    
         
            +
              #   object.setting?         # => NoMethodError
         
     | 
| 
      
 65 
     | 
    
         
            +
              #
         
     | 
| 
      
 66 
     | 
    
         
            +
              # To opt out of the instance writer method, pass <tt>instance_writer: false</tt>.
         
     | 
| 
      
 67 
     | 
    
         
            +
              #
         
     | 
| 
      
 68 
     | 
    
         
            +
              #   object.setting = false  # => NoMethodError
         
     | 
| 
      
 69 
     | 
    
         
            +
              #
         
     | 
| 
      
 70 
     | 
    
         
            +
              # To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
         
     | 
| 
      
 71 
     | 
    
         
            +
              def class_attribute(*attrs)
         
     | 
| 
      
 72 
     | 
    
         
            +
                options = attrs.extract_options!
         
     | 
| 
      
 73 
     | 
    
         
            +
                instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
         
     | 
| 
      
 74 
     | 
    
         
            +
                instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
         
     | 
| 
      
 75 
     | 
    
         
            +
                instance_predicate = options.fetch(:instance_predicate, true)
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                attrs.each do |name|
         
     | 
| 
      
 78 
     | 
    
         
            +
                  define_singleton_method(name) { nil }
         
     | 
| 
      
 79 
     | 
    
         
            +
                  define_singleton_method("#{name}?") { !!public_send(name) } if instance_predicate
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  ivar = "@#{name}"
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                  define_singleton_method("#{name}=") do |val|
         
     | 
| 
      
 84 
     | 
    
         
            +
                    singleton_class.class_eval do
         
     | 
| 
      
 85 
     | 
    
         
            +
                      remove_possible_method(name)
         
     | 
| 
      
 86 
     | 
    
         
            +
                      define_method(name) { val }
         
     | 
| 
      
 87 
     | 
    
         
            +
                    end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                    if singleton_class?
         
     | 
| 
      
 90 
     | 
    
         
            +
                      class_eval do
         
     | 
| 
      
 91 
     | 
    
         
            +
                        remove_possible_method(name)
         
     | 
| 
      
 92 
     | 
    
         
            +
                        define_method(name) do
         
     | 
| 
      
 93 
     | 
    
         
            +
                          if instance_variable_defined? ivar
         
     | 
| 
      
 94 
     | 
    
         
            +
                            instance_variable_get ivar
         
     | 
| 
      
 95 
     | 
    
         
            +
                          else
         
     | 
| 
      
 96 
     | 
    
         
            +
                            singleton_class.send name
         
     | 
| 
      
 97 
     | 
    
         
            +
                          end
         
     | 
| 
      
 98 
     | 
    
         
            +
                        end
         
     | 
| 
      
 99 
     | 
    
         
            +
                      end
         
     | 
| 
      
 100 
     | 
    
         
            +
                    end
         
     | 
| 
      
 101 
     | 
    
         
            +
                    val
         
     | 
| 
      
 102 
     | 
    
         
            +
                  end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  if instance_reader
         
     | 
| 
      
 105 
     | 
    
         
            +
                    remove_possible_method name
         
     | 
| 
      
 106 
     | 
    
         
            +
                    define_method(name) do
         
     | 
| 
      
 107 
     | 
    
         
            +
                      if instance_variable_defined?(ivar)
         
     | 
| 
      
 108 
     | 
    
         
            +
                        instance_variable_get ivar
         
     | 
| 
      
 109 
     | 
    
         
            +
                      else
         
     | 
| 
      
 110 
     | 
    
         
            +
                        self.class.public_send name
         
     | 
| 
      
 111 
     | 
    
         
            +
                      end
         
     | 
| 
      
 112 
     | 
    
         
            +
                    end
         
     | 
| 
      
 113 
     | 
    
         
            +
                    define_method("#{name}?") { !!public_send(name) } if instance_predicate
         
     | 
| 
      
 114 
     | 
    
         
            +
                  end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  attr_writer name if instance_writer
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
              end
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
              private
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                unless respond_to?(:singleton_class?)
         
     | 
| 
      
 123 
     | 
    
         
            +
                  def singleton_class?
         
     | 
| 
      
 124 
     | 
    
         
            +
                    ancestors.first != self
         
     | 
| 
      
 125 
     | 
    
         
            +
                  end
         
     | 
| 
      
 126 
     | 
    
         
            +
                end
         
     | 
| 
      
 127 
     | 
    
         
            +
            end
         
     |