rafters 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7900cb89ffd2a9e271783e382d76ce8aef995a1
4
- data.tar.gz: f79f54a8d9ca67f5ccc3c02be7c5b7631446f034
3
+ metadata.gz: 1ac7e06cae8eb40c60138562dca5806c7e7c91a9
4
+ data.tar.gz: 27e6adca0f5e3859ab26c2ec2a6dcb84c0be4a20
5
5
  SHA512:
6
- metadata.gz: fb63afff21e37662bac1b7d76a685b4968a49670bfabd4e1b448303344a2879d0b7747612950d69e6abdb28603b338daaa9e9136966aa78ed46bca44e2d82e83
7
- data.tar.gz: cd553bf4f1a515bfd594dea3f465ae1986b6ac0f7e5b666f387168528019d5fb5460544d0efb37f9cedbe214390b1d3382ebabffccc0d71d9b68a83ec6e83d0b
6
+ metadata.gz: e5f25e71ba70d5b4953a70ec870701b1a82a1d84394fc5f3ebdaa394c6d9291a6deb869d3436f038f4103025f91501c999a14d4a114cade086da3eeaf921b959
7
+ data.tar.gz: 01891c2592c824bc5da723fa63f9b7b8bbe659d8909975328e10d56376ca4b9d1ce45b7a7d772379564aa205d70565a2a84034eae2c2990ff6851c1ff170d85a
data/README.md CHANGED
@@ -74,7 +74,7 @@ You can render components anywhere - in your view, in your controller, in anothe
74
74
 
75
75
  ### Adding an attribute to a component
76
76
 
77
- 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.
77
+ 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` or `Rafters::Component.attributes` methods.
78
78
 
79
79
  For instance, let's say we have a HeadingComponent that exposes a title attribute:
80
80
 
@@ -104,7 +104,7 @@ You can access the method in your component view using the name of the attribute
104
104
 
105
105
  ### Accessing information from the controller in your components
106
106
 
107
- There will often be times when you need to access data in your component that is only available as an instance variable or method in your controller. Rafters provides a convenience method that lets you get to that data in a uniform way - `Rafters::Component#current`:
107
+ There will often be times when you need to access data in your component that is only available as an instance variable or method in your controller. Rafters provides a convenience method that lets you get to that data in a uniform way - `Rafters::Component#controller`:
108
108
 
109
109
  ```ruby
110
110
  class PostController
@@ -128,7 +128,7 @@ class RelatedPostsComponent
128
128
  ...
129
129
 
130
130
  def related_posts
131
- @related_posts ||= current(:post).related_posts.where(author_id: current(:current_user))
131
+ @related_posts ||= controller(:post).related_posts.where(author_id: controller(:current_user))
132
132
  end
133
133
  end
134
134
  ```
@@ -136,23 +136,13 @@ end
136
136
  You can also access the controller's params using this method:
137
137
 
138
138
  ```ruby
139
- current(:params)[:id]
139
+ controller(:params)[:id]
140
140
  ```
141
141
 
142
- ### Adding a setting to a component
142
+ ### Specifying settings for a component instance
143
143
 
144
- In order to build components in a way that allows for re-use, you'll want to define settings that allow individual instances of the component to be configured. These settings will likely be used throughout your component view and controller for any number of purposes, like values in query conditions, section titles, turning on or off specific features of a component, etc.
144
+ In order to build components in a way that allows for re-use, you'll want to use settings that allow individual instances of the component to be configured. These settings will likely be used throughout your component view and controller for any number of purposes, like values in query conditions, section titles, turning on or off specific features of a component, etc.
145
145
 
146
- Adding a setting is very similar to adding an attribute, except they don't point at methods:
147
-
148
- ```ruby
149
- class PostsComponent
150
- include Rafters::Component
151
-
152
- setting :published
153
- end
154
- ```
155
-
156
146
  Setting values are specified when rendering a component:
157
147
 
158
148
  ```erb
@@ -187,22 +177,11 @@ class PostsComponent
187
177
  end
188
178
  ```
189
179
 
190
- Default values can be provided for settings using the `default` option:
180
+ Default values can be provided for settings using `Rafters::Component.defaults` and `Rafters::Component.default`:
191
181
 
192
182
  ```ruby
193
- setting :type, default: "comment"
194
- ```
195
-
196
- Required settings can be specified using the `required` option:
197
-
198
- ```ruby
199
- setting :user_id, required: true
200
- ```
201
-
202
- If you want to restrict the possible values of a setting to a known list, use the `accepts` option:
203
-
204
- ```ruby
205
- setting :type, accepts: %w(post reply comment)
183
+ defaults type: "comment", filter: "none"
184
+ default :published, false
206
185
  ```
207
186
 
208
187
  ## Contributing
