rafters 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -0
  3. data/README.md +12 -4
  4. data/lib/rafters/component.rb +46 -17
  5. data/lib/rafters/component_renderer.rb +3 -3
  6. data/lib/rafters/engine.rb +14 -4
  7. data/lib/rafters/version.rb +1 -1
  8. data/lib/rafters.rb +0 -1
  9. data/lib/{rafters/directive_processor.rb → sprockets/component_processor.rb} +1 -1
  10. data/rafters.gemspec +1 -0
  11. data/spec/dummy/app/components/author/assets/images/.gitkeep +0 -0
  12. data/spec/dummy/app/components/author/assets/javascripts/author_component.js +0 -0
  13. data/spec/dummy/app/components/author/assets/stylesheets/author_component.scss +0 -0
  14. data/spec/dummy/app/components/author/author_component.rb +15 -0
  15. data/spec/dummy/app/components/author/views/author_component.html.erb +1 -0
  16. data/spec/dummy/app/components/heading/heading_component.rb +2 -9
  17. data/spec/dummy/app/components/heading/views/heading_component.html.erb +1 -1
  18. data/spec/dummy/app/components/links/assets/images/.gitkeep +0 -0
  19. data/spec/dummy/app/components/links/assets/javascripts/links_component.js +0 -0
  20. data/spec/dummy/app/components/links/assets/stylesheets/links_component.scss +0 -0
  21. data/spec/dummy/app/components/links/links_component.rb +16 -0
  22. data/spec/dummy/app/components/links/views/links_component.html.erb +5 -0
  23. data/spec/dummy/app/components/post/assets/images/.gitkeep +0 -0
  24. data/spec/dummy/app/components/post/assets/javascripts/post_component.js +0 -0
  25. data/spec/dummy/app/components/post/assets/stylesheets/post_component.scss +0 -0
  26. data/spec/dummy/app/components/post/post_component.rb +16 -0
  27. data/spec/dummy/app/components/post/views/post_component.html.erb +5 -0
  28. data/spec/dummy/app/components/posts/assets/images/.gitkeep +0 -0
  29. data/spec/dummy/app/components/posts/assets/javascripts/posts_component.js +0 -0
  30. data/spec/dummy/app/components/posts/assets/stylesheets/posts_component.scss +0 -0
  31. data/spec/dummy/app/components/posts/posts_component.rb +11 -0
  32. data/spec/dummy/app/components/posts/views/posts_component.html.erb +5 -0
  33. data/spec/dummy/app/controllers/posts_controller.rb +9 -0
  34. data/spec/dummy/app/helpers/posts_helper.rb +2 -0
  35. data/spec/dummy/app/models/author.rb +26 -0
  36. data/spec/dummy/app/models/post.rb +28 -0
  37. data/spec/dummy/app/views/posts/index.html.erb +10 -0
  38. data/spec/dummy/app/views/posts/show.html.erb +9 -0
  39. data/spec/dummy/config/application.rb +0 -6
  40. data/spec/dummy/config/environments/development.rb +0 -3
  41. data/spec/dummy/config/environments/test.rb +0 -3
  42. data/spec/dummy/config/initializers/secret_token.rb +1 -0
  43. data/spec/dummy/config/routes.rb +1 -1
  44. data/spec/rafters/component_context_spec.rb +41 -0
  45. data/spec/rafters/component_renderer_spec.rb +37 -0
  46. data/spec/rafters/component_spec.rb +3 -3
  47. data/spec/rafters/features/rendering_a_page_spec.rb +8 -0
  48. data/spec/spec_helper.rb +1 -4
  49. metadata +79 -12
  50. data/spec/dummy/app/controllers/foos_controller.rb +0 -5
  51. data/spec/dummy/app/helpers/foos_helper.rb +0 -2
  52. data/spec/dummy/app/views/foos/index.html.erb +0 -1
  53. /data/spec/dummy/app/assets/javascripts/{foos.js → posts.js} +0 -0
  54. /data/spec/dummy/app/assets/stylesheets/{foos.css → posts.css} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e8b3844cb042af682eebe4144d1b7fc4ec2c94f4
4
- data.tar.gz: a8289294a9c4738ac9d32d6196341943975cadf1
3
+ metadata.gz: e4199faab0e6c08bb71f8b982f9ec0d8a4f71cdd
4
+ data.tar.gz: eab7deb22988294f34cb4d4c8f20782334709a22
5
5
  SHA512:
