rafters 0.0.2 → 0.0.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.
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" } %>