garnish 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ 0.0.4 (February 16, 2012)
2
+
3
+ * Overhaul on how relationships are manager by a Collection class now.
4
+ Addresses method chaining issues on relationships.
5
+
1
6
  0.0.3 (February 1, 2012)
2
7
 
3
8
  * Version bump so I can push new version to rubygems
data/Gemfile CHANGED
@@ -1,5 +1,10 @@
1
1
  source "http://rubygems.org"
2
2
 
3
+ gem 'rake'
4
+ gem 'activesupport'
5
+ gem 'actionpack'
6
+ gem 'i18n' #Why doesn't activesupport require this?
7
+
3
8
  group :development do
4
9
  gem 'guard'
5
10
  gem 'guard-rspec'
data/Guardfile CHANGED
@@ -18,7 +18,7 @@ guard 'spin' do
18
18
  watch('Guardfile')
19
19
  end
20
20
 
21
- guard 'rspec', :cli => "--drb --color --order random", :version => 2, :rvm => ['1.9.3'] do
21
+ guard 'rspec', :cli => "--color --order random", :version => 2, :rvm => ['1.9.3'] do
22
22
  watch(%r{^spec/.+_spec\.rb$})
23
23
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
24
24
  watch('spec/spec_helper.rb') { "spec" }
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Brian Pearce
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -2,7 +2,7 @@
2
2
 
