depict 0.1.0
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.
- data/lib/depict.rb +7 -0
- data/lib/depict/converters/unix_timestamp.rb +24 -0
- data/lib/depict/mapping.rb +54 -0
- data/lib/depict/presentable.rb +102 -0
- data/lib/depict/presenter.rb +57 -0
- data/lib/depict/version.rb +11 -0
- data/spec/mapping_spec.rb +102 -0
- data/spec/presentable_spec.rb +117 -0
- data/spec/presenter_spec.rb +81 -0
- data/spec/spec_helper.rb +8 -0
- metadata +107 -0
data/lib/depict.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module Depict
|
3
|
+
module Converters
|
4
|
+
module UnixTimestamp
|
5
|
+
|
6
|
+
def self.serialize(value)
|
7
|
+
if value.respond_to? :utc
|
8
|
+
value.utc.to_i * 1000
|
9
|
+
else
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.deserialize(value)
|
15
|
+
if value.respond_to? :to_f
|
16
|
+
Time.at(value.to_f / 1000.0).utc
|
17
|
+
else
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
module Depict
|
3
|
+
class Mapping
|
4
|
+
attr_reader :name
|
5
|
+
|
6
|
+
attr_reader :target_name
|
7
|
+
|
8
|
+
attr_reader :converter
|
9
|
+
|
10
|
+
attr_reader :serializer
|
11
|
+
|
12
|
+
attr_reader :deserializer
|
13
|
+
|
14
|
+
def initialize(name, options={})
|
15
|
+
@name = name.to_sym
|
16
|
+
|
17
|
+
@target_name = options.fetch(:as, @name)
|
18
|
+
|
19
|
+
@converter = options[:with]
|
20
|
+
|
21
|
+
@serializer = options[:serialize_with]
|
22
|
+
|
23
|
+
@deserializer = options[:deserialize_with]
|
24
|
+
end
|
25
|
+
|
26
|
+
def serialize(object, attributes)
|
27
|
+
value = object.send(name)
|
28
|
+
|
29
|
+
if serializer
|
30
|
+
attributes[target_name] = serializer.call(value)
|
31
|
+
elsif converter
|
32
|
+
attributes[target_name] = converter.serialize(value)
|
33
|
+
else
|
34
|
+
attributes[target_name] = value
|
35
|
+
end
|
36
|
+
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def deserialize(object, attributes)
|
41
|
+
value = attributes[target_name]
|
42
|
+
|
43
|
+
if deserializer
|
44
|
+
object.send("#{name}=", deserializer.call(value))
|
45
|
+
elsif converter
|
46
|
+
object.send("#{name}=", converter.deserialize(value))
|
47
|
+
else
|
48
|
+
object.send("#{name}=", value)
|
49
|
+
end
|
50
|
+
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
|
2
|
+
module Depict
|
3
|
+
module Presentable
|
4
|
+
class UndefinedPresentationError < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.send(:extend, ClassMethods)
|
9
|
+
base.send(:include, InstanceMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def depict_presentations
|
14
|
+
@depict_presentations ||= {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def define_presentation(name, options={}, &block)
|
18
|
+
if options[:extends]
|
19
|
+
extends_presenter = depict_presentations[options[:extends]]
|
20
|
+
|
21
|
+
if extends_presenter == nil
|
22
|
+
raise UndefinedPresentationError.new("undefined presentation: #{options[:extends]}")
|
23
|
+
end
|
24
|
+
else
|
25
|
+
extends_presenter = Depict::Presenter
|
26
|
+
end
|
27
|
+
|
28
|
+
depict_presentations[name] = extends_presenter.define(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def new_from_presentation(name, attrs)
|
32
|
+
object = self.new
|
33
|
+
|
34
|
+
presenter_class = depict_presentations[name]
|
35
|
+
|
36
|
+
if presenter_class
|
37
|
+
presenter = presenter_class.new(object)
|
38
|
+
presenter.attributes = attrs
|
39
|
+
end
|
40
|
+
|
41
|
+
object
|
42
|
+
end
|
43
|
+
|
44
|
+
def respond_to?(method, include_private=false)
|
45
|
+
names = depict_presentations.keys
|
46
|
+
|
47
|
+
if /^new_from_(#{names.join("|")})_presentation$/ =~ method.to_s
|
48
|
+
true
|
49
|
+
else
|
50
|
+
super(method, include_private)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def method_missing(method, *args)
|
55
|
+
names = depict_presentations.keys
|
56
|
+
|
57
|
+
match = /^new_from_(#{names.join("|")})_presentation$/.match(method.to_s)
|
58
|
+
|
59
|
+
if match
|
60
|
+
new_from_presentation(match[1].to_sym, *args)
|
61
|
+
else
|
62
|
+
super(method, *args)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module InstanceMethods
|
68
|
+
def to_presentation(presentation)
|
69
|
+
presenter = self.class.depict_presentations[presentation]
|
70
|
+
|
71
|
+
if presenter
|
72
|
+
presenter.new(self).to_hash
|
73
|
+
else
|
74
|
+
{}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def respond_to?(method, include_private=false)
|
79
|
+
names = self.class.depict_presentations.keys
|
80
|
+
|
81
|
+
if /^to_(#{names.join("|")})_presentation$/ =~ method.to_s
|
82
|
+
true
|
83
|
+
else
|
84
|
+
super(method, include_private)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def method_missing(method, *args)
|
89
|
+
names = self.class.depict_presentations.keys
|
90
|
+
|
91
|
+
match = /^to_(#{names.join("|")})_presentation$/.match(method.to_s)
|
92
|
+
|
93
|
+
if match
|
94
|
+
to_presentation(match[1].to_sym)
|
95
|
+
else
|
96
|
+
super(method, *args)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
module Depict
|
3
|
+
class Presenter
|
4
|
+
class << self
|
5
|
+
def define(&block)
|
6
|
+
klass = Class.new(self)
|
7
|
+
klass.instance_eval(&block)
|
8
|
+
klass
|
9
|
+
end
|
10
|
+
|
11
|
+
def mappings
|
12
|
+
@mappings ||= superclass == Object ? [] : superclass.mappings.dup
|
13
|
+
end
|
14
|
+
|
15
|
+
def target_attribute_names
|
16
|
+
mappings.map(&:target_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def maps(name, options={})
|
20
|
+
mappings.push Mapping.new(name, options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(object)
|
25
|
+
@object = object
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_hash
|
29
|
+
self.class.mappings.inject({}) {|attrs, mapping| mapping.serialize(@object, attrs); attrs }
|
30
|
+
end
|
31
|
+
|
32
|
+
def attributes=(attributes)
|
33
|
+
self.class.mappings.each {|mapping| mapping.deserialize(@object, attributes) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def respond_to?(method, include_private=false)
|
37
|
+
if self.class.target_attribute_names.include? method
|
38
|
+
return true
|
39
|
+
else
|
40
|
+
super(method, include_private)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def method_missing(method, *args)
|
45
|
+
mapping = self.class.mappings.detect {|x| x.target_name == method }
|
46
|
+
|
47
|
+
if mapping
|
48
|
+
attrs = {}
|
49
|
+
mapping.serialize(@object, attrs)
|
50
|
+
attrs[method]
|
51
|
+
else
|
52
|
+
super(method, *args)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
describe Depict::Mapping do
|
5
|
+
subject { Depict::Mapping }
|
6
|
+
|
7
|
+
let(:name_mapping) { subject.new(:name) }
|
8
|
+
|
9
|
+
it "should assign the attribute name" do
|
10
|
+
subject.new(:id).name.should == :id
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should symbolize string attribute names" do
|
14
|
+
subject.new("id").name.should == :id
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should assign the :with object as the converter" do
|
18
|
+
mapping = subject.new(:created_at, :with => Depict::Converters::UnixTimestamp)
|
19
|
+
|
20
|
+
mapping.converter.should == Depict::Converters::UnixTimestamp
|
21
|
+
end
|
22
|
+
|
23
|
+
context "serialization" do
|
24
|
+
let(:attrs) { {} }
|
25
|
+
let(:object) { OpenStruct.new(:timestamp => Time.utc(2012, 1, 1, 0, 0, 0)) }
|
26
|
+
let(:serializer) { lambda {|x| x.utc.iso8601 } }
|
27
|
+
|
28
|
+
it "should assign a serialized value to a given hash" do
|
29
|
+
subject.new(:timestamp).serialize(object, attrs)
|
30
|
+
|
31
|
+
attrs[:timestamp].should == Time.utc(2012, 1, 1, 0, 0, 0)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should assign a serialized value using the converter to a given hash" do
|
35
|
+
subject.new(:timestamp, :with => Depict::Converters::UnixTimestamp).serialize(object, attrs)
|
36
|
+
|
37
|
+
attrs[:timestamp].should == 1325376000000
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should write to the :as attribute name" do
|
41
|
+
subject.new(:timestamp, :as => :created_at).serialize(object, attrs)
|
42
|
+
|
43
|
+
attrs[:created_at].should == Time.utc(2012, 1, 1, 0, 0, 0)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should use the lamda function passed as :serialize_with" do
|
47
|
+
subject.new(:timestamp, :serialize_with => serializer).serialize(object, attrs)
|
48
|
+
|
49
|
+
attrs[:timestamp].should == "2012-01-01T00:00:00Z"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should prefer the lambda function to the converter if both are given" do
|
53
|
+
mapping = subject.new(:timestamp, :with => Depict::Converters::UnixTimestamp, :serialize_with => serializer)
|
54
|
+
|
55
|
+
mapping.serialize(object, attrs)
|
56
|
+
|
57
|
+
attrs[:timestamp].should == "2012-01-01T00:00:00Z"
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
context "deserialization" do
|
63
|
+
let(:attrs) { {:timestamp => 1325376000000 } }
|
64
|
+
let(:object) { OpenStruct.new }
|
65
|
+
let(:deserializer) { lambda {|x| Time.iso8601(x) } }
|
66
|
+
|
67
|
+
it "should assign the value from the given hash" do
|
68
|
+
subject.new(:timestamp).deserialize(object, attrs)
|
69
|
+
|
70
|
+
object.timestamp.should == 1325376000000
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should assign the value using the converter from the given hash" do
|
74
|
+
subject.new(:timestamp, :with => Depict::Converters::UnixTimestamp).deserialize(object, attrs)
|
75
|
+
|
76
|
+
object.timestamp.should == Time.utc(2012, 1, 1, 0, 0, 0)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should read from the :as attribute name" do
|
80
|
+
subject.new(:created_at, :as => :timestamp).deserialize(object, attrs)
|
81
|
+
|
82
|
+
object.created_at.should == 1325376000000
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should use the lambda function passed as :deserialize_with" do
|
86
|
+
mapping = subject.new(:timestamp, :deserialize_with => deserializer)
|
87
|
+
|
88
|
+
mapping.deserialize(object, {:timestamp => "2012-01-01T00:00:00Z"})
|
89
|
+
|
90
|
+
object.timestamp.should == Time.utc(2012, 1, 1, 0, 0, 0)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should prefer the lambda function to the converter if both are given" do
|
94
|
+
mapping = subject.new(:timestamp, :with => Depict::Converters::UnixTimestamp, :deserialize_with => deserializer)
|
95
|
+
|
96
|
+
mapping.deserialize(object, {:timestamp => "2012-01-01T00:00:00Z"})
|
97
|
+
|
98
|
+
object.timestamp.should == Time.utc(2012, 1, 1, 0, 0, 0)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Depict::Presentable do
|
4
|
+
subject { Depict::Presentable }
|
5
|
+
|
6
|
+
let(:base_class) { Class.new }
|
7
|
+
let(:mixed_class) { base_class.send(:include, subject); base_class }
|
8
|
+
|
9
|
+
let(:user_model) do
|
10
|
+
mixed_class.define_presentation :user do
|
11
|
+
maps :id
|
12
|
+
maps :name
|
13
|
+
end
|
14
|
+
|
15
|
+
mixed_class.send(:attr_accessor, :id, :name, :role)
|
16
|
+
|
17
|
+
mixed_class
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:user) do
|
21
|
+
user = user_model.new
|
22
|
+
user.id = 42
|
23
|
+
user.name = "foo"
|
24
|
+
user.role = "superuser"
|
25
|
+
user
|
26
|
+
end
|
27
|
+
|
28
|
+
context "defining presentations" do
|
29
|
+
it "should define #depict_presentations on the class that mixes it in" do
|
30
|
+
base_class.should_not respond_to :depict_presentations
|
31
|
+
base_class.send(:include, subject)
|
32
|
+
base_class.should respond_to :depict_presentations
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return an empty hash by default" do
|
36
|
+
mixed_class.depict_presentations.should == {}
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should allow defining a presentation with #define_presentation" do
|
40
|
+
presentations = user_model.depict_presentations
|
41
|
+
|
42
|
+
presentations.keys.should == [:user]
|
43
|
+
presentations[:user].superclass.should == Depict::Presenter
|
44
|
+
presentations[:user].should have(2).mappings
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should allow defining a super presentation with :extends" do
|
48
|
+
user_model.define_presentation :admin, :extends => :user do
|
49
|
+
maps :role
|
50
|
+
end
|
51
|
+
|
52
|
+
presenter = user_model.depict_presentations[:admin]
|
53
|
+
presenter.superclass.should == user_model.depict_presentations[:user]
|
54
|
+
presenter.mappings.map(&:name).should == [:id, :name, :role]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should raise an UndefinedPresentationError if trying to extend an undefined presentation" do
|
58
|
+
lambda do
|
59
|
+
user_model.define_presentation :admin, :extends => :fake do
|
60
|
+
maps :role
|
61
|
+
end
|
62
|
+
end.should raise_error(Depict::Presentable::UndefinedPresentationError)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "serializing as a presentation" do
|
67
|
+
it "should define :to_presentation on the instance level" do
|
68
|
+
user_model.new.should respond_to :to_presentation
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return the presentation specified" do
|
72
|
+
user.to_presentation(:user).should == {
|
73
|
+
:id => 42,
|
74
|
+
:name => "foo"
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should respond to the #to_xyz_presentation methods" do
|
79
|
+
user.should respond_to :to_user_presentation
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should use method_missing to support #to_xyz_presentation" do
|
83
|
+
user.to_user_presentation.should == {
|
84
|
+
:id => 42,
|
85
|
+
:name => "foo"
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should return an empty hash if the presentation is not defined" do
|
90
|
+
user.to_presentation(:fake).should == {}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "instantiation from presentations" do
|
95
|
+
it "should be serializable from a presentation" do
|
96
|
+
user = user_model.new_from_presentation(:user, :id => 99, :name => "bar")
|
97
|
+
user.id.should == 99
|
98
|
+
user.name.should == "bar"
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should respond to #new_from_xyz_presentation" do
|
102
|
+
user_model.should respond_to :new_from_user_presentation
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should use method_missing to support #new_from_xyz_presentation" do
|
106
|
+
user = user_model.new_from_user_presentation(:id => 80, :name => "baz")
|
107
|
+
user.id.should == 80
|
108
|
+
user.name.should == "baz"
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should return a new object with nothing assigned if the presentation is not defined" do
|
112
|
+
user = user_model.new_from_presentation(:fake, {:id => 42, :name => "foo"})
|
113
|
+
user.id.should == nil
|
114
|
+
user.name.should == nil
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
describe Depict::Presenter do
|
5
|
+
|
6
|
+
let(:user_presenter) do
|
7
|
+
Depict::Presenter.define do
|
8
|
+
maps :database_id
|
9
|
+
maps :name
|
10
|
+
maps :email, :as => :login
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should call the block given" do
|
15
|
+
ran_block = false
|
16
|
+
Depict::Presenter.define { ran_block = true }
|
17
|
+
ran_block.should == true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return a class which is a subclass of Depict::Presenter" do
|
21
|
+
presenter = Depict::Presenter.define {}
|
22
|
+
presenter.should be_an_instance_of Class
|
23
|
+
presenter.superclass.should eql Depict::Presenter
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return a class which also define's the same #define method" do
|
27
|
+
super_presenter = Depict::Presenter.define {}
|
28
|
+
|
29
|
+
inhereted_presenter = super_presenter.define {}
|
30
|
+
|
31
|
+
inhereted_presenter.superclass.should == super_presenter
|
32
|
+
inhereted_presenter.superclass.superclass.should == Depict::Presenter
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be able to access defined mappings" do
|
36
|
+
presenter = Depict::Presenter.define {}
|
37
|
+
presenter.mappings.should == []
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should add a mapping for each call to #map" do
|
41
|
+
user_presenter.mappings.map(&:name).should == [:database_id, :name, :email]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should inherit all mappings of it's superclass without modifying them" do
|
45
|
+
admin_presenter = user_presenter.define do
|
46
|
+
maps :role
|
47
|
+
end
|
48
|
+
|
49
|
+
user_presenter.mappings.map(&:name).should == [:database_id, :name, :email]
|
50
|
+
admin_presenter.mappings.map(&:name).should == [:database_id, :name, :email, :role]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should be able to wrap an object and produce a hash of it's presentation" do
|
54
|
+
user = OpenStruct.new(:database_id => 42, :name => "foobar", :role => "admin")
|
55
|
+
|
56
|
+
user_presenter.new(user).to_hash.should == {
|
57
|
+
:database_id => 42,
|
58
|
+
:name => "foobar",
|
59
|
+
:login => nil
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should be able to wrap an object and assign attributes from a hash" do
|
64
|
+
user = OpenStruct.new
|
65
|
+
|
66
|
+
user_presenter.new(user).attributes = {:database_id => 42, :name => "foobar"}
|
67
|
+
|
68
|
+
user.database_id.should == 42
|
69
|
+
user.name.should == "foobar"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should respond to any attribute defined on it" do
|
73
|
+
user_presenter.new(OpenStruct.new).should respond_to :login
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should retrieve the value of the attribute when called" do
|
77
|
+
user = OpenStruct.new(:email => "foo@example.com")
|
78
|
+
|
79
|
+
user_presenter.new(user).login.should == "foo@example.com"
|
80
|
+
end
|
81
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: depict
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- William Howard
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
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
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.10.0
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.10.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: guard-rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description:
|
63
|
+
email:
|
64
|
+
- whoward.tke@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- lib/depict/presentable.rb
|
70
|
+
- lib/depict/version.rb
|
71
|
+
- lib/depict/converters/unix_timestamp.rb
|
72
|
+
- lib/depict/presenter.rb
|
73
|
+
- lib/depict/mapping.rb
|
74
|
+
- lib/depict.rb
|
75
|
+
- spec/presenter_spec.rb
|
76
|
+
- spec/mapping_spec.rb
|
77
|
+
- spec/spec_helper.rb
|
78
|
+
- spec/presentable_spec.rb
|
79
|
+
homepage: http://github.com/whoward/depict
|
80
|
+
licenses: []
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 1.8.24
|
100
|
+
signing_key:
|
101
|
+
specification_version: 3
|
102
|
+
summary: Presentation library with support for multiple bidirectional presentations
|
103
|
+
test_files:
|
104
|
+
- spec/presenter_spec.rb
|
105
|
+
- spec/mapping_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
107
|
+
- spec/presentable_spec.rb
|