action_component 0.1.2 → 0.1.3
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +5 -1
- data/lib/action_component.rb +10 -1
- data/lib/action_component/base.rb +6 -1
- data/lib/action_component/callbacks.rb +29 -0
- data/lib/action_component/element_builder.rb +64 -0
- data/lib/action_component/elements.rb +4 -0
- data/lib/action_component/version.rb +1 -1
- data/spec/action_component/base_spec.rb +1 -1
- data/spec/action_component/callbacks_spec.rb +38 -0
- data/spec/action_component/element_builder_spec.rb +53 -0
- data/spec/action_component/elements_spec.rb +6 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f33f7082a98706e560055f13359cde3c1047221
|
4
|
+
data.tar.gz: 71e05e1a88e06f812e0d8323713f71aaacea3f8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 73fb3c94cb8d6545196a41a63e75714e6bae851dbadf239ffa9b65c6a8bee22b2a73d0fed95d803be963d8028bf02fb42d2d00a8fc199074993feb9ded023879
|
7
|
+
data.tar.gz: 8152c4885c00c68a1dc7bb4fd99349b425350a7992a472925435e802ba8348543ea7fae7e5a76d7d7656a9a6eaee24893f9bc4b9348ca7b51b79aa1ebce68bce
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -86,6 +86,10 @@ class PostComponent < ActionComponent::Base
|
|
86
86
|
div(class: 'post') do
|
87
87
|
h2 @post.title
|
88
88
|
|
89
|
+
# This renders a div with a class of 'published-at'
|
90
|
+
# Note the underscore has been replaced with a dash.
|
91
|
+
e.div.published_at "Published at #{l @post.published_at}"
|
92
|
+
|
89
93
|
component AuthorComponent, author: @post.author
|
90
94
|
|
91
95
|
insert simple_format(@post.content)
|
@@ -97,7 +101,7 @@ end
|
|
97
101
|
## More documentation to come
|
98
102
|
|
99
103
|
ActionComponent is new. It works just fine, but at the moment if you need more information than is given above,
|
100
|
-
please dive into the (
|
104
|
+
please dive into the (small) codebase to learn more.
|
101
105
|
|
102
106
|
## Contributing
|
103
107
|
|
data/lib/action_component.rb
CHANGED
@@ -3,10 +3,19 @@ end
|
|
3
3
|
|
4
4
|
require 'action_component/version'
|
5
5
|
|
6
|
+
# Rails integration
|
7
|
+
|
6
8
|
require 'action_component/action_controller_rendering'
|
7
9
|
require 'action_component/action_view_rendering'
|
10
|
+
require 'action_component/railtie'
|
11
|
+
|
12
|
+
# Base dependencies
|
13
|
+
|
14
|
+
require 'action_component/callbacks'
|
8
15
|
require 'action_component/constraints'
|
9
16
|
require 'action_component/elements'
|
17
|
+
require 'action_component/element_builder'
|
18
|
+
|
19
|
+
# Base
|
10
20
|
|
11
21
|
require 'action_component/base'
|
12
|
-
require 'action_component/railtie'
|
@@ -8,13 +8,14 @@ module ActionComponent
|
|
8
8
|
class Base
|
9
9
|
include ActionComponent::Constraints
|
10
10
|
include ActionComponent::Elements
|
11
|
+
prepend ActionComponent::Callbacks
|
11
12
|
|
12
13
|
delegate :concat, to: :@_view
|
13
14
|
|
14
15
|
def self.render(view, opts = {})
|
15
16
|
component = new(view, opts)
|
16
17
|
component.load
|
17
|
-
component.
|
18
|
+
component.render_view
|
18
19
|
nil
|
19
20
|
end
|
20
21
|
|
@@ -35,6 +36,10 @@ module ActionComponent
|
|
35
36
|
raise ActionComponent::ViewMissingError, "#{self.class.name} must define a view method to be a valid component"
|
36
37
|
end
|
37
38
|
|
39
|
+
def render_view
|
40
|
+
view
|
41
|
+
end
|
42
|
+
|
38
43
|
private
|
39
44
|
|
40
45
|
def method_missing(method, *args, &block)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActionComponent
|
2
|
+
module Callbacks
|
3
|
+
def self.prepended(base)
|
4
|
+
base.class_attribute :before_render_callback_methods, :after_render_callback_methods
|
5
|
+
|
6
|
+
base.before_render_callback_methods = []
|
7
|
+
base.after_render_callback_methods = []
|
8
|
+
|
9
|
+
base.extend ClassMethods
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def before_render(*methods)
|
14
|
+
self.before_render_callback_methods += methods
|
15
|
+
end
|
16
|
+
|
17
|
+
def after_render(*methods)
|
18
|
+
self.after_render_callback_methods += methods
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_view
|
23
|
+
before_render_callback_methods.each { |method| send(method) }
|
24
|
+
result = super
|
25
|
+
after_render_callback_methods.each { |method| send(method) }
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module ActionComponent
|
2
|
+
class ElementBuilder
|
3
|
+
def initialize(base, element_name = nil, classes = nil, id = nil)
|
4
|
+
@base = base
|
5
|
+
@element_name = element_name
|
6
|
+
@classes = classes
|
7
|
+
@id = id
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(method, *args, &block)
|
11
|
+
element_name = @element_name
|
12
|
+
classes = @classes
|
13
|
+
id = @id
|
14
|
+
|
15
|
+
command = method.to_s
|
16
|
+
|
17
|
+
command = command[-1] == '?' ? command[0..-2] : command.gsub('_', '-')
|
18
|
+
|
19
|
+
if element_name
|
20
|
+
if command[-1] == '!'
|
21
|
+
id = command[0..-2]
|
22
|
+
else
|
23
|
+
classes = classes ? "#{classes} #{command}" : command
|
24
|
+
end
|
25
|
+
else
|
26
|
+
element_name = command
|
27
|
+
end
|
28
|
+
|
29
|
+
if !args.empty? || block
|
30
|
+
first, second = args
|
31
|
+
|
32
|
+
if second.is_a?(Hash)
|
33
|
+
build_options(classes, id, second)
|
34
|
+
elsif first.is_a?(Hash)
|
35
|
+
build_options(classes, id, first)
|
36
|
+
elsif first
|
37
|
+
second = build_options(classes, id)
|
38
|
+
else
|
39
|
+
first = build_options(classes, id)
|
40
|
+
end
|
41
|
+
|
42
|
+
@base.send(:element, element_name, first, second, &block)
|
43
|
+
else
|
44
|
+
self.class.new(@base, element_name, classes, id)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def build_options(classes, id, options = {})
|
51
|
+
if classes
|
52
|
+
if options[:class]
|
53
|
+
options[:class] = "#{options[:class]} #{classes}"
|
54
|
+
else
|
55
|
+
options[:class] = classes
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
options[:id] = id if id
|
60
|
+
|
61
|
+
options
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -10,7 +10,7 @@ RSpec.describe ActionComponent::Base do
|
|
10
10
|
it "makes a new component, then calls load and view, returning nil" do
|
11
11
|
component = instance_double(ActionComponent::Base)
|
12
12
|
expect(component).to receive(:load).ordered
|
13
|
-
expect(component).to receive(:
|
13
|
+
expect(component).to receive(:render_view).ordered
|
14
14
|
|
15
15
|
expect(ActionComponent::Base).to receive(:new)
|
16
16
|
.with(view, {option: 'value'})
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ActionComponent::Callbacks do
|
4
|
+
class FakeComponent
|
5
|
+
prepend ActionComponent::Callbacks
|
6
|
+
|
7
|
+
before_render :test1
|
8
|
+
before_render :test2
|
9
|
+
after_render :test3
|
10
|
+
|
11
|
+
def test1
|
12
|
+
end
|
13
|
+
|
14
|
+
def test2
|
15
|
+
end
|
16
|
+
|
17
|
+
def test3
|
18
|
+
end
|
19
|
+
|
20
|
+
def view
|
21
|
+
end
|
22
|
+
|
23
|
+
def render_view
|
24
|
+
view
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
subject { FakeComponent.new }
|
29
|
+
|
30
|
+
it "calls the before and after callbacks" do
|
31
|
+
expect(subject).to receive(:test1).ordered
|
32
|
+
expect(subject).to receive(:test2).ordered
|
33
|
+
expect(subject).to receive(:view).ordered.and_return('result')
|
34
|
+
expect(subject).to receive(:test3).ordered
|
35
|
+
|
36
|
+
expect(subject.render_view).to eq 'result'
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ActionComponent::ElementBuilder do
|
4
|
+
class FakeBase
|
5
|
+
def element(*args, &block)
|
6
|
+
[*args, block]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:base) { FakeBase.new }
|
11
|
+
|
12
|
+
subject { ActionComponent::ElementBuilder.new(base) }
|
13
|
+
|
14
|
+
it "builds a simple element" do
|
15
|
+
expect(subject.simple("test")).to eq ['simple', 'test', {}, nil]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "builds an element with a class" do
|
19
|
+
expect(subject.simple.blue("test")).to eq ['simple', 'test', {class: 'blue'}, nil]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "builds an element with two classes" do
|
23
|
+
expect(subject.simple.blue.loud("test")).to eq ['simple', 'test', {class: 'blue loud'}, nil]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "builds an element with an id" do
|
27
|
+
expect(subject.simple.blue!("test")).to eq ['simple', 'test', {id: 'blue'}, nil]
|
28
|
+
end
|
29
|
+
|
30
|
+
it "converts underscores to dashes" do
|
31
|
+
expect(subject.simple.strong_blue("test")).to eq ['simple', 'test', {class: 'strong-blue'}, nil]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "does not convert underscores to dashes if the method ends in a ?" do
|
35
|
+
expect(subject.simple.strong_blue?("test")).to eq ['simple', 'test', {class: 'strong_blue'}, nil]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "merges classes with ones specified in the hash" do
|
39
|
+
expect(subject.simple.blue("test", testy: "very", class: "strong")).to eq ['simple', 'test', {testy: "very", class: 'strong blue'}, nil]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "passes just a block" do
|
43
|
+
block = -> {}
|
44
|
+
|
45
|
+
expect(subject.simple.blue(&block)).to eq ['simple', {class: 'blue'}, nil, block]
|
46
|
+
end
|
47
|
+
|
48
|
+
it "passes a block with a hash" do
|
49
|
+
block = -> {}
|
50
|
+
|
51
|
+
expect(subject.simple.blue(testy: "very", &block)).to eq ['simple', {testy: "very", class: 'blue'}, nil, block]
|
52
|
+
end
|
53
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: action_component
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roger Nesbitt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-11-
|
11
|
+
date: 2016-11-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionpack
|
@@ -102,12 +102,16 @@ files:
|
|
102
102
|
- lib/action_component/action_controller_rendering.rb
|
103
103
|
- lib/action_component/action_view_rendering.rb
|
104
104
|
- lib/action_component/base.rb
|
105
|
+
- lib/action_component/callbacks.rb
|
105
106
|
- lib/action_component/constraints.rb
|
107
|
+
- lib/action_component/element_builder.rb
|
106
108
|
- lib/action_component/elements.rb
|
107
109
|
- lib/action_component/railtie.rb
|
108
110
|
- lib/action_component/version.rb
|
109
111
|
- spec/action_component/base_spec.rb
|
112
|
+
- spec/action_component/callbacks_spec.rb
|
110
113
|
- spec/action_component/constraints_spec.rb
|
114
|
+
- spec/action_component/element_builder_spec.rb
|
111
115
|
- spec/action_component/elements_spec.rb
|
112
116
|
- spec/fake_view.rb
|
113
117
|
- spec/spec_helper.rb
|
@@ -137,7 +141,9 @@ specification_version: 4
|
|
137
141
|
summary: React-style components for Rails
|
138
142
|
test_files:
|
139
143
|
- spec/action_component/base_spec.rb
|
144
|
+
- spec/action_component/callbacks_spec.rb
|
140
145
|
- spec/action_component/constraints_spec.rb
|
146
|
+
- spec/action_component/element_builder_spec.rb
|
141
147
|
- spec/action_component/elements_spec.rb
|
142
148
|
- spec/fake_view.rb
|
143
149
|
- spec/spec_helper.rb
|