6
- metadata.gz: 72dc85e535552dd97e66455a060c6177f6e9877e3172e5e6f2509947e0cbf9d3aeb16c674596075d1112eff71c88b1d9db20eb7f1c59f24b035f3937cff72235
7
- data.tar.gz: f28a3aa42f3d4a0fc9e9c2a70106a864377b93388e829c9a2cbdfaf5c0b581a4c783fce4f96bc41bc669ca702b5ecda11b61831ef2487dd8c234980c4ade613c
6
+ metadata.gz: 0c5e9b1ad6c5773c0e2e8ce44ad5452d225dc6668cd97bb10e123320303f84f20972599bcdfe2f74d118e86f81b8547d1286aa41308e1b09feee6716590a0c30
7
+ data.tar.gz: 821b6b96f755c152c3f938b9e984d8398047efe28e6505824d202ed61713028ba12127b26696f11a3e3f17a6eac4d3664f0a07816da1c2f03403b88c15e1b346
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  !!! STILL UNDER ACTIVE DEVELOPMENT. USE AT YOUR OWN RISK !!!
4
4
 
5
+ [![Build Status](https://travis-ci.org/andyhite/rafters.png?branch=master)](https://travis-ci.org/andyhite/rafters)
6
+
5
7
  Rafters lets you think about each page of your application as a collection of small pieces instead of monolithic, difficult to maintain
6
8
  views.
7
9
 
@@ -71,7 +73,7 @@ You can render components anywhere - in your view, in your controller, in anothe
71
73
 
72
74
  ### Adding an attribute to a component
73
75
 
74
- Each component exposes attributes to it's view using `Rafters::Component#attributes`, which are available in the view under the local variable `attributes`. The `attributes` are simply a collection of methods that you explicitly declare as such in your component, using the `Rafters::Component.attribute` method.
76
+ Each component exposes `attributes` to it's view as locals. The `attributes` are simply a collection of methods that you explicitly declare as `attributes` in your component, using the `Rafters::Component.attribute` method.
75
77
 
76
78
  For instance, let's say we have a HeadingComponent that exposes a title attribute:
77
79
 
@@ -91,11 +93,11 @@ end
91
93
 
92
94
  Since we won't be accessing the `HeadingComponent#title` method directly from within our view, it's recommended to make it a private method. The interface that our component exposes is taken care of behind the scenes.
93
95
 
94
- You can access the attribute in your component view using the `attributes` object:
96
+ You can access the method in your component view using the name of the attribute:
95
97
 
96
98
  ```erb
97
99
  <div class="heading">
98
- <h1><%= attributes.title %></h1>
100
+ <h1><%= title %></h1>
99
101
  </div>
100
102
  ```
101
103
 
@@ -187,7 +189,7 @@ end
187
189
  Default values can be provided for settings using the `default` option:
188
190
 
189
191
  ```ruby
190
- setting :type, default: "Comment"
192
+ setting :type, default: "comment"
191
193
  ```
192
194
 
193
195
  Required settings can be specified using the `required` option:
@@ -196,6 +198,12 @@ Required settings can be specified using the `required` option:
196
198
  setting :user_id, required: true
197
199
  ```
198
200
 
201
+ If you want to restrict the possible values of a setting to a known list, use the `accepts` option:
202
+
203
+ ```ruby
204
+ setting :type, accepts: %w(post reply comment)
205
+ ```
206
+
199
207
  ## Contributing
200
208
 
201
209
  1. Fork it
@@ -3,36 +3,38 @@ module Rafters::Component
3
3
 
4
4
  attr_writer :controller
5
5
 
6
+ included do
7
+ attribute :settings
8
+ end
9
+
6
10
  def initialize(settings = {})
7
11
  @settings = settings
8
12
  end
9
13
 
10
14
  def template_name
11
- return @_template_name if @_template_name
12
-
13
- _template_name = self.class._template_name
14
- _underscored_name = self.class.name.underscore
15
-
16
- if _template_name.is_a?(Proc)
17
- _template_name = _template_name.call(self)
15
+ @_template_name ||= begin
16
+ _template_name = (self.class._template_name || self.class.name.underscore)
17
+ _template_name = _template_name.call(self) if _template_name.is_a?(Proc)
18
+ _template_name
18
19
  end
19
-
20
- @_template_name = (_template_name || _underscored_name)
21
20
  end
22
21
 
23
22
  def attributes
23
+ return {} if self.class._attributes.nil?
24
+
24
25
  @_attributes ||= Hashie::Mash.new.tap do |_attributes|
25
- self.class._attributes.each do |name, options|
26
+ self.class._attributes.each do |name|
26
27
  _attributes[name] = send(name)
27
28
  end
28
29
  end
29
30
  end
30
31
 
31
32
  def settings
33
+ return {} if self.class._settings.nil?
34
+
32
35
  @_settings ||= Hashie::Mash.new.tap do |_settings|
33
36
  self.class._settings.each do |name, options|
34
- _settings[name] = (@settings[name] || options[:default] || nil)
35
- raise SettingRequired if options[:required] && _settings[name].nil?
37
+ _settings[name] = value_for_setting(name, options)
36
38
  end
37
39
  end
38
40
  end
@@ -43,16 +45,42 @@ module Rafters::Component
43
45
  elsif @controller.respond_to?(variable_or_method_name, true)
44
46
  @controller.send(variable_or_method_name)
45
47
  else
46
- raise CurrentVariableOrMethodNameMissing
48
+ raise CurrentMissing, "#{variable_or_method_name.to_s} not found in #{@controller.class.name}"
47
49
  end
48
50
  end
49
51
 
52
+ private
53
+
54
+ def value_for_setting(name, options)
55
+ value = @settings.has_key?(name) ? @settings[name] : options[:default]
56
+ validate_setting(name, value, options) && value
57
+ end
58
+
59
+ def validate_setting(name, value, options)
60
+ validate_setting_required(name, value, options[:required])
61
+ validate_setting_accepts(name, value, options[:accepts])
62
+ end
63
+
64
+ def validate_setting_required(name, value, required)
65
+ return true unless !!required
66
+ raise SettingRequired, "#{name} is required but not provided" if value.nil?
67
+ end
68
+
69
+ def validate_setting_accepts(name, value, accepts)
70
+ return true unless !!accepts
71
+ raise InvalidSetting, "#{value} is not a valid value for #{name}. Accepts: #{accepts.join(', ')}" unless accepts.include?(value)
72
+ end
73
+
50
74
  module ClassMethods
51
75
  attr_accessor :_attributes, :_settings, :_template_name
52
76
 
53
- def attribute(name, options = {})
54
- self._attributes ||= {}
55
- self._attributes[name.to_sym] = options
77
+ def attribute(name)
78
+ self._attributes ||= []
79
+ self._attributes << name
80
+ end
81
+
82
+ def attributes(*names)
83
+ names.each { |name| attribute(name) }
56
84
  end
57
85
 
58
86
  def setting(name, options = {})
@@ -65,6 +93,7 @@ module Rafters::Component
65
93
  end
66
94
  end
67
95
 
68
- class CurrentVariableOrMethodNameMissing < StandardError; end
96
+ class CurrentMissing < StandardError; end
69
97
  class SettingRequired < StandardError; end
98
+ class InvalidSetting < StandardError; end
70
99
  end
@@ -12,9 +12,9 @@ class Rafters::ComponentRenderer
12
12
 
13
13
  template_name = (template_name || component.template_name)
14
14
 
15
- @controller.view_context.render(file: "/#{template_name}", locals: {
16
- settings: component.settings,
17
- attributes: component.attributes
15
+ @controller.view_context.render({
16
+ file: "/#{template_name}",
17
+ locals: component.attributes
18
18
  })
19
19
  end
20
20
  end
@@ -1,3 +1,5 @@
1
+ require 'sprockets/component_processor'
2
+
1
3
  class Rafters::Engine < Rails::Engine
2
4
  isolate_namespace Rafters
3
5
 
@@ -24,10 +26,18 @@ class Rafters::Engine < Rails::Engine
24
26
  end
25
27
 
26
28
  config.after_initialize do |app|
27
- app.assets.unregister_preprocessor('text/css', Sprockets::DirectiveProcessor)
28
- app.assets.register_preprocessor('text/css', Rafters::DirectiveProcessor)
29
+ begin
30
+ app.assets.unregister_preprocessor('text/css', Sprockets::DirectiveProcessor)
31
+ app.assets.register_preprocessor('text/css', Sprockets::ComponentProcessor)
32
+ rescue
33
+ Rails.logger.warn("Could not load Sprockets::ComponentProcessor for text/css")
34
+ end
29
35
 
30
- app.assets.unregister_preprocessor('application/javascript', Sprockets::DirectiveProcessor)
31
- app.assets.register_preprocessor('application/javascript', Rafters::DirectiveProcessor)
36
+ begin
37
+ app.assets.unregister_preprocessor('application/javascript', Sprockets::DirectiveProcessor)
38
+ app.assets.register_preprocessor('application/javascript', Sprockets::ComponentProcessor)
39
+ rescue
40
+ Rails.logger.warn("Could not load Sprockets::ComponentProcessor for application/javascript")
41
+ end
32
42
  end
33
43
  end
@@ -1,3 +1,3 @@
1
1
  module Rafters
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/rafters.rb CHANGED
@@ -10,7 +10,6 @@ module Rafters
10
10
  autoload :Component
11
11
  autoload :ComponentContext
12
12
  autoload :ComponentRenderer
13
- autoload :DirectiveProcessor
14
13
  end
15
14
 
16
15
  def self.setup
@@ -1,4 +1,4 @@
1
- class Rafters::DirectiveProcessor < Sprockets::DirectiveProcessor
1
+ class Sprockets::ComponentProcessor < Sprockets::DirectiveProcessor
2
2
  def process_require_components_directive
3
3
  Rafters.asset_paths.sort.each do |asset_path|
4
4
  each_entry(asset_path) do |pathname|
data/rafters.gemspec CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "debugger", "~> 1.6"
23
23
  spec.add_development_dependency "rake", "~> 10.1"
24
24
  spec.add_development_dependency "rspec-rails", "~> 2.14"
25
+ spec.add_development_dependency "capybara", "~> 2.1"
25
26
 
26
27
  spec.add_dependency "rails", "> 3.2"
27
28
  spec.add_dependency "hashie", "~> 2.0.5"
@@ -0,0 +1,15 @@
1
+ class AuthorComponent
2
+ include Rafters::Component
3
+
4
+ # Settings
5
+ setting :id, required: true
6
+
7
+ # Attributes
8
+ attribute :author
9
+
10
+ private
11
+
12
+ def author
13
+ @author ||= Author.find(settings.id)
14
+ end
15
+ end
@@ -0,0 +1 @@
1
+ <h3><%= author.name %></h3>
@@ -1,13 +1,6 @@
1
1
  class HeadingComponent
2
2
  include Rafters::Component
3
3
 
4
- attribute :title
5
-
6
- setting :level, required: true
7
-
8
- private
9
-
10
- def title
11
- current(:title)
12
- end
4
+ # Settings
5
+ setting :title, required: true
13
6
  end
@@ -1 +1 @@
1
- <<%= settings.level %>><%= attributes.title %></<%= settings.level %>>
1
+ <h1><%= settings.title %></h1>
@@ -0,0 +1,16 @@
1
+ class LinksComponent
2
+ include Rafters::Component
3
+
4
+ # Attributes
5
+ attribute :links
6
+
7
+ private
8
+
9
+ def links
10
+ @links ||= [
11
+ { name: "Google", url: "http://google.com" },
12
+ { name: "Yahoo", url: "http://yahoo.com" },
13
+ { name: "Bing", url: "http://bing.com" }
14
+ ]
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ <ul class="links">
2
+ <% links.each do |link| %>
3
+ <li><%= link_to link.name, link.url, target: "_blank" %></li>
4
+ <% end %>
5
+ </ul>
@@ -0,0 +1,16 @@
1
+ class PostComponent
2
+ include Rafters::Component
3
+
4
+ # Settings
5
+ setting :post
6
+ setting :link_to_post, accepts: [true, false], default: false
7
+
8
+ # Attributes
9
+ attribute :post
10
+
11
+ private
12
+
13
+ def post
14
+ @post ||= (settings.post || current(:post))
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ <h2><%= link_to_if settings.link_to_post?, post.title, post_path(post.id) %></h2>
2
+
3
+ <%= render_component :author, { id: post.author.id } %>
4
+
5
+ <%= simple_format post.body %>
@@ -0,0 +1,11 @@
1
+ class PostsComponent
2
+ include Rafters::Component
3
+
4
+ attribute :posts
5
+
6
+ private
7
+
8
+ def posts
9
+ @posts ||= current(:posts)
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ <div class="posts">
2
+ <% posts.each do |post| %>
3
+ <%= render_component :post, { post: post, link_to_post: true } %>
4
+ <% end %>
5
+ </div>
@@ -0,0 +1,9 @@
1
+ class PostsController < ApplicationController
2
+ def index
3
+ @posts = Post.all
4
+ end
5
+
6
+ def show
7
+ @post = Post.find(params[:id])
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ module PostsHelper
2
+ end
@@ -0,0 +1,26 @@
1
+ class Author
2
+ attr_accessor :id, :name
3
+
4
+ FIXTURES = [
5
+ { id: 1, name: "Andrew Hite" },
6
+ { id: 2, name: "Andrew Latimer" }
7
+ ]
8
+
9
+ def initialize(attributes = {})
10
+ @id = attributes[:id]
11
+ @name = attributes[:name]
12
+ end
13
+
14
+ class << self
15
+ def all
16
+ FIXTURES.map do |attributes|
17
+ new(attributes)
18
+ end
19
+ end
20
+
21
+ def find(id)
22
+ attributes = FIXTURES.find { |fixture| fixture[:id] == id.to_i }
23
+ new(attributes)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ class Post
2
+ attr_accessor :id, :title, :body, :author
3
+
4
+ FIXTURES = [
5
+ { id: 1, title: "Lorem Ipsum", body: "Lorem ipsum dolor sit amet...", author: Author.find(1) },
6
+ { id: 2, title: "Dolor Sit Amet", body: "Consectetur adipiscing elit...", author: Author.find(2) }
7
+ ]
8
+
9
+ def initialize(attributes = {})
10
+ @id = attributes[:id]
11
+ @title = attributes[:title]
12
+ @body = attributes[:body]
13
+ @author = attributes[:author]
14
+ end
15
+
16
+ class << self
17
+ def all
18
+ FIXTURES.map do |attributes|
19
+ new(attributes)
20
+ end
21
+ end
22
+
23
+ def find(id)
24
+ attributes = FIXTURES.find { |fixture| fixture[:id] == id.to_i }
25
+ new(attributes)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,10 @@
1
+ <div class="main">
2
+ <div class="content">
3
+ <%= render_component :heading, { title: "Posts" } %>
4
+ <%= render_component :posts %>
5
+ </div>
6
+
7
+ <div class="sidebar">
8
+ <%= render_component :links %>
9
+ </div>
10
+ </div>
@@ -0,0 +1,9 @@
1
+ <div class="main">
2
+ <div class="content">
3
+ <%= render_component :post %>
4
+ </div>
5
+
6
+ <div class="sidebar">
7
+ <%= render_component :links %>
8
+ </div>
9
+ </div>
@@ -43,12 +43,6 @@ module Dummy
43
43
  # like if you have constraints or database-specific column types
44
44
  # config.active_record.schema_format = :sql
45
45
 
46
- # Enforce whitelist mode for mass assignment.
47
- # This will create an empty whitelist of attributes available for mass-assignment for all models
48
- # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
49
- # parameters by using an attr_accessible or attr_protected declaration.
50
- config.active_record.whitelist_attributes = true
51
-
52
46
  # Enable the asset pipeline
53
47
  config.assets.enabled = true
54
48
 
@@ -22,9 +22,6 @@ Dummy::Application.configure do
22
22
  # Only use best-standards-support built into browsers
23
23
  config.action_dispatch.best_standards_support = :builtin
24
24
 
25
- # Raise exception on mass assignment protection for Active Record models
26
- config.active_record.mass_assignment_sanitizer = :strict
27
-
28
25
  # Log the query plan for queries taking more than this (works
29
26
  # with SQLite, MySQL, and PostgreSQL)
30
27
  config.active_record.auto_explain_threshold_in_seconds = 0.5
@@ -29,9 +29,6 @@ Dummy::Application.configure do
29
29
  # ActionMailer::Base.deliveries array.
30
30
  config.action_mailer.delivery_method = :test
31
31
 
32
- # Raise exception on mass assignment protection for Active Record models
33
- config.active_record.mass_assignment_sanitizer = :strict
34
-
35
32
  # Print deprecation notices to the stderr
36
33
  config.active_support.deprecation = :stderr
37
34
  end
@@ -5,3 +5,4 @@
5
5
  # Make sure the secret is at least 30 characters and all random,
6
6
  # no regular words or you'll be exposed to dictionary attacks.
7
7
  Dummy::Application.config.secret_token = '304950c1cbff2fec75b62ede6d392171fc25435481002bd7ba9d911433a277bb96aed01bf90572d18f819d20a5ec45a835ccfbfe42347f0c3a0fb527e543c694'
8
+ Dummy::Application.config.secret_key_base = '12345'
@@ -1,5 +1,5 @@
1
1
  Rails.application.routes.draw do
2
2
  mount Rafters::Engine => "/rafters"
3
3
 
4
- resources :foos
4
+ resources :posts
5
5
  end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ class FooController < ActionController::Base
4
+ include Rafters::ComponentContext
5
+ end
6
+
7
+ class FooComponent
8
+ include Rafters::Component
9
+
10
+ setting :test
11
+ end
12
+
13
+ describe Rafters::ComponentContext do
14
+ let(:controller) { FooController.new }
15
+ let(:renderer) { double("ComponentRenderer", render: "<p>Output</p>") }
16
+
17
+ before do
18
+ Rafters::ComponentRenderer.stub(:new).and_return(renderer)
19
+ end
20
+
21
+ describe "#render_component" do
22
+ it "renders the provided component" do
23
+ renderer.should_receive(:render).with(instance_of(FooComponent), nil)
24
+ controller.render_component(:foo)
25
+ end
26
+
27
+ context "with settings" do
28
+ it "renders the provided component with the given settings" do
29
+ FooComponent.should_receive(:new).with({ test: true })
30
+ controller.render_component(:foo, test: true)
31
+ end
32
+ end
33
+
34
+ context "with a specified template name" do
35
+ it "renders the provided component using the given template name" do
36
+ renderer.should_receive(:render).with(instance_of(FooComponent), "template_name")
37
+ controller.render_component(:foo, {}, "template_name")
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rafters::ComponentRenderer do
4
+ let(:view_context) { double("ViewContext", render: "<p>Output</p>") }
5
+ let(:controller) { double("Controller", prepend_view_path: true, view_context: view_context) }
6
+
7
+ describe "when initialized" do
8
+ before do
9
+ Rafters.stub(:view_paths).and_return(["/path/to/views"])
10
+ end
11
+
12
+ it "should add the view paths for all components to the controller" do
13
+ controller.should_receive(:prepend_view_path).with("/path/to/views")
14
+ Rafters::ComponentRenderer.new(controller)
15
+ end
16
+ end
17
+
18
+ describe "#render" do
19
+ subject { Rafters::ComponentRenderer.new(controller) }
20
+
21
+ let(:component) do
22
+ double("Component", attributes: { title: "Foo" }, :'controller=' => true, template_name: "template")
23
+ end
24
+
25
+ it "renders the component template with it's settings and attributes" do
26
+ view_context.should_receive(:render).with(file: "/template", locals: { title: "Foo" })
27
+ subject.render(component)
28
+ end
29
+
30
+ context "with a specified template name" do
31
+ it "renders the component with the specified template" do
32
+ view_context.should_receive(:render).with(file: "/custom_template", locals: { title: "Foo" })
33
+ subject.render(component, "custom_template")
34
+ end
35
+ end
36
+ end
37
+ end
@@ -58,7 +58,7 @@ describe Rafters::Component do
58
58
  subject { HeadingComponent.new }
59
59
 
60
60
  it "returns the registered attributes and their values" do
61
- subject.attributes.should == Hashie::Mash.new({ title: "Lorem Ipsum" })
61
+ subject.attributes.should == Hashie::Mash.new({ title: "Lorem Ipsum", settings: {} })
62
62
  end
63
63
  end
64
64
 
@@ -138,7 +138,7 @@ describe Rafters::Component do
138
138
 
139
139
  context "when there is neither a method nor an instance variable with the given name in the controller" do
140
140
  it "raises an error" do
141
- -> { subject.current(:doesnt_exist) }.should raise_error(Rafters::Component::CurrentVariableOrMethodNameMissing)
141
+ -> { subject.current(:doesnt_exist) }.should raise_error(Rafters::Component::CurrentMissing)
142
142
  end
143
143
  end
144
144
  end
@@ -146,7 +146,7 @@ describe Rafters::Component do
146
146
  after do
147
147
  # A little housekeeping after each spec runs, so that
148
148
  # we have fresh values for each class attribute
149
- HeadingComponent._attributes = nil
149
+ HeadingComponent._attributes = [:settings]
150
150
  HeadingComponent._settings = nil
151
151
  HeadingComponent._template_name = nil
152
152
  end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ feature "Rendering a page" do
4
+ scenario "with components on it" do
5
+ visit "/posts"
6
+ page.should have_css(".posts")
7
+ end
8
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  ENV["RAILS_ENV"] ||= 'test'
2
2
  require File.expand_path("../dummy/config/environment.rb", __FILE__)
3
- require 'rubygems'
4
- require 'bundler/setup'
5
-
6
- require 'rafters'
3
+ require 'rspec/rails'
7
4
 
8
5
  RSpec.configure do |config|
9
6
  config.treat_symbols_as_metadata_keys_with_true_values = true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rafters
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Hite
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.14'
69
+ - !ruby/object:Gem::Dependency
70
+ name: capybara
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '2.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '2.1'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rails
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -105,6 +119,7 @@ files:
105
119
  - .gitignore
106
120
  - .rspec
107
121
  - .rvmrc
122
+ - .travis.yml
108
123
  - Gemfile
109
124
  - MIT-LICENSE
110
125
  - README.md
@@ -120,29 +135,52 @@ files:
120
135
  - lib/rafters/component.rb
121
136
  - lib/rafters/component_context.rb
122
137
  - lib/rafters/component_renderer.rb
123
- - lib/rafters/directive_processor.rb
124
138
  - lib/rafters/engine.rb
125
139
  - lib/rafters/version.rb
140
+ - lib/sprockets/component_processor.rb
126
141
  - lib/tasks/rafters_tasks.rake
127
142
  - rafters.gemspec
128
143
  - spec/dummy/README.rdoc
129
144
  - spec/dummy/Rakefile
130
145
  - spec/dummy/app/assets/javascripts/application.js
131
- - spec/dummy/app/assets/javascripts/foos.js
146
+ - spec/dummy/app/assets/javascripts/posts.js
132
147
  - spec/dummy/app/assets/stylesheets/application.css
133
- - spec/dummy/app/assets/stylesheets/foos.css
148
+ - spec/dummy/app/assets/stylesheets/posts.css
149
+ - spec/dummy/app/components/author/assets/images/.gitkeep
150
+ - spec/dummy/app/components/author/assets/javascripts/author_component.js
151
+ - spec/dummy/app/components/author/assets/stylesheets/author_component.scss
152
+ - spec/dummy/app/components/author/author_component.rb
153
+ - spec/dummy/app/components/author/views/author_component.html.erb
134
154
  - spec/dummy/app/components/heading/assets/javascripts/heading_component.js
135
155
  - spec/dummy/app/components/heading/assets/stylesheets/heading_component.css
136
156
  - spec/dummy/app/components/heading/heading_component.rb
137
157
  - spec/dummy/app/components/heading/views/heading_component.html.erb
158
+ - spec/dummy/app/components/links/assets/images/.gitkeep
159
+ - spec/dummy/app/components/links/assets/javascripts/links_component.js
160
+ - spec/dummy/app/components/links/assets/stylesheets/links_component.scss
161
+ - spec/dummy/app/components/links/links_component.rb
162
+ - spec/dummy/app/components/links/views/links_component.html.erb
163
+ - spec/dummy/app/components/post/assets/images/.gitkeep
164
+ - spec/dummy/app/components/post/assets/javascripts/post_component.js
165
+ - spec/dummy/app/components/post/assets/stylesheets/post_component.scss
166
+ - spec/dummy/app/components/post/post_component.rb
167
+ - spec/dummy/app/components/post/views/post_component.html.erb
168
+ - spec/dummy/app/components/posts/assets/images/.gitkeep
169
+ - spec/dummy/app/components/posts/assets/javascripts/posts_component.js
170
+ - spec/dummy/app/components/posts/assets/stylesheets/posts_component.scss
171
+ - spec/dummy/app/components/posts/posts_component.rb
172
+ - spec/dummy/app/components/posts/views/posts_component.html.erb
138
173
  - spec/dummy/app/controllers/application_controller.rb
139
- - spec/dummy/app/controllers/foos_controller.rb
174
+ - spec/dummy/app/controllers/posts_controller.rb
140
175
  - spec/dummy/app/helpers/application_helper.rb
141
- - spec/dummy/app/helpers/foos_helper.rb
176
+ - spec/dummy/app/helpers/posts_helper.rb
142
177
  - spec/dummy/app/mailers/.gitkeep
143
178
  - spec/dummy/app/models/.gitkeep
144
- - spec/dummy/app/views/foos/index.html.erb
179
+ - spec/dummy/app/models/author.rb
180
+ - spec/dummy/app/models/post.rb
145
181
  - spec/dummy/app/views/layouts/application.html.erb
182
+ - spec/dummy/app/views/posts/index.html.erb
183
+ - spec/dummy/app/views/posts/show.html.erb
146
184
  - spec/dummy/config.ru
147
185
  - spec/dummy/config/application.rb
148
186
  - spec/dummy/config/boot.rb
@@ -167,7 +205,10 @@ files:
167
205
  - spec/dummy/public/500.html
168
206
  - spec/dummy/public/favicon.ico
169
207
  - spec/dummy/script/rails
208
+ - spec/rafters/component_context_spec.rb
209
+ - spec/rafters/component_renderer_spec.rb
170
210
  - spec/rafters/component_spec.rb
211
+ - spec/rafters/features/rendering_a_page_spec.rb
171
212
  - spec/spec_helper.rb
172
213
  homepage: ''
173
214
  licenses:
@@ -198,21 +239,44 @@ test_files:
198
239
  - spec/dummy/README.rdoc
199
240
  - spec/dummy/Rakefile
200
241
  - spec/dummy/app/assets/javascripts/application.js
201
- - spec/dummy/app/assets/javascripts/foos.js
242
+ - spec/dummy/app/assets/javascripts/posts.js
202
243
  - spec/dummy/app/assets/stylesheets/application.css
203
- - spec/dummy/app/assets/stylesheets/foos.css
244
+ - spec/dummy/app/assets/stylesheets/posts.css
245
+ - spec/dummy/app/components/author/assets/images/.gitkeep
246
+ - spec/dummy/app/components/author/assets/javascripts/author_component.js
247
+ - spec/dummy/app/components/author/assets/stylesheets/author_component.scss
248
+ - spec/dummy/app/components/author/author_component.rb
249
+ - spec/dummy/app/components/author/views/author_component.html.erb
204
250
  - spec/dummy/app/components/heading/assets/javascripts/heading_component.js
205
251
  - spec/dummy/app/components/heading/assets/stylesheets/heading_component.css
206
252
  - spec/dummy/app/components/heading/heading_component.rb
207
253
  - spec/dummy/app/components/heading/views/heading_component.html.erb
254
+ - spec/dummy/app/components/links/assets/images/.gitkeep
255
+ - spec/dummy/app/components/links/assets/javascripts/links_component.js
256
+ - spec/dummy/app/components/links/assets/stylesheets/links_component.scss
257
+ - spec/dummy/app/components/links/links_component.rb
258
+ - spec/dummy/app/components/links/views/links_component.html.erb
259
+ - spec/dummy/app/components/post/assets/images/.gitkeep
260
+ - spec/dummy/app/components/post/assets/javascripts/post_component.js
261
+ - spec/dummy/app/components/post/assets/stylesheets/post_component.scss
262
+ - spec/dummy/app/components/post/post_component.rb
263
+ - spec/dummy/app/components/post/views/post_component.html.erb
264
+ - spec/dummy/app/components/posts/assets/images/.gitkeep
265
+ - spec/dummy/app/components/posts/assets/javascripts/posts_component.js
266
+ - spec/dummy/app/components/posts/assets/stylesheets/posts_component.scss
267
+ - spec/dummy/app/components/posts/posts_component.rb
268
+ - spec/dummy/app/components/posts/views/posts_component.html.erb
208
269
  - spec/dummy/app/controllers/application_controller.rb
209
- - spec/dummy/app/controllers/foos_controller.rb
270
+ - spec/dummy/app/controllers/posts_controller.rb
210
271
  - spec/dummy/app/helpers/application_helper.rb
211
- - spec/dummy/app/helpers/foos_helper.rb
272
+ - spec/dummy/app/helpers/posts_helper.rb
212
273
  - spec/dummy/app/mailers/.gitkeep
213
274
  - spec/dummy/app/models/.gitkeep
214
- - spec/dummy/app/views/foos/index.html.erb
275
+ - spec/dummy/app/models/author.rb
276
+ - spec/dummy/app/models/post.rb
215
277
  - spec/dummy/app/views/layouts/application.html.erb
278
+ - spec/dummy/app/views/posts/index.html.erb
279
+ - spec/dummy/app/views/posts/show.html.erb
216
280
  - spec/dummy/config.ru
217
281
  - spec/dummy/config/application.rb
218
282
  - spec/dummy/config/boot.rb
@@ -237,5 +301,8 @@ test_files:
237
301
  - spec/dummy/public/500.html
238
302
  - spec/dummy/public/favicon.ico
239
303
  - spec/dummy/script/rails
304
+ - spec/rafters/component_context_spec.rb
305
+ - spec/rafters/component_renderer_spec.rb
240
306
  - spec/rafters/component_spec.rb
307
+ - spec/rafters/features/rendering_a_page_spec.rb
241
308
  - spec/spec_helper.rb
@@ -1,5 +0,0 @@
1
- class FoosController < ApplicationController
2
- def index
3
- @title = "Title from action"
4
- end
5
- end
@@ -1,2 +0,0 @@
1
- module FoosHelper
2
- end
@@ -1 +0,0 @@
1
- <%= render_component :heading, { level: "h1" } %>