@@ -30,49 +30,23 @@ module Rafters::Component
30
30
  end
31
31
 
32
32
  def settings
33
- return {} if self.class._settings.nil?
34
-
35
- @_settings ||= Hashie::Mash.new.tap do |_settings|
36
- self.class._settings.each do |name, options|
37
- _settings[name] = value_for_setting(name, options)
38
- end
39
- end
33
+ @_settings ||= Hashie::Mash.new(@settings.reverse_merge(self.class._defaults || {}))
40
34
  end
41
35
 
42
- def current(variable_or_method_name)
36
+ def controller(variable_or_method_name)
43
37
  if @controller.instance_variable_defined?("@#{variable_or_method_name}")
44
38
  @controller.instance_variable_get("@#{variable_or_method_name}")
45
39
  elsif @controller.respond_to?(variable_or_method_name, true)
46
40
  @controller.send(variable_or_method_name)
47
41
  else
48
- raise CurrentMissing, "#{variable_or_method_name.to_s} not found in #{@controller.class.name}"
42
+ raise ControllerMethodOrVariableMissing, "#{variable_or_method_name.to_s} not found in #{@controller.class.name}"
49
43
  end
50
44
  end
51
45
 
52
46
  private
53
47
 
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
-
74
48
  module ClassMethods
75
- attr_accessor :_attributes, :_settings, :_template_name
49
+ attr_accessor :_attributes, :_defaults, :_template_name
76
50
 
77
51
  def attribute(name)
78
52
  self._attributes ||= []
@@ -83,9 +57,13 @@ module Rafters::Component
83
57
  names.each { |name| attribute(name) }
84
58
  end
85
59
 
86
- def setting(name, options = {})
87
- self._settings ||= {}
88
- self._settings[name.to_sym] = options
60
+ def default(name, value)
61
+ self._defaults ||= {}
62
+ self._defaults[name] = value
63
+ end
64
+
65
+ def defaults(settings = {})
66
+ settings.each { |name, value| default(name, value) }
89
67
  end
90
68
 
91
69
  def template_name(name)
@@ -93,7 +71,7 @@ module Rafters::Component
93
71
  end
94
72
  end
95
73
 
96
- class CurrentMissing < StandardError; end
74
+ class ControllerMethodOrVariableMissing < StandardError; end
97
75
  class SettingRequired < StandardError; end
98
76
  class InvalidSetting < StandardError; end
99
77
  end
@@ -3,6 +3,7 @@ module Rafters::ComponentContext
3
3
 
4
4
  included do
5
5
  helper_method :render_component
6
+ alias_method_chain :render, :component
6
7
  end
7
8
 
8
9
  def render_component(name, settings = {}, template_name = nil)
@@ -11,6 +12,30 @@ module Rafters::ComponentContext
11
12
  component_renderer.render(component, template_name)
12
13
  end
13
14
 
15
+ def render_component_attributes(name, settings = {})
16
+ component_klass = "#{name}_component".classify.constantize
17
+ component = component_klass.new(settings)
18
+ { :"#{name}" => component.attributes }.as_json
19
+ end
20
+
21
+ def render_with_component(*args, &block)
22
+ if params[:component]
23
+ component, settings = params[:component], params[:settings]
24
+
25
+ respond_to do |format|
26
+ format.html do
27
+ render_without_component(text: render_component(component, settings)) and return
28
+ end
29
+
30
+ format.json do
31
+ render_without_component(json: render_component_attributes(component, settings)) and return
32
+ end
33
+ end
34
+ else
35
+ render_without_component(*args, &block)
36
+ end
37
+ end
38
+
14
39
  private
15
40
 
16
41
  def component_renderer
@@ -1,3 +1,3 @@
1
1
  module Rafters
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -1,9 +1,6 @@
1
1
  class AuthorComponent
2
2
  include Rafters::Component
3
3
 
4
- # Settings
5
- setting :id, required: true
6
-
7
4
  # Attributes
8
5
  attribute :author
9
6
 
@@ -1,6 +1,5 @@
1
1
  class HeadingComponent
2
2
  include Rafters::Component
3
3
 
4
- # Settings
5
- setting :title, required: true
4
+ defaults title: "No Title Specified"
6
5
  end
@@ -1,16 +1,11 @@
1
1
  class PostComponent
2
2
  include Rafters::Component
3
3
 
4
- # Settings
5
- setting :post
6
- setting :link_to_post, accepts: [true, false], default: false
7
-
8
- # Attributes
9
4
  attribute :post
10
5
 
11
6
  private
12
7
 
13
8
  def post
14
- @post ||= (settings.post || current(:post))
9
+ @post ||= (settings.post || controller(:post))
15
10
  end
16
11
  end
@@ -6,6 +6,6 @@ class PostsComponent
6
6
  private
