server_component 0.1.0
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/.circleci/config.yml +42 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.rubocop.yml +46 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +19 -0
- data/README.md +108 -0
- data/Rakefile +12 -0
- data/app/controllers/server_component/base_component_controller.rb +95 -0
- data/app/controllers/server_component/component_routers_controller.rb +27 -0
- data/app/controllers/server_component/components_controller.rb +35 -0
- data/app/helpers/server_component_helper.rb +30 -0
- data/bin/rails +9 -0
- data/bin/webpack +4 -0
- data/config/routes.rb +6 -0
- data/lib/generators/server_component/component_controller_generator.rb +28 -0
- data/lib/generators/server_component/install_generator.rb +31 -0
- data/lib/generators/templates/AFTER_INSTALL +45 -0
- data/lib/generators/templates/api_component_router.rb +3 -0
- data/lib/generators/templates/component_controller.rb.tt +5 -0
- data/lib/generators/templates/server_component.rb +64 -0
- data/lib/server_component.rb +29 -0
- data/lib/server_component/component_router.rb +58 -0
- data/lib/server_component/engine.rb +7 -0
- data/lib/server_component/js_function_builder.rb +0 -0
- data/lib/server_component/jsrb_handler.rb +10 -0
- data/lib/server_component/railtie.rb +17 -0
- data/lib/server_component/version.rb +5 -0
- data/server_component.gemspec +40 -0
- metadata +152 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: dba7844e0d4e1ca570d77659d7ef3eea346900fc8ab9e84afef4dba723bf8113
         | 
| 4 | 
            +
              data.tar.gz: 8d331e9937dfc21a5f281724831a18ab9c56dc6168b4df3dc0ca398bea09d9dd
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: a70a74596bbf8482aa244ed247bf04a8a412318c2aed0e8533c19715c9551a55099245bf8c7b93d02b5ebfd21b505c07734a655bb951dab25a9dcfc73df29796
         | 
| 7 | 
            +
              data.tar.gz: 963688b759513463ef25f378c074830ec2e83710b1465a16ee1a5b31fc495eeabb3a798c3560dd405d58409d05a0747fab5e451ab3c38b0c3b5ea80b490377e7
         | 
| @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            # Ruby CircleCI 2.0 configuration file
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # Check https://circleci.com/docs/2.0/language-ruby/ for more details
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            version: 2
         | 
| 6 | 
            +
            jobs:
         | 
| 7 | 
            +
              build:
         | 
| 8 | 
            +
                docker:
         | 
| 9 | 
            +
                  - image: circleci/ruby:2.5.1-node-browsers
         | 
| 10 | 
            +
                working_directory: ~/repo
         | 
| 11 | 
            +
                steps:
         | 
| 12 | 
            +
                  - checkout
         | 
| 13 | 
            +
                  - run:
         | 
| 14 | 
            +
                      name: install dependencies
         | 
| 15 | 
            +
                      working_directory: ~/repo
         | 
| 16 | 
            +
                      command: |
         | 
| 17 | 
            +
                        bundle install --jobs=4 --retry=3 --path vendor/bundle
         | 
| 18 | 
            +
                  - run:
         | 
| 19 | 
            +
                      name: install binstubs
         | 
| 20 | 
            +
                      working_directory: ~/repo
         | 
| 21 | 
            +
                      command: |
         | 
| 22 | 
            +
                        bundle exec rake app:update:bin webpacker:binstubs
         | 
| 23 | 
            +
                  - run:
         | 
| 24 | 
            +
                      name: install dependencies
         | 
| 25 | 
            +
                      working_directory: ~/repo/spec/dummy
         | 
| 26 | 
            +
                      command: |
         | 
| 27 | 
            +
                        yarn install
         | 
| 28 | 
            +
                  - run:
         | 
| 29 | 
            +
                      name: run tests
         | 
| 30 | 
            +
                      working_directory: ~/repo
         | 
| 31 | 
            +
                      command: |
         | 
| 32 | 
            +
                        bundle exec rspec
         | 
| 33 | 
            +
                  - run:
         | 
| 34 | 
            +
                      name: run rubocop
         | 
| 35 | 
            +
                      working_directory: ~/repo
         | 
| 36 | 
            +
                      command: |
         | 
| 37 | 
            +
                        bundle exec rubocop
         | 
| 38 | 
            +
                  - run:
         | 
| 39 | 
            +
                      name: report coverage
         | 
| 40 | 
            +
                      working_directory: ~/repo
         | 
| 41 | 
            +
                      command: |
         | 
