rafters 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +4 -3
- data/lib/rafters/component.rb +12 -18
- data/lib/rafters/component_context.rb +10 -10
- data/lib/rafters/component_renderer.rb +2 -4
- data/lib/rafters/version.rb +1 -1
- data/rafters.gemspec +1 -0
- data/spec/dummy/app/components/post/views/post_component.html.erb +1 -1
- data/spec/dummy/app/components/posts/views/posts_component.html.erb +1 -1
- data/spec/dummy/app/views/posts/index.html.erb +3 -3
- data/spec/rafters/component_context_spec.rb +4 -11
- data/spec/rafters/component_renderer_spec.rb +0 -7
- data/spec/rafters/component_spec.rb +11 -11
- data/spec/spec_helper.rb +8 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46aa108c7fdb1430b81316137e96b4597788c632
|
4
|
+
data.tar.gz: 40bc5436d5e593f804b3d31bedc38a425ac73a79
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 750fa198c767793cfec5e397b060ae88fbab408b28b3617827e6f25cf50618fdd2d6d733dc34dcbba42c4016397099f0316ce1d7ed15c571234e100413f2e491
|
7
|
+
data.tar.gz: 65f55f6c3c41678d035a9e1520f848a7f9ede30a34a81390a7686e26ca870944fd37fedc59a61d90d319c6b43f983e8bb610affa04a5d17c128b11dc9ef43700
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
[![Build Status](https://travis-ci.org/andyhite/rafters.png?branch=master)](https://travis-ci.org/andyhite/rafters)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/rafters.png)](http://badge.fury.io/rb/rafters)
|
5
5
|
[![Code Climate](https://codeclimate.com/github/andyhite/rafters.png)](https://codeclimate.com/github/andyhite/rafters)
|
6
|
+
[![Coverage Status](https://coveralls.io/repos/andyhite/rafters/badge.png)](https://coveralls.io/r/andyhite/rafters)
|
6
7
|
|
7
8
|
Rafters lets you think about each page of your application as a collection of small pieces instead of monolithic, difficult to maintain
|
8
9
|
views.
|
@@ -61,12 +62,12 @@ The two most important files generated above are `app/rafters/[name]/[name]_comp
|
|
61
62
|
|
62
63
|
### Rendering a component
|
63
64
|
|
64
|
-
You can render components anywhere - in your view, in your controller, in another component, etc. - but the most common place will (obviously) be in your views. To render a component, call `render_component
|
65
|
+
You can render components anywhere - in your view, in your controller, in another component, etc. - but the most common place will (obviously) be in your views. To render a component, call `render_component :component_name, as: "unique-identifier"` in one of your app views. For example:
|
65
66
|
|
66
67
|
```erb
|
67
68
|
...
|
68
69
|
<div class="main">
|
69
|
-
<%= render_component :heading %>
|
70
|
+
<%= render_component :heading, as: "page-heading" %>
|
70
71
|
</div>
|
71
72
|
...
|
72
73
|
```
|
@@ -147,7 +148,7 @@ Setting values are specified when rendering a component:
|
|
147
148
|
```erb
|
148
149
|
...
|
149
150
|
<div class="main">
|
150
|
-
<%= render_component :posts, published: true %>
|
151
|
+
<%= render_component :posts, as: "published-posts", settings: { published: true } %>
|
151
152
|
</div>
|
152
153
|
...
|
153
154
|
```
|
data/lib/rafters/component.rb
CHANGED
@@ -2,13 +2,17 @@ module Rafters::Component
|
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
4
|
attr_writer :controller
|
5
|
+
attr_reader :identifier
|
5
6
|
|
6
7
|
included do
|
7
|
-
|
8
|
+
attributes :settings, :identifier
|
8
9
|
end
|
9
10
|
|
10
|
-
def initialize(
|
11
|
-
|
11
|
+
def initialize(options = {})
|
12
|
+
raise IdentifierMissing unless options.has_key?(:as)
|
13
|
+
|
14
|
+
@identifier = options.delete(:as)
|
15
|
+
@settings = options.delete(:settings) || {}
|
12
16
|
end
|
13
17
|
|
14
18
|
def name(without_postfix = false)
|
@@ -16,10 +20,6 @@ module Rafters::Component
|
|
16
20
|
without_postfix ? _name.gsub(/_component/, '') : _name
|
17
21
|
end
|
18
22
|
|
19
|
-
def identifier
|
20
|
-
@identifier ||= "#{name}-#{random_identifier}"
|
21
|
-
end
|
22
|
-
|
23
23
|
def template_name
|
24
24
|
@_template_name ||= begin
|
25
25
|
_template_name = (self.class._template_name || self.class.name.underscore)
|
@@ -43,7 +43,7 @@ module Rafters::Component
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def settings
|
46
|
-
@_settings ||= Hashie::Mash.new(@settings.
|
46
|
+
@_settings ||= Hashie::Mash.new(defaults.merge(@settings).merge(overrides))
|
47
47
|
end
|
48
48
|
|
49
49
|
def defaults
|
@@ -55,8 +55,10 @@ module Rafters::Component
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def overrides
|
58
|
+
return {} if @controller.nil?
|
59
|
+
|
58
60
|
@_overrides ||= Hashie::Mash.new.tap do |_overrides|
|
59
|
-
(controller(:params)[
|
61
|
+
(controller(:params)[identifier] || {}).each do |name, value|
|
60
62
|
_overrides[name] = value
|
61
63
|
end
|
62
64
|
end
|
@@ -78,14 +80,6 @@ module Rafters::Component
|
|
78
80
|
|
79
81
|
private
|
80
82
|
|
81
|
-
def random_seed
|
82
|
-
rand(DateTime.now.to_i).to_s
|
83
|
-
end
|
84
|
-
|
85
|
-
def random_identifier
|
86
|
-
Digest::MD5.hexdigest(random_seed)[0..6]
|
87
|
-
end
|
88
|
-
|
89
83
|
module ClassMethods
|
90
84
|
attr_accessor :_attributes, :_defaults, :_template_name
|
91
85
|
|
@@ -112,6 +106,6 @@ module Rafters::Component
|
|
112
106
|
end
|
113
107
|
end
|
114
108
|
|
115
|
-
class
|
109
|
+
class IdentifierMissing < StandardError; end
|
116
110
|
class InvalidSetting < StandardError; end
|
117
111
|
end
|
@@ -8,23 +8,23 @@ module Rafters::ComponentContext
|
|
8
8
|
alias_method_chain :render, :component
|
9
9
|
end
|
10
10
|
|
11
|
-
def component_attributes(name,
|
12
|
-
component = component(name,
|
11
|
+
def component_attributes(name, options = {})
|
12
|
+
component = component(name, options)
|
13
13
|
component.as_json
|
14
14
|
end
|
15
15
|
|
16
|
-
def render_component(name,
|
17
|
-
component = component(name,
|
18
|
-
component_renderer.render(component
|
16
|
+
def render_component(name, options = {})
|
17
|
+
component = component(name, options)
|
18
|
+
component_renderer.render(component)
|
19
19
|
end
|
20
20
|
|
21
21
|
def render_with_component(*args, &block)
|
22
22
|
if params[:component]
|
23
|
-
component, settings = params[:component], params[:
|
23
|
+
component, settings = params[:component], params[:options]
|
24
24
|
|
25
25
|
respond_to do |format|
|
26
|
-
format.html { render_without_component(text: render_component(component,
|
27
|
-
format.json { render_without_component(json: component_attributes(component,
|
26
|
+
format.html { render_without_component(text: render_component(component, options)) }
|
27
|
+
format.json { render_without_component(json: component_attributes(component, options)) }
|
28
28
|
end
|
29
29
|
else
|
30
30
|
render_without_component(*args, &block)
|
@@ -37,8 +37,8 @@ module Rafters::ComponentContext
|
|
37
37
|
@_component_renderer ||= Rafters::ComponentRenderer.new(self)
|
38
38
|
end
|
39
39
|
|
40
|
-
def component(name,
|
40
|
+
def component(name, options = {})
|
41
41
|
component_klass = "#{name}_component".classify.constantize
|
42
|
-
component = component_klass.new(
|
42
|
+
component = component_klass.new(options)
|
43
43
|
end
|
44
44
|
end
|
@@ -7,15 +7,13 @@ class Rafters::ComponentRenderer
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
def render(component
|
10
|
+
def render(component)
|
11
11
|
component.controller = @controller
|
12
12
|
|
13
|
-
template_name = (template_name || component.template_name)
|
14
|
-
|
15
13
|
store(component)
|
16
14
|
|
17
15
|
@controller.view_context.content_tag(:div, class: "component", id: component.identifier) do
|
18
|
-
@controller.view_context.render(file: "/#{template_name}", locals: component.attributes)
|
16
|
+
@controller.view_context.render(file: "/#{component.template_name}", locals: component.attributes)
|
19
17
|
end
|
20
18
|
end
|
21
19
|
|
data/lib/rafters/version.rb
CHANGED
data/rafters.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency "rspec-rails", "~> 2.14"
|
25
25
|
spec.add_development_dependency "capybara", "~> 2.1"
|
26
26
|
spec.add_development_dependency "yard", "~> 0.8"
|
27
|
+
spec.add_development_dependency 'coveralls', "~> 0.6.7"
|
27
28
|
|
28
29
|
spec.add_dependency "rails", "> 3.2"
|
29
30
|
spec.add_dependency "sprockets", "> 2.2"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<h2><%= link_to_if settings.link_to_post?, post.title, post_path(post.id) %></h2>
|
2
2
|
|
3
|
-
<%= render_component :author, id: post.author.id %>
|
3
|
+
<%= render_component :author, as: "author-#{post.author.id}", settings: { id: post.author.id } %>
|
4
4
|
|
5
5
|
<%= simple_format post.body %>
|
@@ -1,10 +1,10 @@
|
|
1
1
|
<div class="main">
|
2
2
|
<div class="content">
|
3
|
-
<%= render_component :heading, title: "Posts" %>
|
4
|
-
<%= render_component :posts %>
|
3
|
+
<%= render_component :heading, as: "heading", settings: { title: "Posts" } %>
|
4
|
+
<%= render_component :posts, as: "posts" %>
|
5
5
|
</div>
|
6
6
|
|
7
7
|
<div class="sidebar">
|
8
|
-
<%= render_component :links %>
|
8
|
+
<%= render_component :links, as: "links" %>
|
9
9
|
</div>
|
10
10
|
</div>
|
@@ -18,21 +18,14 @@ describe Rafters::ComponentContext do
|
|
18
18
|
|
19
19
|
describe "#render_component" do
|
20
20
|
it "renders the provided component" do
|
21
|
-
renderer.should_receive(:render).with(instance_of(FooComponent)
|
22
|
-
controller.render_component(:foo)
|
21
|
+
renderer.should_receive(:render).with(instance_of(FooComponent))
|
22
|
+
controller.render_component(:foo, as: "foo")
|
23
23
|
end
|
24
24
|
|
25
25
|
context "with settings" do
|
26
26
|
it "renders the provided component with the given settings" do
|
27
|
-
FooComponent.should_receive(:new).with({ test: true })
|
28
|
-
controller.render_component(:foo, test: true)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context "with a specified template name" do
|
33
|
-
it "renders the provided component using the given template name" do
|
34
|
-
renderer.should_receive(:render).with(instance_of(FooComponent), "template_name")
|
35
|
-
controller.render_component(:foo, {}, "template_name")
|
27
|
+
FooComponent.should_receive(:new).with({ as: "foo", settings: { test: true } })
|
28
|
+
controller.render_component(:foo, { as: "foo", settings: { test: true } })
|
36
29
|
end
|
37
30
|
end
|
38
31
|
end
|
@@ -35,12 +35,5 @@ describe Rafters::ComponentRenderer do
|
|
35
35
|
view_context.should_receive(:render).with(file: "/template", locals: { title: "Foo" })
|
36
36
|
subject.render(component)
|
37
37
|
end
|
38
|
-
|
39
|
-
context "with a specified template name" do
|
40
|
-
it "renders the component with the specified template" do
|
41
|
-
view_context.should_receive(:render).with(file: "/custom_template", locals: { title: "Foo" })
|
42
|
-
subject.render(component, "custom_template")
|
43
|
-
end
|
44
|
-
end
|
45
38
|
end
|
46
39
|
end
|
@@ -17,7 +17,7 @@ describe Rafters::Component do
|
|
17
17
|
HeadingComponent.send(:define_method, :title, -> { "Lorem Ipsum" })
|
18
18
|
HeadingComponent.attribute(:title)
|
19
19
|
|
20
|
-
heading = HeadingComponent.new
|
20
|
+
heading = HeadingComponent.new(as: "heading")
|
21
21
|
heading.attributes.should have_key(:title)
|
22
22
|
end
|
23
23
|
end
|
@@ -28,7 +28,7 @@ describe Rafters::Component do
|
|
28
28
|
HeadingComponent.send(:define_method, :subtitle, -> { "Dolor Sit Amet" })
|
29
29
|
HeadingComponent.attributes(:title, :subtitle)
|
30
30
|
|
31
|
-
heading = HeadingComponent.new
|
31
|
+
heading = HeadingComponent.new(as: "heading")
|
32
32
|
heading.attributes.keys.map(&:to_sym).should include(:title)
|
33
33
|
heading.attributes.keys.map(&:to_sym).should include(:subtitle)
|
34
34
|
end
|
@@ -38,7 +38,7 @@ describe Rafters::Component do
|
|
38
38
|
it "adds default values to the component settings" do
|
39
39
|
HeadingComponent.defaults(foo: "bar")
|
40
40
|
|
41
|
-
heading = HeadingComponent.new
|
41
|
+
heading = HeadingComponent.new(as: "heading")
|
42
42
|
heading.settings.foo.should == "bar"
|
43
43
|
end
|
44
44
|
end
|
@@ -49,15 +49,15 @@ describe Rafters::Component do
|
|
49
49
|
HeadingComponent.attribute(:title)
|
50
50
|
end
|
51
51
|
|
52
|
-
subject { HeadingComponent.new }
|
52
|
+
subject { HeadingComponent.new(as: "heading") }
|
53
53
|
|
54
54
|
it "returns the registered attributes and their values" do
|
55
|
-
subject.attributes.should == Hashie::Mash.new({ title: "Lorem Ipsum", settings: {} })
|
55
|
+
subject.attributes.should == Hashie::Mash.new({ title: "Lorem Ipsum", identifier: "heading", settings: {} })
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
describe "#settings" do
|
60
|
-
subject { HeadingComponent.new({ type: "h2" }) }
|
60
|
+
subject { HeadingComponent.new(as: "heading", settings: { type: "h2" }) }
|
61
61
|
|
62
62
|
it "returns the provided settings" do
|
63
63
|
subject.settings.should == Hashie::Mash.new({ type: "h2" })
|
@@ -70,7 +70,7 @@ describe Rafters::Component do
|
|
70
70
|
end
|
71
71
|
|
72
72
|
describe "#template_name" do
|
73
|
-
subject { HeadingComponent.new }
|
73
|
+
subject { HeadingComponent.new(as: "heading") }
|
74
74
|
|
75
75
|
context "with no specified template name" do
|
76
76
|
it "returns the inferred template name" do
|
@@ -103,7 +103,7 @@ describe Rafters::Component do
|
|
103
103
|
end
|
104
104
|
|
105
105
|
describe "#controller" do
|
106
|
-
subject { HeadingComponent.new }
|
106
|
+
subject { HeadingComponent.new(as: "heading") }
|
107
107
|
|
108
108
|
let(:controller) { Object.new }
|
109
109
|
|
@@ -132,8 +132,8 @@ describe Rafters::Component do
|
|
132
132
|
end
|
133
133
|
|
134
134
|
context "when there is neither a method nor an instance variable with the given name in the controller" do
|
135
|
-
it "
|
136
|
-
|
135
|
+
it "returns nil" do
|
136
|
+
subject.controller(:doesnt_exist).should == nil
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
@@ -141,7 +141,7 @@ describe Rafters::Component do
|
|
141
141
|
after do
|
142
142
|
# A little housekeeping after each spec runs, so that
|
143
143
|
# we have fresh values for each class attribute
|
144
|
-
HeadingComponent._attributes = [:settings]
|
144
|
+
HeadingComponent._attributes = [:settings, :identifier]
|
145
145
|
HeadingComponent._defaults = {}
|
146
146
|
HeadingComponent._template_name = nil
|
147
147
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
require 'coveralls'
|
2
|
+
Coveralls.wear!
|
3
|
+
|
4
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter 'spec/dummy'
|
7
|
+
end
|
8
|
+
|
1
9
|
ENV["RAILS_ENV"] ||= 'test'
|
2
10
|
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
3
11
|
require 'rspec/rails'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rafters
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Hite
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
11
|
+
date: 2013-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ~>
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.8'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: coveralls
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.6.7
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.6.7
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: rails
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|