action_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/.gitignore +1 -0
- data/README.md +87 -0
- data/action_component.gemspec +24 -0
- data/lib/action_component.rb +8 -0
- data/lib/action_component/action_controller_rendering.rb +21 -0
- data/lib/action_component/action_view_rendering.rb +7 -0
- data/lib/action_component/base.rb +107 -0
- data/lib/action_component/railtie.rb +15 -0
- data/lib/action_component/version.rb +3 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 743d176be9df1da38d3b0aa1b4609505ea8de03a
|
4
|
+
data.tar.gz: 7be1460ea0d7b0f68e58bb90a70ec78ff8ee6013
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 92ba9a92079dc33beaac95607f98dcad316b559540dfcc54be48cec5a7bb3f4759cf283fd8af3292fcc8e914777dfa77b36fd9be0ce397432d64ea5e565dba1c
|
7
|
+
data.tar.gz: 7e540ab4fc1fd22440286c3e1bee0293e1f069f7c2f59fe03afb90851e738d9148202374260d0dc661dfc1596bde57625b3fb7cc110abf51699a5026b7b9d685
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# ActionComponent
|
2
|
+
|
3
|
+
A React-style component system for Ruby on Rails.
|
4
|
+
|
5
|
+
This gem should be considered "alpha" as it currently has no tests.
|
6
|
+
|
7
|
+
## Examples
|
8
|
+
|
9
|
+
### Example 1: Integrating components into a standard Rails app
|
10
|
+
|
11
|
+
```html+erb
|
12
|
+
<!-- app/views/posts/show.html.erb -->
|
13
|
+
|
14
|
+
<div class="post">
|
15
|
+
<h2><%= @post.title %></h2>
|
16
|
+
<%= render_component AuthorComponent, author: @post.author %>
|
17
|
+
|
18
|
+
<%= simple_format @post.content %>
|
19
|
+
</div>
|
20
|
+
```
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
# app/components/author_component.rb
|
24
|
+
|
25
|
+
class AuthorComponent < ActionComponent::Base
|
26
|
+
def load
|
27
|
+
@post_count = @author.posts.published.count
|
28
|
+
end
|
29
|
+
|
30
|
+
def view
|
31
|
+
div(class: 'author') do
|
32
|
+
insert image_tag(@author, alt: @author.name)
|
33
|
+
|
34
|
+
div link_to(@author.name, @author), class: 'name'
|
35
|
+
|
36
|
+
div pluralize(@post_count, 'post'), class: 'post-count'
|
37
|
+
|
38
|
+
stars
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def stars
|
43
|
+
div class: 'stars' do
|
44
|
+
@author.stars.times { span "*" }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
### Example 2: Using components instead of views
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
# app/controllers/posts_controller.rb
|
54
|
+
|
55
|
+
class PostsController < ApplicationController
|
56
|
+
def show
|
57
|
+
post = Post.find(params[:id])
|
58
|
+
|
59
|
+
render_component PostComponent, post: post
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
# app/components/post_component.rb
|
66
|
+
|
67
|
+
class PostComponent < ActionComponent::Base
|
68
|
+
def view
|
69
|
+
div(class: 'post') do
|
70
|
+
h2(@post.title)
|
71
|
+
|
72
|
+
component AuthorComponent, author: @post.author
|
73
|
+
|
74
|
+
insert simple_format(@post.content)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
## Contributing
|
81
|
+
|
82
|
+
Pull requests welcome! If you're thinking of contributing a new feature, or
|
83
|
+
significantly changing an existing feature, please propose it as an issue.
|
84
|
+
|
85
|
+
## Licence
|
86
|
+
|
87
|
+
MIT. Copyright Roger Nesbitt.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
require "action_component/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "action_component"
|
7
|
+
s.version = ActionComponent::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.licenses = ['MIT']
|
10
|
+
s.authors = ["Roger Nesbitt"]
|
11
|
+
s.email = ["roger@seriousorange.com"]
|
12
|
+
s.homepage = "https://github.com/mogest/action_component"
|
13
|
+
s.summary = %q{React-style components for Rails}
|
14
|
+
s.description = %q{React-style components for Rails, mixing together the controller and a DSL language for HTML views.}
|
15
|
+
|
16
|
+
s.add_dependency "actionpack", ">= 4"
|
17
|
+
s.add_dependency "activesupport", ">= 4"
|
18
|
+
|
19
|
+
s.add_development_dependency "rspec"
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ActionComponent
|
2
|
+
module ActionControllerRendering
|
3
|
+
private
|
4
|
+
|
5
|
+
def render_component(component_class, opts = {})
|
6
|
+
@_component_class = component_class
|
7
|
+
@_component_options = opts
|
8
|
+
|
9
|
+
render_opts = {
|
10
|
+
inline: "<% render_component(@_component_class, @_component_options) %>",
|
11
|
+
layout: true
|
12
|
+
}
|
13
|
+
|
14
|
+
[:content_type, :layout, :location, :status, :formats].each do |option|
|
15
|
+
render_opts[option] = opts[option] if opts.member?(option)
|
16
|
+
end
|
17
|
+
|
18
|
+
render render_opts
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module ActionComponent
|
2
|
+
RenderError = Class.new(StandardError)
|
3
|
+
|
4
|
+
ELEMENTS = %w(
|
5
|
+
html head title base link meta style
|
6
|
+
script noscript
|
7
|
+
body section nav article aside h1 h2 h3 h4 h5 h6 hgroup header footer address
|
8
|
+
p hr br pre blockquote ol ul li dl dt dd figure figcaption div
|
9
|
+
a em strong small s cite q dfn abbr time code var samp kbd sub sup i b u mark rt rp bdi bdo span
|
10
|
+
ins del
|
11
|
+
img iframe embed object param video audio source track canvas map area
|
12
|
+
table caption colgroup col tbody thead tfoot tr td th
|
13
|
+
form fieldset legend label input button select datalist optgroup option textarea keygen output progress meter
|
14
|
+
details summary command menu
|
15
|
+
)
|
16
|
+
|
17
|
+
class Base
|
18
|
+
delegate :concat, to: :@_view
|
19
|
+
|
20
|
+
def self.define_tags(*element_names)
|
21
|
+
element_names.each do |element_name|
|
22
|
+
define_method(element_name) do |*args, &block|
|
23
|
+
element(element_name, *args, &block)
|
24
|
+
end
|
25
|
+
|
26
|
+
private element_name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
define_tags *ActionComponent::ELEMENTS
|
31
|
+
|
32
|
+
def self.render(view, opts = {})
|
33
|
+
component = new(view, opts)
|
34
|
+
component.load
|
35
|
+
component.view
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(view, opts = {})
|
39
|
+
opts.each do |key, value|
|
40
|
+
instance_variable_set("@#{key}", value)
|
41
|
+
end
|
42
|
+
|
43
|
+
@_view = view
|
44
|
+
end
|
45
|
+
|
46
|
+
def load
|
47
|
+
end
|
48
|
+
|
49
|
+
def view
|
50
|
+
raise "#{self.class.name} must define a view method to be a valid component"
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def method_missing(method, *args, &block)
|
56
|
+
if @_view.respond_to?(method)
|
57
|
+
@_view.send(method, *args, &block)
|
58
|
+
else
|
59
|
+
super
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def render(*args)
|
64
|
+
@_view.concat(@_view.render(*args))
|
65
|
+
end
|
66
|
+
|
67
|
+
def component(component, opts = {})
|
68
|
+
self.class.render(@_view, opts)
|
69
|
+
end
|
70
|
+
|
71
|
+
alias_method :render_component, :component
|
72
|
+
|
73
|
+
def text(content)
|
74
|
+
@_view.concat content
|
75
|
+
end
|
76
|
+
|
77
|
+
alias_method :text_node, :text
|
78
|
+
alias_method :insert, :text
|
79
|
+
|
80
|
+
def doctype(text = "html")
|
81
|
+
@_view.concat("<!doctype #{h(text)}>".html_safe)
|
82
|
+
end
|
83
|
+
|
84
|
+
def element(name, first = nil, second = nil, &block)
|
85
|
+
if first.is_a?(Hash)
|
86
|
+
opts = first
|
87
|
+
else
|
88
|
+
opts = second
|
89
|
+
text = first
|
90
|
+
end
|
91
|
+
|
92
|
+
output = if text && block
|
93
|
+
raise ActionComponent::RenderError, "An element cannot have both text and a block supplied; choose one or the other"
|
94
|
+
elsif text
|
95
|
+
@_view.content_tag name, text, opts
|
96
|
+
elsif block
|
97
|
+
@_view.content_tag name, opts, &block
|
98
|
+
else
|
99
|
+
@_view.tag name, opts
|
100
|
+
end
|
101
|
+
|
102
|
+
@_view.concat(output)
|
103
|
+
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActionComponent
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer "action_component.add_to_action_controller" do
|
4
|
+
ActiveSupport.on_load(:action_controller) do
|
5
|
+
include ActionComponent::ActionControllerRendering
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
initializer "action_component.add_to_action_view" do
|
10
|
+
ActiveSupport.on_load(:action_view) do
|
11
|
+
include ActionComponent::ActionViewRendering
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: action_component
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roger Nesbitt
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: actionpack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: React-style components for Rails, mixing together the controller and
|
56
|
+
a DSL language for HTML views.
|
57
|
+
email:
|
58
|
+
- roger@seriousorange.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- README.md
|
65
|
+
- action_component.gemspec
|
66
|
+
- lib/action_component.rb
|
67
|
+
- lib/action_component/action_controller_rendering.rb
|
68
|
+
- lib/action_component/action_view_rendering.rb
|
69
|
+
- lib/action_component/base.rb
|
70
|
+
- lib/action_component/railtie.rb
|
71
|
+
- lib/action_component/version.rb
|
72
|
+
homepage: https://github.com/mogest/action_component
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.5.1
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: React-style components for Rails
|
96
|
+
test_files: []
|