3
3
  RDocs[http://rdoc.info/projects/brianp/garnish]
4
4
 
5
- Garnish is a Presenter / Decorator pattern for models in Rails. It gives a home to presntation level view logic that normally litters helpers and view files. Using it can help you:
5
+ Garnish is a Presenter / Decorator pattern for models in Rails. It gives a home to presentation level view logic that normally litters helpers and view files. Using it can help you:
6
6
 
7
7
  * Keep helper files and views clean of if/else statements and other logic
8
8
  * Better define an interface for views to interact with models
@@ -10,6 +10,13 @@ Garnish is a Presenter / Decorator pattern for models in Rails. It gives a home
10
10
  * Keep you controller code clean by never having to instantiate the presenters
11
11
  * Handle Decorating / Presenting standard Rails relationships
12
12
 
13
+ == Requirements
14
+
15
+ Garnish Has been tested with
16
+
17
+ * Rails 3
18
+ * Ruby 1.9.2, 1.9.3
19
+
13
20
  == Installation
14
21
 
15
22
  In <b>Rails 3</b>, add this to your Gemfile and run the +bundle+ command.
@@ -35,12 +42,11 @@ Define the user_presenter
35
42
 
36
43
  module UserPresenter
37
44
  include Garnish::Presenter
38
-
39
45
  end
40
46
 
41
47
  === 2. Add methods to your presenter
42
48
 
43
- Define method in your presenter as regular instance methods
49
+ Define methods in your presenter as regular instance methods
44
50
 
45
51
  module UserPresenter
46
52
  include Garnish::Presenter
@@ -83,12 +89,59 @@ The only change you need to make to start using your presenters now is to use re
83
89
 
84
90
  Garnish will now find and load presenters for any instance variables you set inside your action. *NOT* just the ivar passed to the respond_with block.
85
91
 
86
- == 5. Start using your presenter methods
92
+ === 5. Start using your presenter methods
87
93
 
88
94
  <tt>app/views/users/show.html.erb</tt>
89
95
 
90
96
  <span><%= @user.greeting %></span>
91
97
 
98
+ == View Helpers
99
+
100
+ Garnish plays very nicely when adding view helper methods into your presenter. Just treat them like a regular method.
101
+
102
+ module UserPresenter
103
+ include Garnish::Presenter
104
+
105
+ def profile_pic
106
+ image_tag profile_pic unless profile_pic.nil?
107
+ end
108
+ end
109
+
110
+ == Relationships
111
+
112
+ The real reason I got down to business. If I'm using presenters in my views I probably have presenters for multiple objects.
113
+
114
+ class User < ActiveRecord::Base
115
+ has_many :items
116
+ end
117
+
118
+ class Item < ActiveRecord::Base
119
+ belongs_to :user
120
+ end
121
+
122
+ Assuming I have presenters for both of these models
123
+
124
+ module UserPresenter
125
+ include Garnish::Presenter
126
+ end
127
+
128
+ module ItemPresenter
129
+ include Garnish::Presenter
130
+
131
+ def picture
132
+ image_tag profile_pic unless profile_pic.nil?
133
+ end
134
+ end
135
+
136
+
137
+ In my view when I'm accessing a user's items via the association what I really want is an Item extended with presenter methods not just a regular item.
138
+
139
+ Garnish handles this for us. Anytime a relationship is accessed on a garnished resource the returned resources will also be extended with their presenter methods.
140
+
141
+ <%= @user.items.first.picture %>
142
+
143
+ Works with no effort what so ever.
144
+
92
145
  == Questions or Problems?
93
146
 
94
147
  If you have any issues with Garnish which you cannot find the solution to, please add an {issue on GitHub}[https://github.com/brianp/garnish/issues] or fork the project and send a pull request.
@@ -97,4 +150,8 @@ To get the specs running you should call +bundle+ and then +rake+. See the {spec
97
150
 
98
151
  == Special Thanks
99
152
 
153
+ {Fraser Valley Ruby Brigade}[http://www.fvrb.org/]
154
+
155
+ The Ruby Moguls
156
+
100
157
  Garnish was inspired by draper[https://github.com/jcasimir/draper/] and the RailsCast Pro episode #287 Presenters from Scratch. See the CHANGELOG[https://github.com/brianp/garnish/blob/master/CHANGELOG.rdoc] for the full list.
@@ -4,6 +4,7 @@ require 'garnish/responder'
4
4
  require 'garnish/controller'
5
5
  require 'garnish/presenter/relationships'
6
6
  require 'garnish/presenter'
7
+ require 'garnish/collection'
7
8
 
8
9
  require 'garnish/model_adapters/abstract_adapter'
9
10
  require 'garnish/model_adapters/default_adapter'
@@ -0,0 +1,51 @@
1
+ module Garnish
2
+ class Collection
3
+ include Enumerable
4
+ include Garnish::Converter
5
+
6
+ attr_accessor :relation
7
+ attr_accessor :template
8
+
9
+ delegate :avg, :max, :min, :sum, :length, :size, :count, :to => :relation
10
+
11
+ def initialize(relation, template)
12
+ @relation = relation
13
+ @template = template
14
+ end
15
+
16
+ # Call the method on the relation object and then convert the results
17
+ #
18
+ # @example
19
+ # blog.posts.each { |post| post.name }
20
+ #
21
+ # @return [Collection]
22
+ [:to_a, :each].map do |method|
23
+ define_method method do
24
+ records = @relation.send(method)
25
+ convert(records)
26
+ records
27
+ end
28
+ end
29
+
30
+ def respond_to?(method)
31
+ @relation.respond_to?(method)
32
+ end
33
+
34
+ protected
35
+
36
+ def method_missing(method, *args, &block)
37
+ resp = @relation.send(method, *args, &block)
38
+
39
+ if resp.equal? @relation
40
+ self
41
+ elsif resp.instance_of? @relation.class
42
+ Garnish::Collection.new(resp, @template)
43
+ elsif resp.respond_to? :each
44
+ Garnish::Collection.new(resp, @template)
45
+ else
46
+ convert(resp)
47
+ resp
48
+ end
49
+ end
50
+ end
51
+ end
@@ -3,6 +3,15 @@ module Garnish
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  module ClassMethods
6
+ # Set the responder and respond_to formats
7
+ #
8
+ # @example
9
+ # class ApplicationController < ActionController::Base
10
+ # protect_from_forgery
11
+ # garnish
12
+ # end
13
+ #
14
+ # @return [undefined]
6
15
  def garnish(options = {}, &block)
7
16
  self.responder = Garnish::Responder
8
17
  respond_to :html
@@ -11,8 +11,7 @@ module Garnish
11
11
  alias_method "#{key}_orig".to_sym, key.to_sym
12
12
  define_method "#{key}" do |opts = nil, *rest|
13
13
  records = self.send("#{key}_orig")
14
- convert(records)
15
- records
14
+ Garnish::Collection.new(records, template)
16
15
  end
17
16
  end
18
17
  end
@@ -1,3 +1,3 @@
1
1
  module Garnish
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Garnish::Collection do
4
+
5
+ let(:relation) { stub(:relation) }
6
+ let(:template) { stub(:template) }
7
+ let(:collection) { Garnish::Collection.new(relation, template) }
8
+
9
+ it "should init with a relation record" do
10
+ collection.relation.should eq(relation)
11
+ end
12
+
13
+ it "should pass the each method to the relation" do
14
+ relation.should_receive(:each)
15
+ collection.each
16
+ end
17
+
18
+ it "should pass the to_a method to the relation" do
19
+ relation.should_receive(:to_a)
20
+ collection.to_a
21
+ end
22
+
23
+ describe "method chains should return the existing collection" do
24
+ it "should be the same collection" do
25
+ relation.stub(:limit => collection)
26
+ collection.limit(1).should eq(collection)
27
+ end
28
+
29
+ it "should be the same collection" do
30
+ relation.stub(:limit => collection, :order => collection)
31
+ collection.limit(1).order(:desc).should eq(collection)
32
+ end
33
+ end
34
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "A Garnished Controller" do
3
+ describe Garnish::Controller do
4
4
 
5
5
  subject { TestController }
6
6
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "A Garnish Converter" do
3
+ describe Garnish::Converter do
4
4
 
5
5
  context "instance" do
6
6
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "A Presenter Relationship" do
3
+ describe Garnish::Presenter::Relationships do
4
4
 
5
5
  let(:test_class) { TestClass.new }
6
6
  before { test_class.extend Garnish::Presenter::Relationships }
@@ -11,7 +11,8 @@ describe "A Presenter Relationship" do
11
11
  end
12
12
 
13
13
  it "should call convert on the records of the relationship" do
14
- test_class.should_receive(:convert)
14
+ test_class.stub(:template => stub)
15
+ Garnish::Collection.should_receive(:new)
15
16
  test_class.users
16
17
  end
17
18
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "A Garnish Presenter" do
3
+ describe Garnish::Presenter do
4
4
 
5
5
  let(:test_class) { TestClass.new }
6
6
  before { TestClass.send :include, TestClassPresenter }
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "The Garnished Responder" do
3
+ describe Garnish::Responder do
4
4
 
5
5
  let(:responder) { Garnish::Responder.new(controller, resources) }
6
6
  let(:formats) { stub(:formats, :first => nil) }
metadata CHANGED
@@ -1,71 +1,57 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: garnish
3
- version: !ruby/object:Gem::Version
4
- hash: 25
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 3
10
- version: 0.0.3
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - brianp
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-02-01 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-02-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: activesupport
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70340124404820 !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 7
29
- segments:
30
- - 3
31
- - 0
32
- - 0
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
33
21
  version: 3.0.0
34
22
  type: :runtime
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: rspec
38
23
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *70340124404820
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70340124404220 !ruby/object:Gem::Requirement
40
28
  none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 3
45
- segments:
46
- - 0
47
- version: "0"
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
48
33
  type: :development
49
- version_requirements: *id002
50
- description: Provides an easy to use and transparent system for implementing the Decorator Pattern
51
- email:
34
+ prerelease: false
35
+ version_requirements: *70340124404220
36
+ description: Provides an easy to use and transparent system for implementing the Decorator
37
+ Pattern
38
+ email:
52
39
  - brian.o.pearce@gmail.com
53
40
  executables: []
54
-
55
41
  extensions: []
56
-
57
42
  extra_rdoc_files: []
58
-
59
- files:
43
+ files:
60
44
  - .gitignore
61
45
  - .travis.yml
62
46
  - CHANGELOG.rdoc
63
47
  - Gemfile
64
48
  - Guardfile
49
+ - LICENSE
65
50
  - README.rdoc
66
51
  - Rakefile
67
52
  - garnish.gemspec
68
53
  - lib/garnish.rb
54
+ - lib/garnish/collection.rb
69
55
  - lib/garnish/controller.rb
70
56
  - lib/garnish/converter.rb
71
57
  - lib/garnish/model_adapters/abstract_adapter.rb
@@ -77,47 +63,40 @@ files:
77
63
  - lib/garnish/responder.rb
78
64
  - lib/garnish/version.rb
79
65
  - spec/README.rdoc
66
+ - spec/garnish/collection_spec.rb
80
67
  - spec/garnish/controller_spec.rb
81
68
  - spec/garnish/converter_spec.rb
82
69
  - spec/garnish/presenter/relationships_spec.rb
83
70
  - spec/garnish/presenter_spec.rb
84
71
  - spec/garnish/responder_spec.rb
85
72
  - spec/spec_helper.rb
86
- homepage: ""
73
+ homepage: ''
87
74
  licenses: []
88
-
89
75
  post_install_message:
90
76
  rdoc_options: []
91
-
92
- require_paths:
77
+ require_paths:
93
78
  - lib
94
- required_ruby_version: !ruby/object:Gem::Requirement
79
+ required_ruby_version: !ruby/object:Gem::Requirement
95
80
  none: false
96
- requirements:
97
- - - ">="
98
- - !ruby/object:Gem::Version
99
- hash: 3
100
- segments:
101
- - 0
102
- version: "0"
103
- required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
86
  none: false
105
- requirements:
106
- - - ">="
107
- - !ruby/object:Gem::Version
108
- hash: 3
109
- segments:
110
- - 0
111
- version: "0"
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
112
91
  requirements: []
113
-
114
92
  rubyforge_project: garnish
115
93
  rubygems_version: 1.8.10
116
94
  signing_key:
117
95
  specification_version: 3
118
96
  summary: Provides the decorator design pattern
119
- test_files:
97
+ test_files:
120
98
  - spec/README.rdoc
99
+ - spec/garnish/collection_spec.rb
121
100
  - spec/garnish/controller_spec.rb
122
101
  - spec/garnish/converter_spec.rb
123
102
  - spec/garnish/presenter/relationships_spec.rb