ephemeral 1.1.0 → 1.2.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/VERSION +1 -1
- data/ephemeral.gemspec +3 -2
- data/lib/ephemeral/base.rb +13 -1
- data/lib/ephemeral/collection.rb +4 -4
- data/lib/ephemeral/relation.rb +21 -0
- data/lib/ephemeral.rb +1 -0
- data/spec/ephemeral_spec.rb +86 -52
- metadata +4 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.2.0
|
data/ephemeral.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ephemeral"
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Corey Ehmke"]
|
12
|
-
s.date = "2012-09-
|
12
|
+
s.date = "2012-09-24"
|
13
13
|
s.description = "Ephemeral lets you define one-to-many relationships between in-memory objects, with ORM-like support for where clauses and chainable scopes."
|
14
14
|
s.email = "corey@idolhands.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
"lib/ephemeral.rb",
|
28
28
|
"lib/ephemeral/base.rb",
|
29
29
|
"lib/ephemeral/collection.rb",
|
30
|
+
"lib/ephemeral/relation.rb",
|
30
31
|
"spec/ephemeral_spec.rb"
|
31
32
|
]
|
32
33
|
s.homepage = "http://github.com/Bantik/ephemeral"
|
data/lib/ephemeral/base.rb
CHANGED
@@ -7,7 +7,7 @@ module Ephemeral
|
|
7
7
|
|
8
8
|
def self.included(base)
|
9
9
|
base.extend ClassMethods
|
10
|
-
base.send(:attr_accessor, :collections)
|
10
|
+
base.send(:attr_accessor, :collections, :relations)
|
11
11
|
end
|
12
12
|
|
13
13
|
module ClassMethods
|
@@ -24,6 +24,18 @@ module Ephemeral
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
def has_one(name, args={})
|
28
|
+
class_name = args[:class_name] || name.to_s.classify
|
29
|
+
self.send :define_method, name do
|
30
|
+
self.relations ||= {}
|
31
|
+
self.relations[class_name] ||= Ephemeral::Relation.new(class_name).materialize
|
32
|
+
end
|
33
|
+
self.send :define_method, "#{name}=" do |object|
|
34
|
+
self.relations ||= {}
|
35
|
+
self.relations[class_name] = Ephemeral::Relation.new(class_name).materialize(object)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
27
39
|
def scope(name, conditions)
|
28
40
|
self.scopes ||= {}
|
29
41
|
self.scopes[name] = conditions
|
data/lib/ephemeral/collection.rb
CHANGED
@@ -23,8 +23,8 @@ module Ephemeral
|
|
23
23
|
|
24
24
|
def where(args={})
|
25
25
|
return [] unless self.objects
|
26
|
-
results = args.inject([]){|a,
|
27
|
-
results = results.flatten.select{|r| results.flatten.count(r) == results.count}.uniq
|
26
|
+
results = args.inject([]) {|a, (k, v)| a << self.objects.select {|o| o.send(k) == v} }
|
27
|
+
results = results.flatten.select {|r| results.flatten.count(r) == results.count }.uniq
|
28
28
|
end
|
29
29
|
|
30
30
|
def last
|
@@ -39,8 +39,8 @@ module Ephemeral
|
|
39
39
|
|
40
40
|
def execute_scope(method)
|
41
41
|
return Ephemeral::Collection.new(self.klass.name) unless self.objects
|
42
|
-
results = self.klass.scopes[method].inject([]){|a,
|
43
|
-
results = results.flatten.select{|r| results.flatten.count(r) == results.count}.uniq
|
42
|
+
results = self.klass.scopes[method].inject([]) {|a, (k, v)| a << self.objects.select {|o| o.send(k) == v } }
|
43
|
+
results = results.flatten.select {|r| results.flatten.count(r) == results.count }.uniq
|
44
44
|
Ephemeral::Collection.new(self.klass.name, results)
|
45
45
|
end
|
46
46
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Ephemeral
|
2
|
+
|
3
|
+
class Relation
|
4
|
+
|
5
|
+
attr_accessor :object, :klass
|
6
|
+
|
7
|
+
def initialize(klass, object=nil)
|
8
|
+
self.klass = eval(klass)
|
9
|
+
self.object = self.materialize(object)
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def materialize(object=nil)
|
14
|
+
return nil unless object
|
15
|
+
return object if object.is_a? self.klass
|
16
|
+
self.klass.new(object)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/ephemeral.rb
CHANGED
data/spec/ephemeral_spec.rb
CHANGED
@@ -11,6 +11,7 @@ end
|
|
11
11
|
|
12
12
|
class Antique
|
13
13
|
include Ephemeral::Base
|
14
|
+
has_one :picker
|
14
15
|
attr_accessor :name, :item_count
|
15
16
|
def initialize(args={}); args.each{|k,v| self.send("#{k}=", v)}; end
|
16
17
|
end
|
@@ -21,6 +22,12 @@ class NotCollectible
|
|
21
22
|
def initialize(args={}); args.each{|k,v| self.send("#{k}=", v)}; end
|
22
23
|
end
|
23
24
|
|
25
|
+
class Picker
|
26
|
+
include Ephemeral::Base
|
27
|
+
attr_accessor :name
|
28
|
+
def initialize(args={}); args.each{|k,v| self.send("#{k}=", v)}; end
|
29
|
+
end
|
30
|
+
|
24
31
|
class Collector
|
25
32
|
include Ephemeral::Base
|
26
33
|
attr_accessor :name
|
@@ -34,81 +41,108 @@ describe Ephemeral do
|
|
34
41
|
|
35
42
|
context 'class methods' do
|
36
43
|
|
37
|
-
|
38
|
-
Collector.new.rarities.klass.should == Rarity
|
39
|
-
Collector.new.antiques.klass.should == Antique
|
40
|
-
end
|
44
|
+
context 'collections' do
|
41
45
|
|
42
|
-
|
43
|
-
|
44
|
-
|
46
|
+
it 'defines a collection' do
|
47
|
+
Collector.new.rarities.klass.should == Rarity
|
48
|
+
Collector.new.antiques.klass.should == Antique
|
49
|
+
end
|
45
50
|
|
46
|
-
|
47
|
-
|
48
|
-
|
51
|
+
it 'accepts a class name' do
|
52
|
+
Collector.new.junk.klass.should == NotCollectible
|
53
|
+
end
|
49
54
|
|
50
|
-
|
51
|
-
|
52
|
-
|
55
|
+
it 'creates a setter' do
|
56
|
+
Collector.new.respond_to?(:rarities=).should be_true
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'creates a getter' do
|
60
|
+
Collector.new.respond_to?(:rarities).should be_true
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'registers a scope' do
|
64
|
+
Rarity.scopes.include?(:foos).should be_true
|
65
|
+
end
|
53
66
|
|
54
|
-
it 'registers a scope' do
|
55
|
-
Rarity.scopes.include?(:foos).should be_true
|
56
67
|
end
|
57
68
|
|
69
|
+
context 'relations' do
|
70
|
+
|
71
|
+
it 'defines a relation' do
|
72
|
+
Antique.new(:picker => {:name => 'Frank Fritz'}).picker.is_a?(Picker).should be_true
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
58
76
|
end
|
59
77
|
|
60
78
|
context 'instance methods' do
|
61
79
|
|
62
|
-
|
63
|
-
|
64
|
-
@rarities = [
|
65
|
-
Rarity.new(:name => 'Paychecks', :item_count => 1),
|
66
|
-
Rarity.new(:name => 'Paychecks', :item_count => 3),
|
67
|
-
Rarity.new(:name => 'Requisitions', :item_count => 2),
|
68
|
-
]
|
80
|
+
context 'relations' do
|
69
81
|
|
70
|
-
|
71
|
-
Antique.new(:name => '
|
72
|
-
|
82
|
+
before :each do
|
83
|
+
@antique = Antique.new(:name => 'Model T Ford', :item_count => 1, :picker => {:name => "Mike Wolfe"} )
|
84
|
+
end
|
73
85
|
|
74
|
-
|
75
|
-
|
76
|
-
|
86
|
+
it 'initializes with a materialized object' do
|
87
|
+
@antique.picker.name.should == "Mike Wolfe"
|
88
|
+
end
|
77
89
|
|
78
90
|
end
|
79
91
|
|
80
|
-
|
81
|
-
|
82
|
-
it 'from a setter' do
|
83
|
-
collector = Collector.new(
|
84
|
-
:name => 'from_api',
|
85
|
-
'rarities' => [
|
86
|
-
{'name' => 'foo'},
|
87
|
-
{'name' => 'bar'}
|
88
|
-
]
|
89
|
-
)
|
90
|
-
collector.rarities.count.should == 2
|
91
|
-
end
|
92
|
+
context 'collections' do
|
92
93
|
|
93
|
-
|
94
|
+
before :each do
|
94
95
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
@rarities = [
|
97
|
+
Rarity.new(:name => 'Paychecks', :item_count => 1),
|
98
|
+
Rarity.new(:name => 'Paychecks', :item_count => 3),
|
99
|
+
Rarity.new(:name => 'Requisitions', :item_count => 2),
|
100
|
+
]
|
101
|
+
|
102
|
+
@antiques = [
|
103
|
+
Antique.new(:name => 'Trading Cards', :item_count => 100)
|
104
|
+
]
|
99
105
|
|
100
|
-
|
106
|
+
@collector = Collector.new(:name => 'Hermes')
|
107
|
+
@collector.rarities = @rarities
|
108
|
+
@collector.antiques = @antiques
|
101
109
|
|
102
|
-
it 'executes a scope' do
|
103
|
-
@collector.rarities.paychecks.first.should_not be_nil
|
104
110
|
end
|
105
111
|
|
106
|
-
|
107
|
-
|
112
|
+
describe 'initializes with materialized objects' do
|
113
|
+
|
114
|
+
it 'from a setter' do
|
115
|
+
collector = Collector.new(
|
116
|
+
:name => 'from_api',
|
117
|
+
'rarities' => [
|
118
|
+
{'name' => 'foo'},
|
119
|
+
{'name' => 'bar'}
|
120
|
+
]
|
121
|
+
)
|
122
|
+
collector.rarities.count.should == 2
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'performs a where' do
|
128
|
+
@collector.rarities.where(:name => 'Paychecks').should_not be_blank
|
129
|
+
@collector.antiques.where(:name => 'Trading Cards').should_not be_blank
|
108
130
|
end
|
109
131
|
|
110
|
-
|
111
|
-
|
132
|
+
describe 'scope method' do
|
133
|
+
|
134
|
+
it 'executes a scope' do
|
135
|
+
@collector.rarities.paychecks.first.should_not be_nil
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'returns a collection' do
|
139
|
+
@collector.rarities.paychecks.class.name.should == 'Ephemeral::Collection'
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'chains scopes' do
|
143
|
+
@collector.rarities.paychecks.threes.count.should == 1
|
144
|
+
end
|
145
|
+
|
112
146
|
end
|
113
147
|
|
114
148
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ephemeral
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- lib/ephemeral.rb
|
111
111
|
- lib/ephemeral/base.rb
|
112
112
|
- lib/ephemeral/collection.rb
|
113
|
+
- lib/ephemeral/relation.rb
|
113
114
|
- spec/ephemeral_spec.rb
|
114
115
|
homepage: http://github.com/Bantik/ephemeral
|
115
116
|
licenses:
|
@@ -126,7 +127,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
126
127
|
version: '0'
|
127
128
|
segments:
|
128
129
|
- 0
|
129
|
-
hash:
|
130
|
+
hash: -1586023366873335519
|
130
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
132
|
none: false
|
132
133
|
requirements:
|