Skip to content

Create render_react_component controller helper #118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ react_component('HelloMessage', {name: 'John'}, {id: 'hello', class: 'foo', tag:
# <span class="foo" id="hello" data-...></span>
```

### Controller helper

There is also a controller helper `render_react_component` which is included so that you can specify a component as your view instead of an extra view file that only uses the `react_component` view helper.

```ruby
class TodoController < ApplicationController
def show
todos = Todos.all
render_react_component 'TodoList', { todos: todos }, prerender: true
end
```

#### With JSON and Jbuilder

You can pass prepared JSON directly to the helper, as well.
Expand Down
1 change: 1 addition & 0 deletions lib/react/rails.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require 'react/rails/railtie'
require 'react/rails/engine'
require 'react/rails/controller_helper'
require 'react/rails/view_helper'
26 changes: 26 additions & 0 deletions lib/react/rails/controller_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module React
module Rails
module ControllerHelper

# Render a React component as the view instead of
# a template from the app/views folder.
#
def render_react_component(name, args = {}, options = {}, &block)
__render_react_component_args = {
inline: '<%= react_component(*@__react_component_args, &@__react_component_block) %>',
layout: options.delete(:layout) || _layout.virtual_path
}

if status = options.delete(:status)
__render_react_component_args.merge!(status: status)
end

@__react_component_args = [name, args, options]
@__react_component_block = block

render __render_react_component_args
end

end
end
end
7 changes: 7 additions & 0 deletions lib/react/rails/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ class Railtie < ::Rails::Railtie
end
end

# Include the react-rails controller helper lazily
initializer "react_rails.setup_controller_helpers" do
ActiveSupport.on_load(:action_controller) do
include ::React::Rails::ControllerHelper
end
end

# run after all initializers to allow sprockets to pick up react.js and
# jsxtransformer.js from end-user to override ours if needed
initializer "react_rails.setup_vendor", :after => "sprockets.environment", group: :all do |app|
Expand Down
26 changes: 26 additions & 0 deletions test/controller_helper_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require 'test_helper'
require 'support/setup_capybara'

class ControllerHelperTest < ActionDispatch::IntegrationTest
include Capybara::DSL

setup do
@helper = ActionView::Base.new.extend(React::Rails::ViewHelper)
Capybara.current_driver = Capybara.javascript_driver
end

test 'uses a custom layout and status' do
get '/helper/1'

assert response.status == 218
assert response.body.include?('This is a different layout')
end

test 'renders the React component' do
get '/helper/1'

%w(data-react-class="Foo" data-react-props="{&quot;bar&quot;:&quot;value&quot;}").each do |segment|
assert response.body.include?(segment)
end
end
end
6 changes: 6 additions & 0 deletions test/dummy/app/controllers/helper_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class HelperController < ApplicationController
def show
@todos = %w{todo1 todo2 todo3}
render_react_component "Foo", {:bar => 'value'}, layout: 'custom', status: 218
end
end
15 changes: 15 additions & 0 deletions test/dummy/app/views/layouts/custom.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Dummy</title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body>

This is a different layout
<%= yield %>

</body>
</html>
1 change: 1 addition & 0 deletions test/dummy/config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Dummy::Application.routes.draw do
resources :pages, :only => [:show]
resources :server, :only => [:show]
resources :helper, :only => [:show]
end
13 changes: 13 additions & 0 deletions test/support/setup_capybara.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require 'capybara/rails'
require 'capybara/poltergeist'

Capybara.javascript_driver = :poltergeist
Capybara.app = Rails.application

# Useful for debugging.
# Just put page.driver.debug in your test and it will
# pause and throw up a browser
Capybara.register_driver :poltergeist_debug do |app|
Capybara::Poltergeist::Driver.new(app, :inspector => true)
end
Capybara.javascript_driver = :poltergeist_debug
15 changes: 1 addition & 14 deletions test/view_helper_test.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
require 'test_helper'

require 'capybara/rails'
require 'capybara/poltergeist'

Capybara.javascript_driver = :poltergeist
Capybara.app = Rails.application

# Useful for debugging.
# Just put page.driver.debug in your test and it will
# pause and throw up a browser
Capybara.register_driver :poltergeist_debug do |app|
Capybara::Poltergeist::Driver.new(app, :inspector => true)
end
Capybara.javascript_driver = :poltergeist_debug
require 'support/setup_capybara'

class ViewHelperTest < ActionDispatch::IntegrationTest
include Capybara::DSL
Expand Down