7
7
 
8
8
  def posts
9
- @posts ||= current(:posts)
9
+ @posts ||= controller(:posts)
10
10
  end
11
11
  end
@@ -6,8 +6,6 @@ end
6
6
 
7
7
  class FooComponent
8
8
  include Rafters::Component
9
-
10
- setting :test
11
9
  end
12
10
 
13
11
  describe Rafters::ComponentContext do
@@ -22,30 +22,24 @@ describe Rafters::Component do
22
22
  end
23
23
  end
24
24
 
25
- describe ".setting" do
26
- it "adds the provided key to the component's settings" do
27
- HeadingComponent.setting(:type)
25
+ describe ".attributes" do
26
+ it "adds a list of methods to the components attributes" do
27
+ HeadingComponent.send(:define_method, :title, -> { "Lorem Ipsum" })
28
+ HeadingComponent.send(:define_method, :subtitle, -> { "Dolor Sit Amet" })
29
+ HeadingComponent.attributes(:title, :subtitle)
28
30
 
29
31
  heading = HeadingComponent.new
30
- heading.settings.should respond_to(:type)
31
- end
32
-
33
- context "with a :default value" do
34
- it "sets the setting's value to the provided value when no value is available" do
35
- HeadingComponent.setting(:type, default: "h1")
36
-
37
- heading = HeadingComponent.new
38
- heading.settings.type.should == "h1"
39
- end
32
+ heading.attributes.keys.map(&:to_sym).should include(:title)
33
+ heading.attributes.keys.map(&:to_sym).should include(:subtitle)
40
34
  end
35
+ end
41
36
 
42
- context "with the :required option" do
43
- it "raises an error when accessing the settings if the value is nil" do
44
- HeadingComponent.setting(:type, required: true)
37
+ describe ".defaults" do
38
+ it "adds default values to the component settings" do
39
+ HeadingComponent.defaults(foo: "bar")
45
40
 
46
- heading = HeadingComponent.new
47
- -> { heading.settings }.should raise_error(Rafters::Component::SettingRequired)
48
- end
41
+ heading = HeadingComponent.new
42
+ heading.settings.foo.should == "bar"
49
43
  end
50
44
  end
51
45
 
@@ -63,15 +57,16 @@ describe Rafters::Component do
63
57
  end
64
58
 
65
59
  describe "#settings" do
66
- before do
67
- HeadingComponent.setting(:type)
68
- end
69
-
70
60
  subject { HeadingComponent.new({ type: "h2" }) }
71
61
 
72
- it "returns the registered settings and their values" do
62
+ it "returns the provided settings" do
73
63
  subject.settings.should == Hashie::Mash.new({ type: "h2" })
74
64
  end
65
+
66
+ it "gives provided settings precedence over default settings" do
67
+ HeadingComponent.default(:type, "h1")
68
+ subject.settings[:type].should == "h2"
69
+ end
75
70
  end
76
71
 
77
72
  describe "#template_name" do
@@ -107,7 +102,7 @@ describe Rafters::Component do
107
102
  end
108
103
  end
109
104
 
110
- describe "#current" do
105
+ describe "#controller" do
111
106
  subject { HeadingComponent.new }
112
107
 
113
108
  let(:controller) { Object.new }
@@ -122,7 +117,7 @@ describe Rafters::Component do
122
117
  end
123
118
 
124
119
  it "returns the value of the instance variable" do
125
- subject.current(:foo_bar).should == "lorem ipsum"
120
+ subject.controller(:foo_bar).should == "lorem ipsum"
126
121
  end
127
122
  end
128
123
 
@@ -132,13 +127,13 @@ describe Rafters::Component do
132
127
  end
133
128
 
134
129
  it "returns the value of the method" do
135
- subject.current(:lorem_ipsum).should == "foo bar"
130
+ subject.controller(:lorem_ipsum).should == "foo bar"
136
131
  end
137
132
  end
138
133
 
139
134
  context "when there is neither a method nor an instance variable with the given name in the controller" do
140
135
  it "raises an error" do
141
- -> { subject.current(:doesnt_exist) }.should raise_error(Rafters::Component::CurrentMissing)
136
+ -> { subject.controller(:doesnt_exist) }.should raise_error(Rafters::Component::ControllerMethodOrVariableMissing)
142
137
  end
143
138
  end
144
139
  end
@@ -147,7 +142,7 @@ describe Rafters::Component do
147
142
  # A little housekeeping after each spec runs, so that
148
143
  # we have fresh values for each class attribute
149
144
  HeadingComponent._attributes = [:settings]
150
- HeadingComponent._settings = nil
145
+ HeadingComponent._defaults = {}
151
146
  HeadingComponent._template_name = nil
152
147
  end
153
148
  end
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.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Hite