upholsterer 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d3dd008b546feae2ddff4f38335af3f31d6c840d
4
+ data.tar.gz: f9ea4a88970b4c410317603bb52356926e8bfe3e
5
+ SHA512:
6
+ metadata.gz: 41a567e2724c898933ae141d9b63fbaa875d37e3c7a0aadcab3e69914d9a46910750074a053df88adde0828c58d5c8117c44ddf393f537f0fd579f52a0c94561
7
+ data.tar.gz: 720f8af029261deb38042c76c951be4a82b92932c956a4b2fc01d084363e87eabcf54d81c56c4bc8577f36c65a594b97dd44226d207996250611c323c0126301
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ pkg
3
+ tmp
4
+ .tags
5
+ .idea
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format documentation
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ upholsterer (0.3.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ awesome_print (1.2.0)
10
+ coderay (1.0.9)
11
+ diff-lcs (1.2.4)
12
+ method_source (0.8.2)
13
+ pry (0.9.12.2)
14
+ coderay (~> 1.0.5)
15
+ method_source (~> 0.8)
16
+ slop (~> 3.4)
17
+ pry-meta (0.0.5)
18
+ awesome_print
19
+ pry
20
+ pry-nav
21
+ pry-remote
22
+ pry-nav (0.2.3)
23
+ pry (~> 0.9.10)
24
+ pry-remote (0.1.7)
25
+ pry (~> 0.9)
26
+ slop (~> 3.0)
27
+ rake (10.1.0)
28
+ rspec (2.14.1)
29
+ rspec-core (~> 2.14.0)
30
+ rspec-expectations (~> 2.14.0)
31
+ rspec-mocks (~> 2.14.0)
32
+ rspec-core (2.14.6)
33
+ rspec-expectations (2.14.3)
34
+ diff-lcs (>= 1.1.3, < 2.0)
35
+ rspec-mocks (2.14.4)
36
+ slop (3.4.6)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ pry-meta
43
+ rake
44
+ rspec
45
+ upholsterer!
@@ -0,0 +1,88 @@
1
+ = upholsterer
2
+
3
+ Based on SimplePresenter (https://github.com/fnando/simple_presenter)
4
+
5
+ == Installation
6
+
7
+ gem install upholsterer
8
+
9
+ == Usage
10
+
11
+ class User < ActiveRecord::Base
12
+ # implements the following attributes: name, email, password_hash, password_salt
13
+ end
14
+
15
+ class UserPresenter < Upholsterer::Base
16
+ expose :name, :email
17
+ end
18
+
19
+ or
20
+
21
+ class UserPresenter < Upholsterer::Base
22
+ expose_all
23
+ end
24
+
25
+ user = UserPresenter.new(User.first)
26
+ users = UserPresenter.map(User.all)
27
+
28
+ If you're using Upholsterer within Rails, presenters also have access to:
29
+
30
+ * route helpers: just use the <tt>routes</tt> or <tt>r</tt> methods
31
+ * view helpers: just use the <tt>helpers</tt> or <tt>h</tt> methods
32
+ * I18n methods: just use the <tt>translate</tt>, <tt>t</tt>, <tt>localize</tt> or <tt>l</tt> methods
33
+
34
+ If you want to to use <tt>*_url</tt> route methods, make sure you set the <tt>default_url_options</tt> option. You can use the <tt>config.upholsterer.default_url_options</tt> method, which defaults to <tt>config.action_mailer.default_url_options</tt>. You can add something like the following to your <tt>config/environments/development.rb</tt>, for instance:
35
+
36
+ config.upholsterer.default_url_options = {:host => "localhost:3000"}
37
+
38
+ For additional usage, check the specs.
39
+
40
+ == TO-DO
41
+
42
+ * Recognize ActiveRecord objects and automatically expose attributes used by url and form helpers (like <tt>Model.model_name</tt>, <tt>Model#to_key</tt>, and <tt>Model#to_param</tt>).
43
+ * Override <tt>respond_to?</tt> to reflect exposed attributes.
44
+
45
+ == Troubleshooting
46
+
47
+ If you're having problems because already have a class/module called Presenter that is conflicting with this gem, you can require the namespace and inherit from <tt>Upholsterer::Base</tt>.
48
+
49
+ require "upholsterer/namespace"
50
+
51
+ class UserPresenter < Upholsterer::Base
52
+ end
53
+
54
+ If you're using Rails/Bundler or something like that, remember to override the <tt>:require</tt> option.
55
+
56
+ # Gemfile
57
+ source :rubygems
58
+
59
+ gem "upholsterer", :require => "upholsterer/namespace"
60
+
61
+ == Maintainer
62
+
63
+ * Nando Vieira (http://nandovieira.com.br)
64
+ * Aleksandr Fomin (https://github.com/llxff)
65
+ * Gleb Sinyavsky (http://github.com/zhulik)
66
+
67
+ == License
68
+
69
+ (The MIT License)
70
+
71
+ Permission is hereby granted, free of charge, to any person obtaining
72
+ a copy of this software and associated documentation files (the
73
+ 'Software'), to deal in the Software without restriction, including
74
+ without limitation the rights to use, copy, modify, merge, publish,
75
+ distribute, sublicense, and/or sell copies of the Software, and to
76
+ permit persons to whom the Software is furnished to do so, subject to
77
+ the following conditions:
78
+
79
+ The above copyright notice and this permission notice shall be
80
+ included in all copies or substantial portions of the Software.
81
+
82
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
83
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
84
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
85
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
86
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
87
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
88
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rspec/core/rake_task"
5
+ RSpec::Core::RakeTask.new
6
+
7
+ task default: :spec
@@ -0,0 +1,2 @@
1
+ require 'upholsterer/namespace'
2
+ Presenter = Upholsterer::Base
@@ -0,0 +1,163 @@
1
+ module Upholsterer
2
+ class Base
3
+ # Define how many subjects this presenter will receive.
4
+ # Each subject will create a private method with the same name.
5
+ #
6
+ # The first subject name will be used as default, thus isn't required as <tt>:with</tt>
7
+ # option on the Upholsterer::Base.expose method.
8
+ #
9
+ # class CommentPresenter < Presenter
10
+ # subjects :comment, :post
11
+ # expose :body # will expose comment.body through CommentPresenter#body
12
+ # expose :title, :with => :post # will expose post.title through CommentPresenter#post_title
13
+ # end
14
+ #
15
+ # Subjects can be accessed by a private name with the same name.
16
+ # So the above subjects can be accessed internally by the methods +comment+ and +post+.
17
+ #
18
+ # If you're not setting any special name, then you can access it using the +subject+ method.
19
+ #
20
+
21
+ attr_reader :subject
22
+
23
+ def self.subjects(*names)
24
+ @subjects ||= [:subject]
25
+
26
+ unless names.empty?
27
+ @subjects = names
28
+ attr_reader *names
29
+ end
30
+
31
+ @subjects
32
+ end
33
+
34
+ class << self
35
+ alias_method :subject, :subjects
36
+ end
37
+
38
+ # Propagate inherited subjects and attributes.
39
+ #
40
+ def self.inherited(child)
41
+ child.subjects(*subjects)
42
+ attributes.each_value do |attr_name, options|
43
+ child.expose(attr_name, options)
44
+ end
45
+ end
46
+
47
+ # Store all attributes and options that have been exposed.
48
+ #
49
+ # class UserPresenter < Presenter
50
+ # expose :name
51
+ # expose :street, with: "address"
52
+ # end
53
+ #
54
+ # UserPresenter.attributes
55
+ # #=> {
56
+ # #=> name: [:name, {}],
57
+ # #=> address_street: [:street, {with: "address"}]
58
+ # #=> }
59
+ #
60
+ def self.attributes
61
+ @attributes ||= {}
62
+ end
63
+
64
+ # This method will return a presenter for each item of collection.
65
+ #
66
+ # users = UserPresenter.map(User.all)
67
+ #
68
+ # If your presenter accepts more than one subject, you can provided
69
+ # them as following parameters.
70
+ #
71
+ # comments = CommentPresenter.map(post.comment.all, post)
72
+ #
73
+ def self.map(collection, *subjects)
74
+ collection.map {|item| new(item, *subjects)}
75
+ end
76
+
77
+ # The list of attributes that will be exposed.
78
+ #
79
+ # class UserPresenter < Presenter
80
+ # expose :name, :email
81
+ # end
82
+ #
83
+ # You can also expose an attribute from a composition.
84
+ #
85
+ # class CommentPresenter < Presenter
86
+ # expose :body, :created_at
87
+ # expose :name, :with => :user
88
+ # expose :name, :as => :author
89
+ # end
90
+ #
91
+ # The presenter above will expose the methods +body+, +created_at+, and +user_name+.
92
+ # Additionaly, it will create an alias called +author+ to the +name+ attribute.
93
+ #
94
+ def self.expose(*attrs)
95
+ options = attrs.pop if attrs.last.kind_of?(Hash)
96
+ options ||= {}
97
+
98
+ attrs.each do |attr_name|
99
+ subject = options.fetch(:with, nil)
100
+
101
+ method_name = [
102
+ subject,
103
+ options.fetch(:as, attr_name)
104
+ ].compact.join("_")
105
+
106
+ attributes[method_name.to_sym] = [attr_name, options]
107
+
108
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
109
+ def #{method_name}(&block) # def user_name(&block)
110
+ proxy_message(#{subject.inspect}, "#{attr_name}", &block) # proxy_message("user", "name")
111
+ end # end
112
+ RUBY
113
+ end
114
+ end
115
+
116
+ def self.expose_all
117
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
118
+ def method_missing(name, *params)
119
+ @subject.send(name, *params)
120
+ end
121
+
122
+ def respond_to?(name)
123
+ super || @subject.respond_to?(name)
124
+ end
125
+ RUBY
126
+ end
127
+
128
+ # It assigns the subjects.
129
+ #
130
+ # user = UserPresenter.new(User.first)
131
+ #
132
+ # You can assign several subjects if you want.
133
+ #
134
+ # class CommentPresenter < Presenter
135
+ # subject :comment, :post
136
+ # expose :body
137
+ # expose :title, :with => :post
138
+ # end
139
+ #
140
+ # comment = CommentPresenter.new(Comment.first, Post.first)
141
+ #
142
+ # If the :with option specified to one of the subjects, then the default subject is bypassed.
143
+ # Otherwise, it will be proxied to the default subject.
144
+ #
145
+ def initialize(*subjects)
146
+ self.class.subjects.each_with_index do |name, index|
147
+ instance_variable_set("@#{name}", subjects[index])
148
+ end
149
+ end
150
+
151
+ def to_param(*params)
152
+ @subject.to_param(*params)
153
+ end
154
+
155
+ private
156
+ def proxy_message(subject_name, method, &block)
157
+ subject_name ||= self.class.subjects.first
158
+ subject = instance_variable_get("@#{subject_name}")
159
+ subject = instance_variable_get("@#{self.class.subjects.first}").__send__(subject_name) unless subject || self.class.subjects.include?(subject_name)
160
+ subject.respond_to?(method) ? subject.__send__(method, &block) : nil
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,6 @@
1
+ module Upholsterer
2
+ require "upholsterer/base"
3
+ require "upholsterer/version"
4
+ require "upholsterer/url_methods"
5
+ require "upholsterer/rails" if defined?(Rails)
6
+ end
@@ -0,0 +1,30 @@
1
+ module Upholsterer
2
+ class Railtie < Rails::Railtie
3
+ config.upholsterer = ActiveSupport::OrderedOptions.new
4
+ end
5
+
6
+ class Base
7
+ delegate :translate, :t, :localize, :l, :to => :helpers
8
+
9
+ def self.routes_module
10
+ @routes_module ||= Module.new do
11
+ include Rails.application.routes.url_helpers
12
+ include UrlMethods
13
+ end
14
+ end
15
+
16
+ def self.routes
17
+ @routes ||= Object.new.extend(routes_module)
18
+ end
19
+
20
+ def routes
21
+ self.class.routes
22
+ end
23
+ alias_method :r, :routes
24
+
25
+ def helpers
26
+ ApplicationController.helpers
27
+ end
28
+ alias_method :h, :helpers
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ module Upholsterer
2
+ module UrlMethods
3
+ def default_url_options
4
+ Rails.configuration.upholsterer.default_url_options ||
5
+ Rails.configuration.action_mailer.default_url_options ||
6
+ {}
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module Upholsterer
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 3
5
+ PATCH = 1
6
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
+ end
8
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'upholsterer/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'upholsterer'
7
+ s.version = Upholsterer::Version::STRING
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Nando Vieira', 'Aleksandr Fomin', 'Gleb Sinyavsky']
10
+ s.email = ['fnando.vieira@gmail.com', 'll.wg.bin@gmail.com']
11
+ s.homepage = 'https://github.com/llxff/upholsterer'
12
+ s.summary = 'A simple presenter/facade/decorator/whatever implementation.'
13
+ s.description = s.summary
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split($/).map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency 'rake'
21
+ s.add_development_dependency 'rspec'
22
+ s.add_development_dependency 'pry-meta'
23
+ end
@@ -0,0 +1,171 @@
1
+ require "spec_helper"
2
+
3
+ describe Upholsterer::Base do
4
+ describe ".expose" do
5
+ context "not using :with option" do
6
+ subject { UserPresenter.new }
7
+
8
+ it { should respond_to(:name) }
9
+ it { should respond_to(:email) }
10
+ it { should_not respond_to(:password_hash) }
11
+ it { should_not respond_to(:password_salt) }
12
+ end
13
+
14
+ context "using :with option" do
15
+ subject { CommentPresenter.new }
16
+
17
+ it { should respond_to(:user_name) }
18
+ end
19
+
20
+ context "using :as option" do
21
+ let(:site) { OpenStruct.new(:site => "http://example.org") }
22
+ subject { AliasPresenter.new(site) }
23
+
24
+ it { should respond_to(:url) }
25
+ it { expect(subject.url).to eql("http://example.org") }
26
+ end
27
+
28
+ context "exposing iterators" do
29
+ subject { IteratorPresenter.new([1, 2, 3]) }
30
+
31
+ its(:each) { should be_a(Enumerator) }
32
+
33
+ it "uses provided block" do
34
+ numbers = []
35
+ subject.each {|n| numbers << n}
36
+ expect(numbers).to eql([1, 2, 3])
37
+ end
38
+ end
39
+ end
40
+
41
+ describe ".attributes" do
42
+ context "using defaults" do
43
+ let(:presenter) { UserPresenter }
44
+ subject { presenter.attributes }
45
+
46
+ it { should have(2).items }
47
+ its([:name]) { should eql([:name, {}]) }
48
+ its([:email]) { should eql([:email, {}]) }
49
+ end
50
+
51
+ context "using provided options" do
52
+ let(:presenter) { CommentPresenter }
53
+ subject { presenter.attributes }
54
+
55
+ it { should have(3).items }
56
+ its([:user_name]) { should eql([:name, {with: :user}]) }
57
+ its([:post_title]) { should eql([:title, {with: :post}]) }
58
+ end
59
+ end
60
+
61
+ describe ".subjects" do
62
+ it "is aliased as .subject" do
63
+ thing = double("Thing")
64
+ presenter_class = Class.new(Presenter)
65
+ presenter_class.subject :thing
66
+ presenter = presenter_class.new(thing)
67
+
68
+ expect(presenter.instance_variable_get("@thing")).to eql(thing)
69
+ end
70
+
71
+ context "using defaults" do
72
+ let(:user) { double :name => "John Doe", :email => "john@doe.com" }
73
+ subject { UserPresenter.new(user) }
74
+
75
+ its(:name) { should == "John Doe" }
76
+ its(:email) { should == "john@doe.com" }
77
+
78
+ it "responds to private subject method" do
79
+ expect(subject.public_methods).to include(:subject)
80
+ end
81
+
82
+ it "returns subject" do
83
+ expect(subject.send(:subject)).to eql(user)
84
+ end
85
+ end
86
+
87
+ context "specifying several subjects" do
88
+ let(:user) { double :name => "John Doe" }
89
+ let(:comment) { double :body => "Some comment", :user => user }
90
+ let(:post) { double :title => "Some post" }
91
+ subject { CommentPresenter.new(comment, post) }
92
+
93
+ its(:body) { should == "Some comment" }
94
+ its(:post_title) { should == "Some post" }
95
+ its(:user_name) { should == "John Doe" }
96
+
97
+ it "responds to private comment method" do
98
+ expect(subject.public_methods).to include(:comment)
99
+ end
100
+
101
+ it "responds to private post method" do
102
+ expect(subject.public_methods).to include(:post)
103
+ end
104
+
105
+ it "returns comment subject" do
106
+ expect(subject.send(:comment)).to eql(comment)
107
+ end
108
+
109
+ it "returns post subject" do
110
+ expect(subject.send(:post)).to eql(post)
111
+ end
112
+ end
113
+
114
+ context "when subjects are nil" do
115
+ let(:comment) { double :body => "Some comment" }
116
+ subject { CommentPresenter.new(comment, nil) }
117
+
118
+ its(:post_title) { should be_nil }
119
+ end
120
+ end
121
+
122
+ describe ".map" do
123
+ context "wraps a single subject" do
124
+ let(:user) { double :name => "John Doe" }
125
+ subject { UserPresenter.map([user])[0] }
126
+
127
+ it { should be_a(UserPresenter) }
128
+ its(:name) { should == "John Doe" }
129
+ end
130
+
131
+ context "wraps several subjects" do
132
+ let(:comment) { double :body => "Some comment" }
133
+ let(:post) { double :title => "Some post" }
134
+ let(:user) { double :name => "John Doe" }
135
+ subject { CommentPresenter.map([comment], post)[0] }
136
+
137
+ it { should be_a(CommentPresenter) }
138
+ its(:body) { should == "Some comment" }
139
+ its(:post_title) { should == "Some post" }
140
+ end
141
+ end
142
+
143
+ describe "#initialize" do
144
+ let(:user) { double }
145
+ subject { UserPresenter.new(user) }
146
+
147
+ it "assigns the subject" do
148
+ expect(subject.instance_variable_get("@subject")).to eql(user)
149
+ end
150
+ end
151
+
152
+ describe "inherited presenter" do
153
+ let(:presenter) { Class.new(CommentPresenter) }
154
+
155
+ context "subjects" do
156
+ subject { presenter.subjects }
157
+
158
+ specify { expect(subject).to have(2).items }
159
+ specify { expect(subject.first).to eql(:comment) }
160
+ specify { expect(subject.last).to eql(:post) }
161
+ end
162
+
163
+ context "attributes" do
164
+ subject { presenter.attributes }
165
+
166
+ it { should have(3).items }
167
+ its([:user_name]) { should eql([:name, {with: :user}]) }
168
+ its([:post_title]) { should eql([:title, {with: :post}]) }
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,9 @@
1
+ require "bundler/setup"
2
+ Bundler.require(:default, :development)
3
+
4
+ require "upholsterer"
5
+ require "ostruct"
6
+
7
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each do |file|
8
+ require file
9
+ end
@@ -0,0 +1,4 @@
1
+ class AliasPresenter < Presenter
2
+ expose :site
3
+ expose :site, :as => :url
4
+ end
@@ -0,0 +1,7 @@
1
+ class Comment
2
+ attr_accessor :body, :created_at, :user
3
+
4
+ def initialize(attrs = {})
5
+ attrs.each {|name, value| __send__("#{name}=", value)}
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class CommentPresenter < Presenter
2
+ expose :body
3
+ expose :name, :with => :user
4
+ expose :title, :with => :post
5
+
6
+ subjects :comment, :post
7
+ end
@@ -0,0 +1,3 @@
1
+ class IteratorPresenter < Presenter
2
+ expose :each
3
+ end
@@ -0,0 +1,7 @@
1
+ class User
2
+ attr_accessor :name, :email, :password_salt, :password_hash
3
+
4
+ def initialize(attrs = {})
5
+ attrs.each {|name, value| __send__("#{name}=", value)}
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ class UserPresenter < Presenter
2
+ expose :name, :email
3
+ end
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ describe Upholsterer do
4
+ it "assigns Upholsterer::Base" do
5
+ expect(::Presenter).to be(Upholsterer::Base)
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: upholsterer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Nando Vieira
8
+ - Aleksandr Fomin
9
+ - Gleb Sinyavsky
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-12-05 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rspec
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: pry-meta
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ description: A simple presenter/facade/decorator/whatever implementation.
58
+ email:
59
+ - fnando.vieira@gmail.com
60
+ - ll.wg.bin@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - ".gitignore"
66
+ - ".rspec"
67
+ - Gemfile
68
+ - Gemfile.lock
69
+ - README.rdoc
70
+ - Rakefile
71
+ - lib/upholsterer.rb
72
+ - lib/upholsterer/base.rb
73
+ - lib/upholsterer/namespace.rb
74
+ - lib/upholsterer/rails.rb
75
+ - lib/upholsterer/url_methods.rb
76
+ - lib/upholsterer/version.rb
77
+ - simple_presenter.gemspec
78
+ - spec/base_spec.rb
79
+ - spec/spec_helper.rb
80
+ - spec/support/alias_presenter.rb
81
+ - spec/support/comment.rb
82
+ - spec/support/comment_presenter.rb
83
+ - spec/support/iterator_presenter.rb
84
+ - spec/support/user.rb
85
+ - spec/support/user_presenter.rb
86
+ - spec/upholsterer_spec.rb
87
+ homepage: https://github.com/llxff/upholsterer
88
+ licenses: []
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.2.2
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: A simple presenter/facade/decorator/whatever implementation.
110
+ test_files: []