remodel-h 0.1.4
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/.gitignore +2 -0
- data/LICENSE +20 -0
- data/README.md +96 -0
- data/Rakefile +27 -0
- data/VERSION +1 -0
- data/bin/redis-monitor.rb +25 -0
- data/docs/docco.css +185 -0
- data/docs/remodel.html +269 -0
- data/example/book.rb +13 -0
- data/lib/remodel/entity.rb +198 -0
- data/lib/remodel/has_many.rb +71 -0
- data/lib/remodel/mapper.rb +29 -0
- data/lib/remodel.rb +77 -0
- data/remodel-h.gemspec +72 -0
- data/remodel.gemspec +72 -0
- data/test/helper.rb +19 -0
- data/test/test_entity.rb +313 -0
- data/test/test_many_to_many.rb +77 -0
- data/test/test_many_to_one.rb +107 -0
- data/test/test_mappers.rb +67 -0
- data/test/test_monkeypatches.rb +30 -0
- data/test/test_one_to_many.rb +96 -0
- data/test/test_one_to_one.rb +57 -0
- metadata +85 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestManyToMany < Test::Unit::TestCase
|
4
|
+
|
5
|
+
class Person < Remodel::Entity
|
6
|
+
has_many :groups, :class => 'TestManyToMany::Group', :reverse => 'members'
|
7
|
+
property :name
|
8
|
+
end
|
9
|
+
|
10
|
+
class Group < Remodel::Entity
|
11
|
+
has_many :members, :class => 'TestManyToMany::Person', :reverse => 'groups'
|
12
|
+
property :name
|
13
|
+
end
|
14
|
+
|
15
|
+
context "both associations" do
|
16
|
+
should "be empty by default" do
|
17
|
+
assert_equal [], Person.new.groups
|
18
|
+
assert_equal [], Group.new.members
|
19
|
+
end
|
20
|
+
|
21
|
+
context "create" do
|
22
|
+
should "add a new group to both associations" do
|
23
|
+
tim = Person.create :name => 'tim'
|
24
|
+
rugb = tim.groups.create :name => 'rug-b'
|
25
|
+
assert_equal [tim], rugb.members
|
26
|
+
end
|
27
|
+
|
28
|
+
should "add a new person to both associations" do
|
29
|
+
rugb = Group.create :name => 'rug-b'
|
30
|
+
tim = rugb.members.create :name => 'tim'
|
31
|
+
assert_equal [rugb], tim.groups
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "add" do
|
36
|
+
setup do
|
37
|
+
@tim = Person.create :name => 'tim'
|
38
|
+
@rugb = Group.create :name => 'rug-b'
|
39
|
+
end
|
40
|
+
|
41
|
+
should "add a new group to both associations" do
|
42
|
+
@tim.groups.add(@rugb)
|
43
|
+
assert_equal [@tim], @rugb.members
|
44
|
+
assert_equal [@rugb], @tim.groups
|
45
|
+
end
|
46
|
+
|
47
|
+
should "add a new person to both associations" do
|
48
|
+
@rugb.members.add(@tim)
|
49
|
+
assert_equal [@tim], @rugb.members
|
50
|
+
assert_equal [@rugb], @tim.groups
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "remove" do
|
55
|
+
setup do
|
56
|
+
@tim = Person.create :name => 'tim'
|
57
|
+
@rugb = @tim.groups.create(:name => 'rug-b')
|
58
|
+
@erlang = @tim.groups.create(:name => 'erlang')
|
59
|
+
@aws = @tim.groups.create(:name => 'aws')
|
60
|
+
end
|
61
|
+
|
62
|
+
should "remove a group from both associations" do
|
63
|
+
@tim.groups.remove(@erlang)
|
64
|
+
assert_equal [@rugb, @aws], @tim.groups
|
65
|
+
assert_equal [], @erlang.members
|
66
|
+
end
|
67
|
+
|
68
|
+
should "remove a person from both associations" do
|
69
|
+
@erlang.members.remove(@tim)
|
70
|
+
assert_equal [@rugb, @aws], @tim.groups
|
71
|
+
assert_equal [], @erlang.members
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class TestManyToOne < Test::Unit::TestCase
|
5
|
+
|
6
|
+
class Puzzle < Remodel::Entity
|
7
|
+
has_many :pieces, :class => 'TestManyToOne::Piece', :reverse => 'puzzle'
|
8
|
+
property :topic
|
9
|
+
end
|
10
|
+
|
11
|
+
class Piece < Remodel::Entity
|
12
|
+
has_one :puzzle, :class => 'TestManyToOne::Puzzle'
|
13
|
+
property :color
|
14
|
+
end
|
15
|
+
|
16
|
+
context "has_many" do
|
17
|
+
context "association" do
|
18
|
+
should "exist" do
|
19
|
+
assert Puzzle.create.respond_to?(:pieces)
|
20
|
+
end
|
21
|
+
|
22
|
+
should "return an empty list by default" do
|
23
|
+
assert_equal [], Puzzle.create.pieces
|
24
|
+
end
|
25
|
+
|
26
|
+
should "return any existing children" do
|
27
|
+
puzzle = Puzzle.create
|
28
|
+
red_piece = Piece.create(:color => 'red')
|
29
|
+
blue_piece = Piece.create(:color => 'blue')
|
30
|
+
value = JSON.generate([red_piece.key, blue_piece.key])
|
31
|
+
redis.hset context, "#{puzzle.key}:pieces", value
|
32
|
+
assert_equal 2, puzzle.pieces.size
|
33
|
+
assert_equal Piece, puzzle.pieces[0].class
|
34
|
+
assert_equal 'red', puzzle.pieces[0].color
|
35
|
+
end
|
36
|
+
|
37
|
+
context "create" do
|
38
|
+
should "have a create method" do
|
39
|
+
assert Puzzle.create.pieces.respond_to?(:create)
|
40
|
+
end
|
41
|
+
|
42
|
+
should "work without attributes" do
|
43
|
+
puzzle = Puzzle.create
|
44
|
+
piece = puzzle.pieces.create
|
45
|
+
assert piece.is_a?(Piece)
|
46
|
+
end
|
47
|
+
|
48
|
+
should "create and store a new child" do
|
49
|
+
puzzle = Puzzle.create
|
50
|
+
puzzle.pieces.create :color => 'green'
|
51
|
+
assert_equal 1, puzzle.pieces.size
|
52
|
+
puzzle.reload
|
53
|
+
assert_equal 1, puzzle.pieces.size
|
54
|
+
assert_equal Piece, puzzle.pieces[0].class
|
55
|
+
assert_equal 'green', puzzle.pieces[0].color
|
56
|
+
end
|
57
|
+
|
58
|
+
should "associate the created child with self" do
|
59
|
+
puzzle = Puzzle.create :topic => 'provence'
|
60
|
+
piece = puzzle.pieces.create :color => 'green'
|
61
|
+
assert_equal 'provence', piece.puzzle.topic
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "add" do
|
66
|
+
should "add the given entity to the association" do
|
67
|
+
puzzle = Puzzle.create
|
68
|
+
piece = Piece.create :color => 'white'
|
69
|
+
puzzle.pieces.add piece
|
70
|
+
assert_equal 1, puzzle.pieces.size
|
71
|
+
puzzle.reload
|
72
|
+
assert_equal 1, puzzle.pieces.size
|
73
|
+
assert_equal Piece, puzzle.pieces[0].class
|
74
|
+
assert_equal 'white', puzzle.pieces[0].color
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "find" do
|
79
|
+
setup do
|
80
|
+
@puzzle = Puzzle.create
|
81
|
+
5.times { @puzzle.pieces.create :color => 'blue' }
|
82
|
+
end
|
83
|
+
|
84
|
+
should "find the element with the given id" do
|
85
|
+
piece = @puzzle.pieces[2]
|
86
|
+
assert_equal piece, @puzzle.pieces.find(piece.id)
|
87
|
+
end
|
88
|
+
|
89
|
+
should "raise an exception if no element with the given id exists" do
|
90
|
+
assert_raises(Remodel::EntityNotFound) { @puzzle.pieces.find(-1) }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context "reload" do
|
98
|
+
should "reset has_many associations" do
|
99
|
+
puzzle = Puzzle.create
|
100
|
+
piece = puzzle.pieces.create :color => 'black'
|
101
|
+
redis.hdel context, "#{puzzle.key}:pieces"
|
102
|
+
puzzle.reload
|
103
|
+
assert_equal [], puzzle.pieces
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class Item < Remodel::Entity
|
4
|
+
property :boolean, :class => Boolean
|
5
|
+
property :string, :class => String
|
6
|
+
property :integer, :class => Integer
|
7
|
+
property :float, :class => Float
|
8
|
+
property :array, :class => Array
|
9
|
+
property :hash, :class => Hash
|
10
|
+
property :time, :class => Time
|
11
|
+
property :date, :class => Date
|
12
|
+
end
|
13
|
+
|
14
|
+
class TestMappers < Test::Unit::TestCase
|
15
|
+
|
16
|
+
context "create" do
|
17
|
+
setup do
|
18
|
+
@item = Item.create :time => Time.at(1234567890), :date => Date.parse("1972-06-16")
|
19
|
+
end
|
20
|
+
|
21
|
+
should "store unmapped values" do
|
22
|
+
assert_equal Time, @item.instance_eval { @attributes[:time].class }
|
23
|
+
assert_equal Date, @item.instance_eval { @attributes[:date].class }
|
24
|
+
end
|
25
|
+
|
26
|
+
should "not change mapped values" do
|
27
|
+
assert_equal Time.at(1234567890), @item.time
|
28
|
+
assert_equal Date.parse("1972-06-16"), @item.date
|
29
|
+
end
|
30
|
+
|
31
|
+
should "not change mapped values after reload" do
|
32
|
+
@item.reload
|
33
|
+
assert_equal Time.at(1234567890), @item.time
|
34
|
+
assert_equal Date.parse("1972-06-16"), @item.date
|
35
|
+
end
|
36
|
+
|
37
|
+
should "serialize mapped values correctly" do
|
38
|
+
json = redis.hget(context, @item.key)
|
39
|
+
assert_match /1234567890/, json
|
40
|
+
assert_match /"1972-06-16"/, json
|
41
|
+
end
|
42
|
+
|
43
|
+
should "handle nil values" do
|
44
|
+
item = Item.create
|
45
|
+
assert_nil item.boolean
|
46
|
+
assert_nil item.string
|
47
|
+
assert_nil item.integer
|
48
|
+
assert_nil item.float
|
49
|
+
assert_nil item.array
|
50
|
+
assert_nil item.hash
|
51
|
+
assert_nil item.time
|
52
|
+
assert_nil item.date
|
53
|
+
end
|
54
|
+
|
55
|
+
should "reject invalid types" do
|
56
|
+
assert_raise(Remodel::InvalidType) { Item.create :boolean => 'hello' }
|
57
|
+
assert_raise(Remodel::InvalidType) { Item.create :string => true }
|
58
|
+
assert_raise(Remodel::InvalidType) { Item.create :integer => 33.5 }
|
59
|
+
assert_raise(Remodel::InvalidType) { Item.create :float => 5 }
|
60
|
+
assert_raise(Remodel::InvalidType) { Item.create :array => {} }
|
61
|
+
assert_raise(Remodel::InvalidType) { Item.create :hash => [] }
|
62
|
+
assert_raise(Remodel::InvalidType) { Item.create :time => Date.new }
|
63
|
+
assert_raise(Remodel::InvalidType) { Item.create :date => Time.now }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestMonkeypatches < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Boolean" do
|
6
|
+
should "be the superclass of both true and false" do
|
7
|
+
assert true.is_a?(Boolean)
|
8
|
+
assert false.is_a?(Boolean)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context "Class[]" do
|
13
|
+
should "return given Class objects" do
|
14
|
+
assert_equal String, Class[String]
|
15
|
+
end
|
16
|
+
|
17
|
+
should "return the Class object for a given String" do
|
18
|
+
assert_equal String, Class['String']
|
19
|
+
end
|
20
|
+
|
21
|
+
should "return the Class object for a given Symbol" do
|
22
|
+
assert_equal String, Class[:String]
|
23
|
+
end
|
24
|
+
|
25
|
+
should "work for nested classes" do
|
26
|
+
assert_equal Remodel::Entity, Class['Remodel::Entity']
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
|
4
|
+
class TestOneToMany < Test::Unit::TestCase
|
5
|
+
|
6
|
+
class Piece < Remodel::Entity
|
7
|
+
has_one :puzzle, :class => 'TestOneToMany::Puzzle', :reverse => 'pieces'
|
8
|
+
property :color
|
9
|
+
end
|
10
|
+
|
11
|
+
class Puzzle < Remodel::Entity
|
12
|
+
has_many :pieces, :class => 'TestOneToMany::Piece', :reverse => 'puzzle'
|
13
|
+
property :topic
|
14
|
+
end
|
15
|
+
|
16
|
+
context "has_one" do
|
17
|
+
context "association getter" do
|
18
|
+
should "exist" do
|
19
|
+
assert Piece.create.respond_to?(:puzzle)
|
20
|
+
end
|
21
|
+
|
22
|
+
should "return nil by default" do
|
23
|
+
assert_nil Piece.create.puzzle
|
24
|
+
end
|
25
|
+
|
26
|
+
should "return the associated entity" do
|
27
|
+
puzzle = Puzzle.create :topic => 'animals'
|
28
|
+
piece = Piece.create
|
29
|
+
redis.hset(context, "#{piece.key}:puzzle", puzzle.key)
|
30
|
+
assert_equal 'animals', piece.puzzle.topic
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "association setter" do
|
35
|
+
should "exist" do
|
36
|
+
assert Piece.create.respond_to?(:'puzzle=')
|
37
|
+
end
|
38
|
+
|
39
|
+
should "store the key of the associated entity" do
|
40
|
+
puzzle = Puzzle.create
|
41
|
+
piece = Piece.create
|
42
|
+
piece.puzzle = puzzle
|
43
|
+
assert_equal puzzle.key, redis.hget(context, "#{piece.key}:puzzle")
|
44
|
+
end
|
45
|
+
|
46
|
+
should "add the entity to the reverse association" do
|
47
|
+
puzzle = Puzzle.create
|
48
|
+
piece = Piece.create
|
49
|
+
piece.puzzle = puzzle
|
50
|
+
assert_equal 1, puzzle.pieces.size
|
51
|
+
assert_equal piece.id, puzzle.pieces.first.id
|
52
|
+
end
|
53
|
+
|
54
|
+
should "remove the entity from the old reverse association" do
|
55
|
+
puzzle = Puzzle.create
|
56
|
+
piece = puzzle.pieces.create
|
57
|
+
new_puzzle = Puzzle.create
|
58
|
+
piece.puzzle = new_puzzle
|
59
|
+
assert_equal [], puzzle.reload.pieces
|
60
|
+
end
|
61
|
+
|
62
|
+
should "be settable to nil" do
|
63
|
+
piece = Piece.create
|
64
|
+
piece.puzzle = nil
|
65
|
+
assert_nil piece.puzzle
|
66
|
+
end
|
67
|
+
|
68
|
+
should "remove the key if set to nil" do
|
69
|
+
piece = Piece.create
|
70
|
+
piece.puzzle = Puzzle.create
|
71
|
+
piece.puzzle = nil
|
72
|
+
assert_nil redis.hget(context, "#{piece.key}:puzzle")
|
73
|
+
end
|
74
|
+
|
75
|
+
should "remove the entity from the reverse association if set to nil" do
|
76
|
+
puzzle = Puzzle.create
|
77
|
+
piece = Piece.create
|
78
|
+
piece.puzzle = puzzle
|
79
|
+
piece.puzzle = nil
|
80
|
+
puzzle.reload
|
81
|
+
assert_equal 0, puzzle.pieces.size
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "reload" do
|
87
|
+
should "reset has_one associations" do
|
88
|
+
piece = Piece.create :color => 'black'
|
89
|
+
piece.puzzle = Puzzle.create
|
90
|
+
redis.hdel context, "#{piece.key}:puzzle"
|
91
|
+
piece.reload
|
92
|
+
assert_nil piece.puzzle
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestOneToOne < Test::Unit::TestCase
|
4
|
+
|
5
|
+
class Man < Remodel::Entity
|
6
|
+
has_one :wife, :class => 'TestOneToOne::Woman', :reverse => 'husband'
|
7
|
+
property :name
|
8
|
+
end
|
9
|
+
|
10
|
+
class Woman < Remodel::Entity
|
11
|
+
has_one :husband, :class => 'TestOneToOne::Man', :reverse => 'wife'
|
12
|
+
property :name
|
13
|
+
end
|
14
|
+
|
15
|
+
context "both associations" do
|
16
|
+
should "be nil by default" do
|
17
|
+
assert_equal nil, Man.new.wife
|
18
|
+
assert_equal nil, Woman.new.husband
|
19
|
+
end
|
20
|
+
|
21
|
+
context "setter" do
|
22
|
+
setup do
|
23
|
+
@bill = Man.create :name => 'Bill'
|
24
|
+
@mary = Woman.create :name => 'Mary'
|
25
|
+
end
|
26
|
+
|
27
|
+
context "non-nil value" do
|
28
|
+
should "also set husband" do
|
29
|
+
@bill.wife = @mary
|
30
|
+
assert_equal @bill, @mary.husband
|
31
|
+
end
|
32
|
+
|
33
|
+
should "also set wife" do
|
34
|
+
@mary.husband = @bill
|
35
|
+
assert_equal @mary, @bill.wife
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "nil value" do
|
40
|
+
setup do
|
41
|
+
@bill.wife = @mary
|
42
|
+
end
|
43
|
+
|
44
|
+
should "also clear husband" do
|
45
|
+
@bill.wife = nil
|
46
|
+
assert_equal nil, @mary.husband
|
47
|
+
end
|
48
|
+
|
49
|
+
should "also clear wife" do
|
50
|
+
@mary.husband = nil
|
51
|
+
assert_equal nil, @bill.wife
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: remodel-h
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tim Lossen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-07-20 00:00:00 +02:00
|
13
|
+
default_executable: redis-monitor.rb
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: persist your objects to redis hashes.
|
17
|
+
email: tim@lossen.de
|
18
|
+
executables:
|
19
|
+
- redis-monitor.rb
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
files:
|
26
|
+
- .gitignore
|
27
|
+
- LICENSE
|
28
|
+
- README.md
|
29
|
+
- Rakefile
|
30
|
+
- VERSION
|
31
|
+
- bin/redis-monitor.rb
|
32
|
+
- docs/docco.css
|
33
|
+
- docs/remodel.html
|
34
|
+
- example/book.rb
|
35
|
+
- lib/remodel.rb
|
36
|
+
- lib/remodel/entity.rb
|
37
|
+
- lib/remodel/has_many.rb
|
38
|
+
- lib/remodel/mapper.rb
|
39
|
+
- remodel-h.gemspec
|
40
|
+
- remodel.gemspec
|
41
|
+
- test/helper.rb
|
42
|
+
- test/test_entity.rb
|
43
|
+
- test/test_many_to_many.rb
|
44
|
+
- test/test_many_to_one.rb
|
45
|
+
- test/test_mappers.rb
|
46
|
+
- test/test_monkeypatches.rb
|
47
|
+
- test/test_one_to_many.rb
|
48
|
+
- test/test_one_to_one.rb
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: http://github.com/tlossen/remodel
|
51
|
+
licenses: []
|
52
|
+
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options:
|
55
|
+
- --charset=UTF-8
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.5
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: remodel variant which uses hashes
|
77
|
+
test_files:
|
78
|
+
- test/helper.rb
|
79
|
+
- test/test_entity.rb
|
80
|
+
- test/test_many_to_many.rb
|
81
|
+
- test/test_many_to_one.rb
|
82
|
+
- test/test_mappers.rb
|
83
|
+
- test/test_monkeypatches.rb
|
84
|
+
- test/test_one_to_many.rb
|
85
|
+
- test/test_one_to_one.rb
|