decor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem "bundler", "~> 1.0.0"
5
+ gem "rake", "~> 0.8.7"
6
+ gem "rspec", "2.1.0"
7
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,21 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ rake (0.8.7)
6
+ rspec (2.1.0)
7
+ rspec-core (~> 2.1.0)
8
+ rspec-expectations (~> 2.1.0)
9
+ rspec-mocks (~> 2.1.0)
10
+ rspec-core (2.1.0)
11
+ rspec-expectations (2.1.0)
12
+ diff-lcs (~> 1.1.2)
13
+ rspec-mocks (2.1.0)
14
+
15
+ PLATFORMS
16
+ ruby
17
+
18
+ DEPENDENCIES
19
+ bundler (~> 1.0.0)
20
+ rake (~> 0.8.7)
21
+ rspec (= 2.1.0)
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require "rubygems"
2
+ require "bundler"
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+
11
+ require 'rspec/core/rake_task'
12
+ RSpec::Core::RakeTask.new do |t|
13
+ t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
14
+ t.pattern = 'spec/**/*_spec.rb'
15
+ end
16
+
17
+ task :default => :spec
data/Readme.textile ADDED
@@ -0,0 +1,159 @@
1
+ h1. Decor
2
+
3
+ Define multiple representations of an object.
4
+
5
+ "Read the documentation":http://empl.us/decor/ or see an example scenario and usage below.
6
+
7
+ h2. Scenario
8
+
9
+ You have an API. It returns provides access to a User resource. This resource:
10
+
11
+ <pre>
12
+ create_table do |t|
13
+ t.string :screen_name
14
+ t.string :state, :default => "active"
15
+ t.string :role, :default => "user"
16
+ end
17
+
18
+ class User < ActiveRecord::Base
19
+ STATES = ["active", "inactive"]
20
+ ROLES = ["user", "admin"]
21
+ end
22
+ </pre>
23
+
24
+ At one point, you had just defined booleans for @active@ and @admin@, but you have plans to expand the states and roles of a User. However, you already provide an API that you do not wish to break.
25
+
26
+ How do you transition your code and your data over and not break backwards compatibility? How do you do this modularly and in an easily testable way without making your API endpoints (controllers et al) heavy?
27
+
28
+ How about:
29
+
30
+ <pre>
31
+ class User < ActiveRecord::Base
32
+ include Decor
33
+
34
+ STATES = ["active", "inactive"]
35
+ ROLES = ["user", "admin"]
36
+
37
+ version "v1" do
38
+ def active
39
+ state == "active"
40
+ end
41
+ def admin
42
+ role == "admin"
43
+ end
44
+
45
+ def as_json(options = {})
46
+ super(options.merge(:only => [:screen_name],
47
+ :methods => [:active, :admin]))
48
+ end
49
+ end
50
+
51
+ version "v2" do
52
+ def as_json(*args)
53
+ super(options.merge(:only => [:screen_name, :state, :role]))
54
+ end
55
+ end
56
+
57
+ end
58
+ </pre>
59
+
60
+ Then, our endpoint:
61
+
62
+ <pre>
63
+ get '/api/:version/users/:id' do
64
+ @user = User.find(params[:id])
65
+ @user.for(version).to_json
66
+ end
67
+ </pre>
68
+
69
+ You can also include external resources providing some contextual influence over how your resources choose to represent themselves:
70
+
71
+ <pre>
72
+ class User < ActiveRecord::Base
73
+ include Decor
74
+
75
+ version "v3" do
76
+ def screen_name
77
+ "%s (%s)" % [super, organization.name]
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ get '/api/:version/organizations/:org_id/users/:id' do
84
+ @organization = Organization.find(params[:org_id])
85
+ @user = User.find(params[:id]).for(version, :organization => @organization)
86
+ @user.to_json
87
+ end
88
+ </pre>
89
+
90
+ h2. Example Usage
91
+
92
+ Defining your class and versions:
93
+
94
+ <pre>
95
+ class Resource < Struct.new(:name, :value)
96
+ include Decor
97
+
98
+ version "v1" do
99
+ # a computed value specific to this version
100
+ def computed
101
+ value * 10
102
+ end
103
+ end
104
+
105
+ version "v2" do
106
+ # overloaded name
107
+ def name
108
+ super.reverse
109
+ end
110
+
111
+ # different computed value for this version
112
+ def computed
113
+ value * 100
114
+ end
115
+ end
116
+
117
+ def unversioned
118
+ "yes"
119
+ end
120
+ end
121
+ </pre>
122
+
123
+ Using the versioned instance:
124
+
125
+ <pre>
126
+ resource = resource.for(version)
127
+ </pre>
128
+
129
+ h2. Contributing
130
+
131
+ Feel free to open "Issues":https://github.com/mtodd/decor/issues or fork and create "Pull Requests":https://github.com/mtodd/decor/pulls.
132
+
133
+ The minimum for contribution is a failing spec. If you can at least convey what the problem is or the feature you'd like to add in a failing spec, I will be much more motivated to fix the issue or add the feature.
134
+
135
+ If you'd like to fix the bug or implement the feature yourself, feel free to! Please document and test your code thoroughly and in similar fashion to what already exists.
136
+
137
+ h2. Copyright and License
138
+
139
+ The MIT License
140
+
141
+ Copyright (c) 2010 Matt Todd.
142
+
143
+ Permission is hereby granted, free of charge, to any person obtaining a copy
144
+ of this software and associated documentation files (the "Software"), to deal
145
+ in the Software without restriction, including without limitation the rights
146
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
147
+ copies of the Software, and to permit persons to whom the Software is
148
+ furnished to do so, subject to the following conditions:
149
+
150
+ The above copyright notice and this permission notice shall be included in
151
+ all copies or substantial portions of the Software.
152
+
153
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
155
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
156
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
157
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
158
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
159
+ THE SOFTWARE.
data/decor.gemspec ADDED
@@ -0,0 +1,52 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{decor}
3
+ s.version = "0.1.0"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Matt Todd"]
7
+ s.date = %q{2010-12-13}
8
+ s.description = %q{Provides a simple way to define multiple representations of an object}
9
+ s.email = %q{chiology@gmail.com}
10
+ s.files = [
11
+ "decor.gemspec",
12
+ "Gemfile",
13
+ "Gemfile.lock",
14
+ "Rakefile",
15
+ "Readme.textile",
16
+ "lib/decor.rb",
17
+ "spec/decor_spec.rb",
18
+ "spec/models/bare.rb",
19
+ "spec/models/resource.rb",
20
+ "spec/spec_helper.rb"
21
+ ]
22
+ s.homepage = %q{http://empl.us/decor/}
23
+ s.licenses = ["MIT"]
24
+ s.require_paths = ["lib"]
25
+ s.rubygems_version = %q{1.3.7}
26
+ s.summary = %q{Defines multiple representations of objects}
27
+ s.test_files = [
28
+ "spec/spec_helper.rb",
29
+ "spec/decor_spec.rb",
30
+ "spec/models/bare.rb",
31
+ "spec/models/resource.rb"
32
+ ]
33
+
34
+ if s.respond_to? :specification_version then
35
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
36
+ s.specification_version = 3
37
+
38
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
39
+ s.add_development_dependency("bundler", ["~> 1.0.0"])
40
+ s.add_development_dependency("rake", ["~> 0.8.7"])
41
+ s.add_development_dependency("rspec", ["= 2.1.0"])
42
+ else
43
+ s.add_dependency("bundler", ["~> 1.0.0"])
44
+ s.add_dependency("rake", ["~> 0.8.7"])
45
+ s.add_dependency("rspec", ["= 2.1.0"])
46
+ end
47
+ else
48
+ s.add_dependency("bundler", ["~> 1.0.0"])
49
+ s.add_dependency("rake", ["~> 0.8.7"])
50
+ s.add_dependency("rspec", ["= 2.1.0"])
51
+ end
52
+ end
data/lib/decor.rb ADDED
@@ -0,0 +1,317 @@
1
+ # Decor provides a simple way to define multiple representations of an object.
2
+ #
3
+ # This is useful for when you want to retain multiple versions of your objects
4
+ # while providing a consistent interface between versions.
5
+ #
6
+ # For example:
7
+ #
8
+ # class Company < ActiveRecord::Base
9
+ # include Decor
10
+ #
11
+ # # the first version, customers are dependent on certain artifacts
12
+ # # like industry_id and industry
13
+ # version "v1" do
14
+ # INDUSTRIES = {1 => "Farm",
15
+ # 2 => "Software"}
16
+ #
17
+ # def industry
18
+ # INDUSTRIES[industry_id]
19
+ # end
20
+ #
21
+ # def as_json(*_)
22
+ # super(:only => [:id, :name, :industry_id],
23
+ # :methods => [:industry])
24
+ # end
25
+ # end
26
+ #
27
+ # # switch to using industry standard codes, cleans up the name
28
+ # version "v2" do
29
+ # SIC_CODES = {...}
30
+ #
31
+ # # use the cleaned name for the name instead
32
+ # def name
33
+ # name_cleaned
34
+ # end
35
+ #
36
+ # def industry
37
+ # SIC_DOES[sic_code]
38
+ # end
39
+ #
40
+ # def as_json(*_)
41
+ # super(:only => [:id, :name, :sic_code],
42
+ # :methods => [:industry])
43
+ # end
44
+ # end
45
+ #
46
+ # end
47
+ #
48
+ # In our API, for instance, we can then define a single endpoint for both
49
+ # versions:
50
+ #
51
+ # get "/api/:version/companies/:id.json" do
52
+ # Company.find(params[:id]).for(version).to_json
53
+ # end
54
+ #
55
+ # This helps us keep our models fat and our "controllers" skinny. This also
56
+ # helps unit testing the versions of your API.
57
+ #
58
+ # Further details can be found on [Github](https://github.com/mtodd/decor/).
59
+ #
60
+ module Decor
61
+
62
+ # Decor is a mixin. Include it into your class and then use the `version`
63
+ # class methods in the class body to define your versions, then use the
64
+ # `for` instance method on your objects to use a specific version.
65
+ #
66
+ # For example:
67
+ #
68
+ # class Model
69
+ # include Decor
70
+ #
71
+ # version "v1" do
72
+ # # implement specifics for this version here
73
+ # end
74
+ # end
75
+ #
76
+ # model = Model.new.for("v1")
77
+ #
78
+ def self.included(target)
79
+ target.send(:extend, ClassMethods)
80
+ class << target; attr_accessor :versions; end
81
+ target.versions = {}
82
+ end
83
+
84
+ module ClassMethods
85
+ # Defines versions of the model's representation.
86
+ #
87
+ # The `version` supplied is a string representation of the version.
88
+ # For example, `"v1"` represents version 1 of this model's representation.
89
+ #
90
+ # The `version` is just a key, however, and any value works. Strings are
91
+ # convenient, especially in the form of `v1` or `v2010-12-09`.
92
+ #
93
+ # If a block is provided, the block is treated as the body of the version's
94
+ # definition.
95
+ #
96
+ # If a hash of `version => version_module` is passed in, we use your module
97
+ # instead of creating our own.
98
+ #
99
+ # For example:
100
+ #
101
+ # class Model
102
+ # include Decor
103
+ #
104
+ # version "v1" do
105
+ # # ...
106
+ # end
107
+ #
108
+ # module V20101209
109
+ # # ...
110
+ # end
111
+ # version "v2010-12-09" => V20101209
112
+ #
113
+ # # or use classes (for example) as version keys and alias to other
114
+ # # versions
115
+ # version AnotherModel => "v1"
116
+ # version OtherModel => V20101209
117
+ #
118
+ # end
119
+ #
120
+ def version(version, &block)
121
+ case
122
+ # Look up version module if no version block or module specified.
123
+ # version "v1" #=> #<Module>
124
+ when self.versions.key?(version)
125
+ return self.versions[version]
126
+
127
+ # Define a new version from the block.
128
+ # version "v1" { ... }
129
+ when block_given?
130
+ constant = Module.new(&block)
131
+ self.versions[version] = constant
132
+ self
133
+
134
+ # Set versions from a module, supports as many versions as passed in.
135
+ # version "v1" => Version1,
136
+ # "v2" => Version2,
137
+ # "v20101209" => "v2" # supports aliases
138
+ else
139
+ version.each do |(new_version, module_or_version)|
140
+ self.versions[new_version] =
141
+ if module_or_version.is_a?(Module)
142
+ module_or_version
143
+ else
144
+ self.versions[module_or_version]
145
+ end
146
+ end
147
+
148
+ end
149
+ self
150
+ end
151
+ end
152
+
153
+ # An object will be told to behave like the version specified.
154
+ #
155
+ # Options provide additional values in the context of the verions.
156
+ #
157
+ # class Model
158
+ # include Decor
159
+ #
160
+ # version "v1" do
161
+ # def versioned?
162
+ # true
163
+ # end
164
+ # end
165
+ #
166
+ # def versioned?
167
+ # false
168
+ # end
169
+ # end
170
+ #
171
+ # model = Model.new
172
+ # model. versioned? #=> false
173
+ # model.for("v1").versioned? #=> true
174
+ #
175
+ # An optional context can be supplied which will make external resources
176
+ # available for specific functions in your versions. For example:
177
+ #
178
+ # class User
179
+ # include Decor
180
+ #
181
+ # version "v1" do
182
+ # def display_name
183
+ # "%s (%s)" % [name, band.display_name]
184
+ # end
185
+ # end
186
+ # end
187
+ #
188
+ # user = User.find(id).for("v1", :band => external_band)
189
+ # user.display_name #=> "Dan Auerbach (The Black Keys)"
190
+ #
191
+ # Lastly, it's possible to pass in a `:module` option which will override the
192
+ # module already defined for the version specified (making the `version`
193
+ # passed in almost meaningless).
194
+ #
195
+ # module Specialized
196
+ # # special considerations here
197
+ # end
198
+ #
199
+ # Model.new.for("v1", :module => Specialized)
200
+ #
201
+ def for(version, options = {})
202
+ version_module = self.version_module_for(version, options)
203
+ decorator = Class.new(Base).new(self, version, options)
204
+ decorator.send(:extend, version_module)
205
+ decorator
206
+ end
207
+
208
+ # Handles finding the module defined for the `version` specified, or
209
+ # overriding with the `:module` option.
210
+ #
211
+ # See `for` for details.
212
+ #
213
+ def version_module_for(version, options = {})
214
+ return options.delete(:module) if options.key?(:module)
215
+ return self.class.versions[version] if self.class.versions.key?(version)
216
+ self.class.const_get(version.upcase)
217
+ end
218
+
219
+ # The basis of our version wrapper.
220
+ #
221
+ # Whenever a version is specified using `Decor#for`, it is wrapped in a
222
+ # decoration that makes it behave like the specified version.
223
+ #
224
+ # This decoration proxies all calls it doesn't define itself to the original
225
+ # object (the `target`).
226
+ #
227
+ # `options` provides context, which are treated as instance methods for the
228
+ # versions. See `for` for details.
229
+ #
230
+ class Base < Struct.new(:target, :version, :options)
231
+
232
+ # This proxies calls to the target if we don't define it explicitly.
233
+ #
234
+ # However, if the `options` context defines a key that matches the `method`
235
+ # name, we return that value instead.
236
+ #
237
+ def method_missing(method, *args, &block)
238
+ return options[method] if options.key?(method)
239
+ return target.send(method, *args, &block) if respond_to?(method)
240
+ super
241
+ end
242
+
243
+ # We can handle the method call if we have a match in the `options` context
244
+ # or if our `target` object responds to the method.
245
+ #
246
+ # For example:
247
+ #
248
+ # class Model
249
+ # include Decor
250
+ #
251
+ # version "v1" do
252
+ # def foo
253
+ # end
254
+ # end
255
+ #
256
+ # def baz
257
+ # end
258
+ #
259
+ # end
260
+ #
261
+ # model = Model.new.for("v1", :bar => true)
262
+ # model.respond_to?(:foo) #=> true # in version
263
+ # model.respond_to?(:bar) #=> true # in context
264
+ # model.respond_to?(:baz) #=> true # on target
265
+ # model.respond_to?(:quux) #=> false
266
+ #
267
+ def respond_to?(method)
268
+ super or options.key?(method) or target.respond_to?(method)
269
+ end
270
+
271
+ # If `for` is called on an object that is already wrapped by a version,
272
+ # we return the `target` with a new version wrapper. This allows for an
273
+ # object to change its version representation at will.
274
+ #
275
+ # For example:
276
+ #
277
+ # class Model
278
+ # include Decor
279
+ #
280
+ # version "v1" do
281
+ # def original?
282
+ # true
283
+ # end
284
+ # end
285
+ #
286
+ # version "v2" do
287
+ # def original?
288
+ # false
289
+ # end
290
+ # end
291
+ # end
292
+ #
293
+ # model = Model.new.for("v1")
294
+ # model.original? #=> true
295
+ #
296
+ # model = model.for("v2")
297
+ # model.original? #=> false
298
+ #
299
+ def for(*args)
300
+ target.for(*args)
301
+ end
302
+
303
+ # This provides additional context to the versions specified. Useful for
304
+ # making external resources accessible, overriding accessors, etc.
305
+ #
306
+ # Ensures `options` is an empty Hash even when not set.
307
+ #
308
+ def options
309
+ super or begin
310
+ self.options = {}
311
+ redo
312
+ end
313
+ end
314
+
315
+ end
316
+
317
+ end
@@ -0,0 +1,139 @@
1
+ require 'spec_helper'
2
+
3
+ require 'models/bare'
4
+ require 'models/resource'
5
+
6
+ describe Decor do
7
+
8
+ describe "when included in a class" do
9
+
10
+ describe ".version" do
11
+ it "should be available" do
12
+ Bare.should_not respond_to(:version)
13
+ Bare.send(:include, Decor)
14
+ Bare.should respond_to(:version)
15
+ end
16
+
17
+ it "should define a collection of versions" do
18
+ Bare.versions.should respond_to(:to_hash)
19
+ end
20
+
21
+ it "should allow new versions to be defined with a block" do
22
+ Bare.should respond_to(:version)
23
+ Bare.version("v1"){}
24
+ Bare.versions.key?("v1").should be_true
25
+ end
26
+
27
+ it "should allow new versions to be defined with a module" do
28
+ v2 = Module.new
29
+ Bare.version "v2" => v2
30
+ Bare.versions.key?("v2").should be_true
31
+ Bare.versions["v2"].should == v2
32
+ end
33
+
34
+ it "should return versions by name when no block or module is given" do
35
+ v3 = Module.new
36
+ Bare.version "v3" => v3
37
+ Bare.version("v3").should == v3
38
+ end
39
+
40
+ it "should turn a block into a module" do
41
+ Bare.version("v4"){}
42
+ Bare.version("v4").should be_a(Module)
43
+ end
44
+ end
45
+
46
+ describe "#for" do
47
+ subject{ Bare.new }
48
+
49
+ it "should decorate the object with the version specified" do
50
+ subject.for("v1").version.should == "v1"
51
+ end
52
+
53
+ it "should target the instance" do
54
+ subject.for("v1").target.should be_a(Bare)
55
+ subject.for("v1").target.should == subject
56
+ end
57
+
58
+ it "should decorate with an instance of Decor::Base" do
59
+ subject.for("v1").should be_a(Decor::Base)
60
+ end
61
+
62
+ it "should decorate by including the version module" do
63
+ subject.for("v1").should be_a(Bare.version("v1"))
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+ describe Decor::Base do
71
+ before{ @version = "v1"; @name = "foo"; @value = 2; @multi = 2; @options = {} }
72
+ subject{ Resource.new(@name, @value, @multi).for(@version, @options) }
73
+
74
+ it "should delegate to the object" do
75
+ subject.name.should == @name
76
+ end
77
+
78
+ it "should allow version switching" do
79
+ resource = subject
80
+ resource.version.should == "v1"
81
+ resource = resource.for("v2")
82
+ resource.version.should == "v2"
83
+ resource.name.should == @name.upcase
84
+ end
85
+
86
+ it "should allow overriding the module for the version" do
87
+ v2 = Module.new
88
+ resource = subject.for("v1", :module => v2)
89
+ resource.should be_a(v2)
90
+ end
91
+
92
+ describe "v1" do
93
+ before{ @version = "v1" }
94
+
95
+ it "should delegate to the target for original values" do
96
+ subject.name.should == @name
97
+ end
98
+
99
+ it "should allow computed values" do
100
+ subject.computed.should == @value * @multi
101
+ end
102
+ end
103
+
104
+ describe "v2" do
105
+ before{ @version = "v2" }
106
+
107
+ it "should allow modified versions of methods in the target" do
108
+ subject.name.should == @name.upcase
109
+ end
110
+
111
+ it "should allow constants in the context of the version" do
112
+ subject.computed.should == @value * @multi * Resource::Version2::MUTLI
113
+ end
114
+
115
+ end
116
+
117
+ describe "v2010-12-08" do
118
+ before{ @version = "v2010-12-08" }
119
+
120
+ it "should keep the name of the alias as the version" do
121
+ subject.version.should == "v2010-12-08"
122
+ end
123
+
124
+ it "should be the same as its alias" do
125
+ subject.should be_a(subject.target.class.version("v2"))
126
+ end
127
+ end
128
+
129
+ describe "v3" do
130
+ before{ @version = "v3"; @options = {:foo => "bar"} }
131
+
132
+ it "should use values in the context hash as methods" do
133
+ subject.name.should == "%s (%s)" % [@name, @options[:foo]]
134
+ end
135
+ end
136
+
137
+ end
138
+
139
+ end
@@ -0,0 +1,2 @@
1
+ class Bare
2
+ end
@@ -0,0 +1,37 @@
1
+ class Resource < Struct.new(:name, :value, :multi)
2
+ include Decor
3
+
4
+ # Module method
5
+ module V1
6
+ def computed
7
+ value * multi
8
+ end
9
+ end
10
+ version "v1" => V1
11
+
12
+ # Module method, non-standard
13
+ module Version2
14
+ MUTLI = 10
15
+ def name
16
+ super.upcase
17
+ end
18
+ def computed
19
+ value * multi * MUTLI
20
+ end
21
+ end
22
+ # mutliple aliases
23
+ version "v2" => Version2,
24
+ "v2010-12-08" => Version2
25
+
26
+ # Block method
27
+ version "v3" do
28
+ # utilizes options hash
29
+ def name
30
+ "%s (%s)" % [super, foo]
31
+ end
32
+ def computed
33
+ nil
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,6 @@
1
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ require 'decor'
5
+
6
+ require 'rspec'
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: decor
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Matt Todd
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-13 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: bundler
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ type: :development
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 49
46
+ segments:
47
+ - 0
48
+ - 8
49
+ - 7
50
+ version: 0.8.7
51
+ type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: rspec
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - "="
60
+ - !ruby/object:Gem::Version
61
+ hash: 11
62
+ segments:
63
+ - 2
64
+ - 1
65
+ - 0
66
+ version: 2.1.0
67
+ type: :development
68
+ version_requirements: *id003
69
+ description: Provides a simple way to define multiple representations of an object
70
+ email: chiology@gmail.com
71
+ executables: []
72
+
73
+ extensions: []
74
+
75
+ extra_rdoc_files: []
76
+
77
+ files:
78
+ - decor.gemspec
79
+ - Gemfile
80
+ - Gemfile.lock
81
+ - Rakefile
82
+ - Readme.textile
83
+ - lib/decor.rb
84
+ - spec/decor_spec.rb
85
+ - spec/models/bare.rb
86
+ - spec/models/resource.rb
87
+ - spec/spec_helper.rb
88
+ has_rdoc: true
89
+ homepage: http://empl.us/decor/
90
+ licenses:
91
+ - MIT
92
+ post_install_message:
93
+ rdoc_options: []
94
+
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ hash: 3
103
+ segments:
104
+ - 0
105
+ version: "0"
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ hash: 3
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ requirements: []
116
+
117
+ rubyforge_project:
118
+ rubygems_version: 1.3.7
119
+ signing_key:
120
+ specification_version: 3
121
+ summary: Defines multiple representations of objects
122
+ test_files:
123
+ - spec/spec_helper.rb
124
+ - spec/decor_spec.rb
125
+ - spec/models/bare.rb
126
+ - spec/models/resource.rb