| 42 | 
            +
                        bash <(curl -s https://codecov.io/bash) -f coverage/.resultset.json
         | 
    
        data/.gitignore
    ADDED
    
    
    
        data/.rspec
    ADDED
    
    
    
        data/.rubocop.yml
    ADDED
    
    | @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            AllCops:
         | 
| 2 | 
            +
              Exclude:
         | 
| 3 | 
            +
                - 'lib/generators/templates/**/*'
         | 
| 4 | 
            +
                - 'tmp/**/*'
         | 
| 5 | 
            +
                - 'bin/*'
         | 
| 6 | 
            +
                - 'spec/dummy/bin/**/*'
         | 
| 7 | 
            +
                - 'spec/dummy/node_modules/**/*'
         | 
| 8 | 
            +
                - 'vendor/**/*'
         | 
| 9 | 
            +
              TargetRubyVersion: 2.5
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            Metrics/LineLength:
         | 
| 12 | 
            +
              Max: 130
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            Metrics/MethodLength:
         | 
| 15 | 
            +
              Max: 30
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            Metrics/AbcSize:
         | 
| 18 | 
            +
              Max: 25
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            Metrics/ClassLength:
         | 
| 21 | 
            +
              Max: 200
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            Style/ClassVars:
         | 
| 24 | 
            +
              Enabled: false
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            Style/MissingRespondToMissing:
         | 
| 27 | 
            +
              Enabled: false
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            Style/GuardClause:
         | 
| 30 | 
            +
              Enabled: false
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            Naming/MemoizedInstanceVariableName:
         | 
| 33 | 
            +
              EnforcedStyleForLeadingUnderscores: optional
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            Style/Documentation:
         | 
| 36 | 
            +
              Enabled: false
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            Style/AccessModifierDeclarations:
         | 
| 39 | 
            +
              Enabled: false
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            Style/NumericPredicate:
         | 
| 42 | 
            +
              Enabled: false
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            Metrics/BlockLength:
         | 
| 45 | 
            +
              Exclude:
         | 
| 46 | 
            +
                - 'spec/**/*'
         | 
    
        data/.ruby-version
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            2.5.1
         | 
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    | @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            source 'https://rubygems.org'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # Specify your gem's dependencies in server_component.gemspec
         | 
| 6 | 
            +
            gemspec
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            gem 'execjs'
         | 
| 9 | 
            +
            gem 'stitch-rb'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            group :development, :test do
         | 
| 12 | 
            +
              gem 'capybara', '~> 2.18.0'
         | 
| 13 | 
            +
              gem 'pry-byebug'
         | 
| 14 | 
            +
              gem 'rspec-rails', '~> 3.8'
         | 
| 15 | 
            +
              gem 'rubocop'
         | 
| 16 | 
            +
              gem 'selenium-webdriver'
         | 
| 17 | 
            +
              gem 'simplecov'
         | 
| 18 | 
            +
              gem 'webpacker', '4.0.0.rc.2'
         | 
| 19 | 
            +
            end
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,108 @@ | |
| 1 | 
            +
            [](https://circleci.com/gh/effective-spa/server_component_rails) [](https://codecov.io/gh/effective-spa/server_component_rails) [](https://codeclimate.com/github/effective-spa/server_component_rails/maintainability)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # ServerComponent
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ServerComponent makes it possible to implement React component as Rails controller.
         | 
| 6 | 
            +
            This gem is designed to be used with [server_component](https://github.com/effective-spa/server_component) NPM package.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            ## Installation
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            Add this line to your application's Gemfile and run `bundle install`:
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            ```ruby
         | 
| 13 | 
            +
            gem 'server_component'
         | 
| 14 | 
            +
            ```
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            Run this command to initialize configuration file and base classes.
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            ```sh
         | 
| 19 | 
            +
            $ rails generate server_component:install
         | 
| 20 | 
            +
            ```
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            ## Getting Started
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            Add a new component controller:
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            ```rb
         | 
| 27 | 
            +
            class CounterComponentController < ServerComponent::ComponentController
         | 
| 28 | 
            +
              def self.initial_state
         | 
| 29 | 
            +
                {
         | 
| 30 | 
            +
                  count: 0
         | 
| 31 | 
            +
                }
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              def increment
         | 
| 35 | 
            +
                set_state do |s|
         | 
| 36 | 
            +
                  s.count { |prev| prev + 1 }
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              def decrement
         | 
| 41 | 
            +
                set_state do |s|
         | 
| 42 | 
            +
                  s.count { |prev| prev - 1 }
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| 46 | 
            +
            ```
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            Specify in a component router:
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            ```rb
         | 
| 51 | 
            +
            class ApiComponentRouter < ServerComponent::ComponentRouter
         | 
| 52 | 
            +
              component :counter
         | 
| 53 | 
            +
            end
         | 
| 54 | 
            +
            ```
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            In the client code (with Babel >= 7):
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            ```js
         | 
| 59 | 
            +
            import React, { Component } from 'react';
         | 
| 60 | 
            +
            import ReactDOM from 'react-dom';
         | 
| 61 | 
            +
            import ServerComponent, { server_component, consumer } from 'server_component';
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            @server_component('counter')
         | 
| 64 | 
            +
            class CounterContainer extends Component { }
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            @consumer('counter')
         | 
| 67 | 
            +
            class CounterBody extends Component {
         | 
| 68 | 
            +
              render() {
         | 
| 69 | 
            +
                const { increment, decrement, state: { count } } = this.props.counter;
         | 
| 70 | 
            +
                return (
         | 
| 71 | 
            +
                  <div>
         | 
| 72 | 
            +
                    <h1>Counter</h1>
         | 
| 73 | 
            +
                    <button onClick={increment}>increment</button>
         | 
| 74 | 
            +
                    <button onClick={decrement}>decrement</button>
         | 
| 75 | 
            +
                    <hr />
         | 
| 76 | 
            +
                    <div>Count: {counter}</div>
         | 
| 77 | 
            +
                  </div>
         | 
| 78 | 
            +
                );
         | 
| 79 | 
            +
              }
         | 
| 80 | 
            +
            }
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            class Main extends Component {
         | 
| 83 | 
            +
              render() {
         | 
| 84 | 
            +
                return (
         | 
| 85 | 
            +
                  <ServerComponent.Use at="/react" name="api">
         | 
| 86 | 
            +
                    <CounterContainer>
         | 
| 87 | 
            +
                      <CounterBody />
         | 
| 88 | 
            +
                    </CounterContainer>
         | 
| 89 | 
            +
                  </ServerComponent.Use>
         | 
| 90 | 
            +
                );
         | 
| 91 | 
            +
              }
         | 
| 92 | 
            +
            }
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            ReactDOM.render(<Main />, document.getElementById('root'));
         | 
| 95 | 
            +
            ```
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            ## API Documentation
         | 
| 98 | 
            +
             | 
| 99 | 
            +
            (TODO)
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            ## Contributing
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            Bug reports and pull requests are welcome on GitHub at https://github.com/effective-spa/server_component.
         | 
| 104 | 
            +
             | 
| 105 | 
            +
             | 
| 106 | 
            +
            ## License
         | 
| 107 | 
            +
             | 
| 108 | 
            +
            The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
         | 
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'bundler/gem_tasks'
         | 
| 4 | 
            +
            require 'rspec/core/rake_task'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            RSpec::Core::RakeTask.new(:spec)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            task default: :spec
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            # This let CI know tasks 'app:update:bin' and 'webpacker:binstubs'
         | 
| 11 | 
            +
            require_relative 'spec/dummy/config/application'
         | 
| 12 | 
            +
            Rails.application.load_tasks
         | 
| @@ -0,0 +1,95 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ServerComponent
         | 
| 4 | 
            +
              class FetcherConfigurator
         | 
| 5 | 
            +
                include ServerComponentHelper
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize(component_class, actions)
         | 
| 8 | 
            +
                  @component_class = component_class
         | 
| 9 | 
            +
                  @actions = actions
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def before
         | 
| 13 | 
            +
                  jsrb = Jsrb::Base.new
         | 
| 14 | 
            +
                  set_state(jsrb) do |s|
         | 
| 15 | 
            +
                    yield(s, jsrb.expr.context.data)
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
                  set_value(:start_function, jsrb.generate_code)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def accept_file!
         | 
| 21 | 
            +
                  set_value :upload, true
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def set_value(key, value)
         | 
| 25 | 
            +
                  @actions.each do |action|
         | 
| 26 | 
            +
                    @component_class.action_descriptors[action][key] = value
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              class BaseComponentController < ServerComponent.parent_controller.constantize
         | 
| 32 | 
            +
                class_attribute :initial_state, :action_on_mount
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                helper ServerComponentHelper
         | 
| 35 | 
            +
                include ServerComponentHelper
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                private
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def set_state(&block) # rubocop:disable Naming/AccessorMethodName
         | 
| 40 | 
            +
                  jsrb = Jsrb::Base.new
         | 
| 41 | 
            +
                  super(jsrb, &block)
         | 
| 42 | 
            +
                  render jsrb: jsrb.generate_code
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                class << self
         | 
| 46 | 
            +
                  def to_json
         | 
| 47 | 
            +
                    {
         | 
| 48 | 
            +
                      action_on_mount: action_on_mount,
         | 
| 49 | 
            +
                      initial_state: initial_state,
         | 
| 50 | 
            +
                      actions: action_descriptors
         | 
| 51 | 
            +
                    }
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  def action_descriptors
         | 
| 55 | 
            +
                    if instance_variable_defined?('@action_descriptors')
         | 
| 56 | 
            +
                      instance_variable_get '@action_descriptors'
         | 
| 57 | 
            +
                    else
         | 
| 58 | 
            +
                      h = {}
         | 
| 59 | 
            +
                      instance_variable_set '@action_descriptors', h
         | 
| 60 | 
            +
                      h
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  def action(*action_names, &block)
         | 
| 65 | 
            +
                    options = action_names.extract_options!
         | 
| 66 | 
            +
                    raise ArgumentError, 'specify at least one action!' if action_names.empty?
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    action_names.each do |action_name|
         | 
| 69 | 
            +
                      action_descriptors[action_name.to_sym] = {}
         | 
| 70 | 
            +
                    end
         | 
| 71 | 
            +
                    fetcher(*action_names, &block) if block
         | 
| 72 | 
            +
                    if options[:on_mount]
         | 
| 73 | 
            +
                      raise ArgumentError, 'on_mount option can accept only one action' if action_names.size > 1
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                      on_mount action_names.first
         | 
| 76 | 
            +
                    end
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  def on_mount(action)
         | 
| 80 | 
            +
                    self.action_on_mount = action
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  def fetcher(*actions)
         | 
| 84 | 
            +
                    configurator = FetcherConfigurator.new(self, actions.map(&:to_sym))
         | 
| 85 | 
            +
                    yield configurator
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  def before(*actions, &block)
         | 
| 89 | 
            +
                    fetcher(*actions) do |c|
         | 
| 90 | 
            +
                      c.before(&block)
         | 
| 91 | 
            +
                    end
         | 
| 92 | 
            +
                  end
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
            end
         | 
| @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ServerComponent
         | 
| 4 | 
            +
              class ComponentRoutersController < ServerComponent.parent_controller.constantize
         | 
| 5 | 
            +
                def show
         | 
| 6 | 
            +
                  component_router = find_component_router
         | 
| 7 | 
            +
                  render json: component_router.to_json
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                private
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def find_component_router
         | 
| 13 | 
            +
                  component_router_class_name = "#{name.camelize}ComponentRouter"
         | 
| 14 | 
            +
                  component_router_class =
         | 
| 15 | 
            +
                    begin
         | 
| 16 | 
            +
                      component_router_class_name.constantize
         | 
| 17 | 
            +
                    rescue NameError
         | 
| 18 | 
            +
                      raise ActionController::RoutingError, "No route matches routes/#{name}"
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                  component_router_class.new
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def name
         | 
| 24 | 
            +
                  params[:name]
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ServerComponent
         | 
| 4 | 
            +
              class ComponentsController < ServerComponent.parent_controller.constantize
         | 
| 5 | 
            +
                def perform
         | 
| 6 | 
            +
                  component_class = find_component_class!
         | 
| 7 | 
            +
                  component_class.dispatch(component_action, request, response)
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                private
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def find_component_class!
         | 
| 13 | 
            +
                  klass_name = "#{component_name.camelize}ComponentController"
         | 
| 14 | 
            +
                  klass =
         | 
| 15 | 
            +
                    begin
         | 
| 16 | 
            +
                      klass_name.constantize
         | 
| 17 | 
            +
                    rescue NameError
         | 
| 18 | 
            +
                      raise ActionController::RoutingError, "No route matches #{component_name}/#{component_action}"
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                  unless klass <= ServerComponent::BaseComponentController
         | 
| 21 | 
            +
                    raise ActionController::RoutingError, "No route matches #{component_name}/#{component_action}"
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  klass
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def component_name
         | 
| 28 | 
            +
                  params[:component_name]
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def component_action
         | 
| 32 | 
            +
                  params[:component_action_name]
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ServerComponentHelper
         | 
| 4 | 
            +
              class SetStateDSL
         | 
| 5 | 
            +
                def initialize(new_state, prev_state)
         | 
| 6 | 
            +
                  @new_state = new_state
         | 
| 7 | 
            +
                  @prev_state = prev_state
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                # rubocop:disable Style/MethodMissingSuper
         | 
| 11 | 
            +
                def method_missing(name, *args)
         | 
| 12 | 
            +
                  if (matches = name.to_s.match(/^(.+)=$/))
         | 
| 13 | 
            +
                    @new_state.member!(matches[1]).assign!(args[0]).as_statement!
         | 
| 14 | 
            +
                  elsif block_given?
         | 
| 15 | 
            +
                    block_result = yield @prev_state.member!(name)
         | 
| 16 | 
            +
                    @new_state.member!(name).assign!(block_result).as_statement!
         | 
| 17 | 
            +
                  else
         | 
| 18 | 
            +
                    @new_state.member!(name)
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
                # rubocop:enable Style/MethodMissingSuper
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def set_state(jsrb) # rubocop:disable Naming/AccessorMethodName
         | 
| 25 | 
            +
                new_state = jsrb.var! { {} }
         | 
| 26 | 
            +
                prev_state = jsrb.expr.component.state
         | 
| 27 | 
            +
                yield SetStateDSL.new(new_state, prev_state)
         | 
| 28 | 
            +
                jsrb.expr.component.setState.call(new_state).as_statement!
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
    
        data/bin/rails
    ADDED
    
    | @@ -0,0 +1,9 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # This is a manually created bin file.
         | 
| 4 | 
            +
            # Some webpacker tasks depend on the current directory,
         | 
| 5 | 
            +
            # which is fixed in https://github.com/rails/webpacker/pull/1475
         | 
| 6 | 
            +
            # but in webpacker 3.x, it's not fixed yet;)
         | 
| 7 | 
            +
            APP_PATH = File.expand_path('../spec/dummy/config/application', __dir__)
         | 
| 8 | 
            +
            require_relative '../spec/dummy/config/boot'
         | 
| 9 | 
            +
            require 'rails/commands'
         | 
    
        data/bin/webpack
    ADDED
    
    
    
        data/config/routes.rb
    ADDED
    
    
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ServerComponent
         | 
| 4 | 
            +
              module Generators
         | 
| 5 | 
            +
                class ComponentControllerGenerator < Rails::Generators::NamedBase
         | 
| 6 | 
            +
                  source_root File.expand_path('../templates', __dir__)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  desc 'Creates a ServerComponent initializer.'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def create_controller_file
         | 
| 11 | 
            +
                    template 'component_controller.rb', File.join('app/controllers', class_path, "#{file_name}_component_controller.rb")
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def component
         | 
| 15 | 
            +
                    rgx = /class [A-z::]+ComponentRouter < ServerComponent::ComponentRouter\n/
         | 
| 16 | 
            +
                    router_path = File.join('app/component_routers', "#{router_name}_component_router.rb")
         | 
| 17 | 
            +
                    routing_code = "  component '#{name}'\n"
         | 
| 18 | 
            +
                    inject_into_file router_path, routing_code, after: rgx
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  private
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def router_name
         | 
| 24 | 
            +
                    @options.fetch(:router, 'api')
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ServerComponent
         | 
| 4 | 
            +
              module Generators
         | 
| 5 | 
            +
                class InstallGenerator < Rails::Generators::Base
         | 
| 6 | 
            +
                  source_root File.expand_path('../templates', __dir__)
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  desc 'Creates a ServerComponent initializer.'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  def create_initializer_file
         | 
| 11 | 
            +
                    template 'server_component.rb', 'config/initializers/server_component.rb'
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def setup_route
         | 
| 15 | 
            +
                    route "mount ServerComponent::Engine, at: 'react'"
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def create_directory
         | 
| 19 | 
            +
                    empty_directory 'app/component_routers'
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  def add_one_router
         | 
| 23 | 
            +
                    template 'api_component_router.rb', 'app/component_routers/api_component_router.rb'
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def show_readme
         | 
| 27 | 
            +
                    readme 'AFTER_INSTALL' if behavior == :invoke
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            ===============================================================================
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            What's next:
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            1. Add "component_routers" directory into autoload_paths
         | 
| 6 | 
            +
               in config/application.rb
         | 
| 7 | 
            +
             | 
| 8 | 
            +
               config.autoload_paths << Rails.root.join('component_routers')
         | 
| 9 | 
            +
             | 
| 10 | 
            +
             | 
| 11 | 
            +
            2. Create component controller. If you want BookComponent for example, run:
         | 
| 12 | 
            +
             | 
| 13 | 
            +
               $ rails generate server_component:component_controller book --router api
         | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| 16 | 
            +
            3. Conjoin client application with `server_component`:
         | 
| 17 | 
            +
             | 
| 18 | 
            +
               // Create a component class.
         | 
| 19 | 
            +
             | 
| 20 | 
            +
               @ServerComponent.component('book')
         | 
| 21 | 
            +
               class BookContainer extends React.Component {}
         | 
| 22 | 
            +
             | 
| 23 | 
            +
               // Create a component-attached class.
         | 
| 24 | 
            +
             | 
| 25 | 
            +
               @ServerComponent.attach('book')
         | 
| 26 | 
            +
               class Book extends React.Component {
         | 
| 27 | 
            +
                 render() {
         | 
| 28 | 
            +
                   const { state: { list } } = this.props.book;
         | 
| 29 | 
            +
                   return (
         | 
| 30 | 
            +
                     <ul>
         | 
| 31 | 
            +
                       {list.map(book => <li>{book.title}</li>)}
         | 
| 32 | 
            +
                     </ul>
         | 
| 33 | 
            +
                   );
         | 
| 34 | 
            +
                 }
         | 
| 35 | 
            +
               }
         | 
| 36 | 
            +
             | 
| 37 | 
            +
               // And use in your root render function:
         | 
| 38 | 
            +
             | 
| 39 | 
            +
               <ServerComponent.Use at="/react" name="api">
         | 
| 40 | 
            +
                 <BookContainer>
         | 
| 41 | 
            +
                   <Book />
         | 
| 42 | 
            +
                 </BookContainer>
         | 
| 43 | 
            +
               </ServerComponent.Use>
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            ===============================================================================
         | 
| @@ -0,0 +1,64 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Use this hook to configure ServerComponent
         | 
| 4 | 
            +
            ServerComponent.setup do |config|
         | 
| 5 | 
            +
              # context_script is executed before response scripts.
         | 
| 6 | 
            +
              # It is useful if you want to add functions
         | 
| 7 | 
            +
              # invoked from JSRB renderer.
         | 
| 8 | 
            +
              # You can get identifiers from JSRB by calling
         | 
| 9 | 
            +
              #  `js.identifier_name` .
         | 
| 10 | 
            +
              # The combination of 'add_custom_chain' option will
         | 
| 11 | 
            +
              # make your JSRB code more readable.
         | 
| 12 | 
            +
              config.context_script = <<~JAVASCRIPT
         | 
| 13 | 
            +
                // Returns new object or array
         | 
| 14 | 
            +
                // updating a property by immediate value or updator
         | 
| 15 | 
            +
                // function in the specified path.
         | 
| 16 | 
            +
                // without side effect in the original.
         | 
| 17 | 
            +
                //
         | 
| 18 | 
            +
                // example:
         | 
| 19 | 
            +
                //   immutable_update({ foo: 1 }, 'foo', 2) => { foo: 2 }
         | 
| 20 | 
            +
                //
         | 
| 21 | 
            +
                var immutable_update = (function () {
         | 
| 22 | 
            +
                  function _is_array(target) {
         | 
| 23 | 
            +
                    return Object.prototype.toString.call(target) === '[object Array]';
         | 
| 24 | 
            +
                  }
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  function _is_object(target) {
         | 
| 27 | 
            +
                    return typeof target === 'object' && target !== null;
         | 
| 28 | 
            +
                  }
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  function _clone_array_or_object(target) {
         | 
| 31 | 
            +
                    if (_is_array(target)) {
         | 
| 32 | 
            +
                      return target.slice(0);
         | 
| 33 | 
            +
                    } else if (_is_object(target)) {
         | 
| 34 | 
            +
                      return Object(target);
         | 
| 35 | 
            +
                    } else {
         | 
| 36 | 
            +
                      throw 'Argument Error: target is neither object nor array';
         | 
| 37 | 
            +
                    }
         | 
| 38 | 
            +
                  }
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  function _clone_update_internal(obj, field, value) {
         | 
| 41 | 
            +
                    if (value instanceof Function) {
         | 
| 42 | 
            +
                      obj[field] = value(obj[field]);
         | 
| 43 | 
            +
                    } else {
         | 
| 44 | 
            +
                      obj[field] = value;
         | 
| 45 | 
            +
                    }
         | 
| 46 | 
            +
                  }
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  return function (target, field, updator) {
         | 
| 49 | 
            +
                    var clone = _clone_array_or_object(target);
         | 
| 50 | 
            +
                    _clone_update_internal(clone, field, updator);
         | 
| 51 | 
            +
                    return clone;
         | 
| 52 | 
            +
                  }
         | 
| 53 | 
            +
                })();
         | 
| 54 | 
            +
              JAVASCRIPT
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              # Adds functionality to JSRB DSL.
         | 
| 57 | 
            +
              # If you add 'func!' to 'some_func',
         | 
| 58 | 
            +
              # then `obj.func!(arg)` is equivalent to `js.some_func.(obj, arg)`
         | 
| 59 | 
            +
              # where `obj` is a chain instance in JSRB.
         | 
| 60 | 
            +
              config.add_custom_chain(:update!, :immutable_update)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              # Specify parent class of ServerComponent's controllers.
         | 
| 63 | 
            +
              # config.parent_controller = 'ApplicationController'
         | 
| 64 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'active_support/dependencies'
         | 
| 4 | 
            +
            require 'jsrb'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module ServerComponent
         | 
| 7 | 
            +
              autoload :VERSION, 'server_component/version'
         | 
| 8 | 
            +
              autoload :ComponentRouter, 'server_component/component_router'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              class NamespaceNotFound < StandardError; end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              mattr_accessor :parent_controller
         | 
| 13 | 
            +
              @@parent_controller = 'ApplicationController'
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def self.setup
         | 
| 16 | 
            +
                yield self
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              mattr_accessor :context_script
         | 
| 20 | 
            +
              @@context_script = ''
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              def self.add_custom_chain(name, function_name)
         | 
| 23 | 
            +
                Jsrb::ExprChain.add_custom_chain name, function_name
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
            end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            require 'server_component/engine'
         | 
| 28 | 
            +
            require 'server_component/jsrb_handler'
         | 
| 29 | 
            +
            require 'server_component/railtie' if defined?(Rails)
         | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ServerComponent
         | 
| 4 | 
            +
              class ComponentRouter
         | 
| 5 | 
            +
                class_attribute :_namespace
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def to_json
         | 
| 8 | 
            +
                  h = {}
         | 
| 9 | 
            +
                  h[:components] = components.each_with_object({}) do |component, json|
         | 
| 10 | 
            +
                    component_controller_class = find_component_controller_class(component)
         | 
| 11 | 
            +
                    json[component] = component_controller_class.to_json
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                  h[:context_script] = context_script
         | 
| 14 | 
            +
                  h
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def components
         | 
| 18 | 
            +
                  self.class.components
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def namespace
         | 
| 22 | 
            +
                  self.class._namespace
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def context_script
         | 
| 26 | 
            +
                  ServerComponent.context_script
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                protected
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def find_component_controller_class(component)
         | 
| 32 | 
            +
                  name = (namespace ? "#{namespace}/#{component}" : component).to_s
         | 
| 33 | 
            +
                  "#{name.camelize}ComponentController".constantize
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                class << self
         | 
| 37 | 
            +
                  def namespace(mod)
         | 
| 38 | 
            +
                    self._namespace = mod
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def components
         | 
| 42 | 
            +
                    if instance_variable_defined?('@components')
         | 
| 43 | 
            +
                      instance_variable_get '@components'
         | 
| 44 | 
            +
                    else
         | 
| 45 | 
            +
                      a = []
         | 
| 46 | 
            +
                      instance_variable_set '@components', a
         | 
| 47 | 
            +
                      a
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  def component(*component_names)
         | 
| 52 | 
            +
                    component_names.each do |name|
         | 
| 53 | 
            +
                      components << name.to_sym
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| 
            File without changes
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module ServerComponent
         | 
| 4 | 
            +
              class Railtie < ::Rails::Railtie
         | 
| 5 | 
            +
                initializer :server_component do
         | 
| 6 | 
            +
                  ActiveSupport.on_load :action_view do
         | 
| 7 | 
            +
                    ActionView::Template.register_template_handler :jsrb, JsrbHandler
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  ActiveSupport.on_load :action_controller do
         | 
| 11 | 
            +
                    ActionController::Renderers.add :jsrb do |obj, _options|
         | 
| 12 | 
            +
                      send_data obj.to_s, type: Mime[:js]
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            lib = File.expand_path('lib', __dir__)
         | 
| 4 | 
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 5 | 
            +
            require 'server_component/version'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Gem::Specification.new do |spec|
         | 
| 8 | 
            +
              spec.name          = 'server_component'
         | 
| 9 | 
            +
              spec.version       = ServerComponent::VERSION
         | 
| 10 | 
            +
              spec.authors       = ['Shun MIZUKAMI']
         | 
| 11 | 
            +
              spec.email         = ['norainu234@gmail.com']
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              spec.summary       = 'ServerComponent support for Rails'
         | 
| 14 | 
            +
              spec.description   = 'ServerComponent makes it possible to implement React component as Rails controller'
         | 
| 15 | 
            +
              spec.homepage      = 'https://github.com/effective-spa/server_component_rails'
         | 
| 16 | 
            +
              spec.license       = 'MIT'
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
         | 
| 19 | 
            +
              # to allow pushing to a single host or delete this section to allow pushing to any host.
         | 
| 20 | 
            +
              if spec.respond_to?(:metadata)
         | 
| 21 | 
            +
                spec.metadata['allowed_push_host'] = 'https://rubygems.org'
         | 
| 22 | 
            +
              else
         | 
| 23 | 
            +
                raise 'RubyGems 2.0 or newer is required to protect against ' \
         | 
| 24 | 
            +
                  'public gem pushes.'
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              spec.files = `git ls-files -z`.split("\x0").reject do |f|
         | 
| 28 | 
            +
                f.match(%r{^(test|spec|features)/})
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
              spec.bindir        = 'exe'
         | 
| 31 | 
            +
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         | 
| 32 | 
            +
              spec.require_paths = ['lib']
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              spec.add_runtime_dependency 'jsrb', '~> 0.1'
         | 
| 35 | 
            +
              spec.add_runtime_dependency 'rails', '~> 5.0', '>= 5.0.0'
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              spec.add_development_dependency 'bundler', '~> 1.13'
         | 
| 38 | 
            +
              spec.add_development_dependency 'rake', '~> 10.0'
         | 
| 39 | 
            +
              spec.add_development_dependency 'rspec', '~> 3.0'
         | 
| 40 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,152 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: server_component
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Shun MIZUKAMI
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: exe
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2019-01-09 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: jsrb
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '0.1'
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '0.1'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: rails
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '5.0'
         | 
| 34 | 
            +
                - - ">="
         | 
| 35 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 36 | 
            +
                    version: 5.0.0
         | 
| 37 | 
            +
              type: :runtime
         | 
| 38 | 
            +
              prerelease: false
         | 
| 39 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 40 | 
            +
                requirements:
         | 
| 41 | 
            +
                - - "~>"
         | 
| 42 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 43 | 
            +
                    version: '5.0'
         | 
| 44 | 
            +
                - - ">="
         | 
| 45 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 46 | 
            +
                    version: 5.0.0
         | 
| 47 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 48 | 
            +
              name: bundler
         | 
| 49 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 50 | 
            +
                requirements:
         | 
| 51 | 
            +
                - - "~>"
         | 
| 52 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 53 | 
            +
                    version: '1.13'
         | 
| 54 | 
            +
              type: :development
         | 
| 55 | 
            +
              prerelease: false
         | 
| 56 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 57 | 
            +
                requirements:
         | 
| 58 | 
            +
                - - "~>"
         | 
| 59 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 60 | 
            +
                    version: '1.13'
         | 
| 61 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 62 | 
            +
              name: rake
         | 
| 63 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 64 | 
            +
                requirements:
         | 
| 65 | 
            +
                - - "~>"
         | 
| 66 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 67 | 
            +
                    version: '10.0'
         | 
| 68 | 
            +
              type: :development
         | 
| 69 | 
            +
              prerelease: false
         | 
| 70 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 71 | 
            +
                requirements:
         | 
| 72 | 
            +
                - - "~>"
         | 
| 73 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 74 | 
            +
                    version: '10.0'
         | 
| 75 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 76 | 
            +
              name: rspec
         | 
| 77 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 78 | 
            +
                requirements:
         | 
| 79 | 
            +
                - - "~>"
         | 
| 80 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 81 | 
            +
                    version: '3.0'
         | 
| 82 | 
            +
              type: :development
         | 
| 83 | 
            +
              prerelease: false
         | 
| 84 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 85 | 
            +
                requirements:
         | 
| 86 | 
            +
                - - "~>"
         | 
| 87 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 88 | 
            +
                    version: '3.0'
         | 
| 89 | 
            +
            description: ServerComponent makes it possible to implement React component as Rails
         | 
| 90 | 
            +
              controller
         | 
| 91 | 
            +
            email:
         | 
| 92 | 
            +
            - norainu234@gmail.com
         | 
| 93 | 
            +
            executables: []
         | 
| 94 | 
            +
            extensions: []
         | 
| 95 | 
            +
            extra_rdoc_files: []
         | 
| 96 | 
            +
            files:
         | 
| 97 | 
            +
            - ".circleci/config.yml"
         | 
| 98 | 
            +
            - ".gitignore"
         | 
| 99 | 
            +
            - ".rspec"
         | 
| 100 | 
            +
            - ".rubocop.yml"
         | 
| 101 | 
            +
            - ".ruby-version"
         | 
| 102 | 
            +
            - ".travis.yml"
         | 
| 103 | 
            +
            - Gemfile
         | 
| 104 | 
            +
            - README.md
         | 
| 105 | 
            +
            - Rakefile
         | 
| 106 | 
            +
            - app/controllers/server_component/base_component_controller.rb
         | 
| 107 | 
            +
            - app/controllers/server_component/component_routers_controller.rb
         | 
| 108 | 
            +
            - app/controllers/server_component/components_controller.rb
         | 
| 109 | 
            +
            - app/helpers/server_component_helper.rb
         | 
| 110 | 
            +
            - bin/rails
         | 
| 111 | 
            +
            - bin/webpack
         | 
| 112 | 
            +
            - config/routes.rb
         | 
| 113 | 
            +
            - lib/generators/server_component/component_controller_generator.rb
         | 
| 114 | 
            +
            - lib/generators/server_component/install_generator.rb
         | 
| 115 | 
            +
            - lib/generators/templates/AFTER_INSTALL
         | 
| 116 | 
            +
            - lib/generators/templates/api_component_router.rb
         | 
| 117 | 
            +
            - lib/generators/templates/component_controller.rb.tt
         | 
| 118 | 
            +
            - lib/generators/templates/server_component.rb
         | 
| 119 | 
            +
            - lib/server_component.rb
         | 
| 120 | 
            +
            - lib/server_component/component_router.rb
         | 
| 121 | 
            +
            - lib/server_component/engine.rb
         | 
| 122 | 
            +
            - lib/server_component/js_function_builder.rb
         | 
| 123 | 
            +
            - lib/server_component/jsrb_handler.rb
         | 
| 124 | 
            +
            - lib/server_component/railtie.rb
         | 
| 125 | 
            +
            - lib/server_component/version.rb
         | 
| 126 | 
            +
            - server_component.gemspec
         | 
| 127 | 
            +
            homepage: https://github.com/effective-spa/server_component_rails
         | 
| 128 | 
            +
            licenses:
         | 
| 129 | 
            +
            - MIT
         | 
| 130 | 
            +
            metadata:
         | 
| 131 | 
            +
              allowed_push_host: https://rubygems.org
         | 
| 132 | 
            +
            post_install_message: 
         | 
| 133 | 
            +
            rdoc_options: []
         | 
| 134 | 
            +
            require_paths:
         | 
| 135 | 
            +
            - lib
         | 
| 136 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 137 | 
            +
              requirements:
         | 
| 138 | 
            +
              - - ">="
         | 
| 139 | 
            +
                - !ruby/object:Gem::Version
         | 
| 140 | 
            +
                  version: '0'
         | 
| 141 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 142 | 
            +
              requirements:
         | 
| 143 | 
            +
              - - ">="
         | 
| 144 | 
            +
                - !ruby/object:Gem::Version
         | 
| 145 | 
            +
                  version: '0'
         | 
| 146 | 
            +
            requirements: []
         | 
| 147 | 
            +
            rubyforge_project: 
         | 
| 148 | 
            +
            rubygems_version: 2.7.6
         | 
| 149 | 
            +
            signing_key: 
         | 
| 150 | 
            +
            specification_version: 4
         | 
| 151 | 
            +
            summary: ServerComponent support for Rails
         | 
| 152 | 
            +
            test_files: []
         |