has_alter_ego 0.0.4 → 0.0.5
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/Changelog.md +7 -0
- data/README.md +18 -0
- data/lib/has_alter_ego.rb +25 -9
- data/test/db/fixtures/alter_egos/sellers.yml +4 -1
- data/test/has_alter_ego_test.rb +64 -31
- data/test/test_helper.rb +52 -0
- metadata +10 -15
data/Changelog.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# 0.0.5 (2010-06-13)
|
2
|
+
* Implemented smart associations, e.g.
|
3
|
+
category_by_name: Sport # => @car.category = Category.find_by_name("Sport")
|
4
|
+
sellers_by_name_and_active: [Hugo, true] # @car.sellers = Seller.find_all_by_name_and_active("Hugo", true)
|
5
|
+
sellers_by_name_and_active: [[Hugo, Egon], true] # @car.sellers = Seller.find_all_by_name_and_active(["Hugo", "Egon"], true)
|
6
|
+
* mark objects as modified when saved with save!
|
7
|
+
|
1
8
|
# 0.0.4 (2010-06-11)
|
2
9
|
* fix some bugs esp. wrt associations
|
3
10
|
* added a on_seed hook which allows for custom login on seed
|
data/README.md
CHANGED
@@ -124,6 +124,24 @@ If you don't want to inherit changes for an object without actually modifying it
|
|
124
124
|
@car.alter_ego_state
|
125
125
|
=> "default"
|
126
126
|
|
127
|
+
# Smart associations
|
128
|
+
|
129
|
+
It's possible to define dynamic associations in the seed data which is helpful if the IDs of the associated objects are
|
130
|
+
not known or the associations depends on the state of the objects. This is done by appending *_by* clauses to the
|
131
|
+
association name, similar to the dynamic finders in ActiveRecord::Base.
|
132
|
+
|
133
|
+
**Example:**
|
134
|
+
db/fixtures/car.yml:
|
135
|
+
1:
|
136
|
+
brand: Lotus
|
137
|
+
model: Elise
|
138
|
+
category_id: 3 # Static way of specifying associations
|
139
|
+
category_by_name: Sport # => @car.category = Category.find_by_name("Sport")
|
140
|
+
|
141
|
+
sellers_by_name_and_active: [Hugo, true] # @car.sellers = Seller.find_all_by_name_and_active("Hugo", true)
|
142
|
+
sellers_by_name_and_active: [[Hugo, Egon], true] # @car.sellers = Seller.find_all_by_name_and_active(["Hugo", "Egon"], true)
|
143
|
+
|
144
|
+
|
127
145
|
# Custom logic on seed
|
128
146
|
|
129
147
|
has_alter_ego provides a hook for adding custom logic when an object is created or updated from the seed definitions.
|
data/lib/has_alter_ego.rb
CHANGED
@@ -46,10 +46,7 @@ module HasAlterEgo
|
|
46
46
|
if db_object
|
47
47
|
raise "There is already a #{db_object.class} with id #{db_object.id} in the database." unless db_object.has_alter_ego?
|
48
48
|
if db_object.alter_ego.state == 'default'
|
49
|
-
yml[primary_key]
|
50
|
-
next unless db_object.respond_to?(attr)
|
51
|
-
db_object.send(attr+"=", yml[primary_key][attr])
|
52
|
-
end
|
49
|
+
assign_attributes db_object, yml[primary_key]
|
53
50
|
db_object.on_seed(yml[primary_key])
|
54
51
|
db_object.save_without_alter_ego
|
55
52
|
end
|
@@ -60,10 +57,7 @@ module HasAlterEgo
|
|
60
57
|
|
61
58
|
db_object = self.new
|
62
59
|
db_object[self.primary_key] = primary_key
|
63
|
-
yml[primary_key]
|
64
|
-
next unless db_object.respond_to?(attr)
|
65
|
-
db_object.send(attr+"=" , yml[primary_key][attr])
|
66
|
-
end
|
60
|
+
assign_attributes db_object, yml[primary_key]
|
67
61
|
db_object.build_alter_ego
|
68
62
|
db_object.alter_ego.state = 'default'
|
69
63
|
db_object.on_seed(yml[primary_key])
|
@@ -71,7 +65,25 @@ module HasAlterEgo
|
|
71
65
|
end
|
72
66
|
end
|
73
67
|
|
74
|
-
|
68
|
+
def assign_attributes obj, yml
|
69
|
+
reflections = self.reflect_on_all_associations
|
70
|
+
yml.keys.each do |attr|
|
71
|
+
if obj.respond_to?(attr)
|
72
|
+
obj.send(attr+"=" , yml[attr])
|
73
|
+
else
|
74
|
+
# Handle smart associations
|
75
|
+
reflections.select{|r| attr.start_with?(r.name.to_s+"_by_")}.each do |r|
|
76
|
+
finder = [:has_one, :belongs_to].include?(r.macro) ? "find" : "find_all"
|
77
|
+
if attr.index("_and_")
|
78
|
+
objects = r.klass.send(attr.gsub(r.name.to_s, finder), *(yml[attr]))
|
79
|
+
else
|
80
|
+
objects = r.klass.send(attr.gsub(r.name.to_s, finder), yml[attr])
|
81
|
+
end
|
82
|
+
obj.send(r.name.to_s+"=", objects) if objects.present?
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
75
87
|
|
76
88
|
def get_yml
|
77
89
|
filename = File.join(RAILS_ROOT, "db", "fixtures", "alter_egos", self.table_name + ".yml")
|
@@ -103,6 +115,10 @@ module HasAlterEgo
|
|
103
115
|
save_without_alter_ego perform_validation
|
104
116
|
end
|
105
117
|
|
118
|
+
def save!
|
119
|
+
save || raise(RecordNotSaved)
|
120
|
+
end
|
121
|
+
|
106
122
|
def destroy
|
107
123
|
if self.alter_ego
|
108
124
|
self.alter_ego.state = 'destroyed'
|
data/test/has_alter_ego_test.rb
CHANGED
@@ -1,36 +1,5 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
class Seller < ActiveRecord::Base
|
5
|
-
has_and_belongs_to_many :cars
|
6
|
-
has_alter_ego
|
7
|
-
end
|
8
|
-
|
9
|
-
class Car < ActiveRecord::Base
|
10
|
-
has_many :tires
|
11
|
-
has_and_belongs_to_many :sellers
|
12
|
-
has_alter_ego
|
13
|
-
attr_accessor :tires_count
|
14
|
-
|
15
|
-
def on_seed attributes
|
16
|
-
self[:tires_count] = attributes["custom_data"]["tires"] if attributes["custom_data"]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
class Bike < ActiveRecord::Base
|
21
|
-
end
|
22
|
-
|
23
|
-
class Scooter < ActiveRecord::Base
|
24
|
-
end
|
25
|
-
|
26
|
-
class Tire < ActiveRecord::Base
|
27
|
-
end
|
28
|
-
|
29
|
-
class Drink < ActiveRecord::Base
|
30
|
-
set_primary_key :name
|
31
|
-
has_alter_ego
|
32
|
-
end
|
33
|
-
|
34
3
|
class HasAlterEgoTest < Test::Unit::TestCase
|
35
4
|
def test_space_gets_reserved
|
36
5
|
c = Car.create
|
@@ -206,4 +175,68 @@ class HasAlterEgoTest < Test::Unit::TestCase
|
|
206
175
|
|
207
176
|
assert_equal [1,2], c.seller_ids
|
208
177
|
end
|
178
|
+
|
179
|
+
def test_smart_habtm
|
180
|
+
Car.destroy_all
|
181
|
+
AlterEgo.find_all_by_alter_ego_object_type("Car").map(&:destroy)
|
182
|
+
Car.class_eval do
|
183
|
+
def self.get_yml
|
184
|
+
return {1 => {
|
185
|
+
"brand" => "Lotus",
|
186
|
+
"model" => "Elise",
|
187
|
+
"sellers_by_name" => ["Harald", "Hugo"]}}
|
188
|
+
end
|
189
|
+
end
|
190
|
+
Car.parse_yml
|
191
|
+
assert_equal 1, Car.count
|
192
|
+
assert_equal 2, Car.first.sellers.size
|
193
|
+
assert_equal [2,3].sort, Car.first.seller_ids.sort
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_smart_has_many
|
197
|
+
Light.create(:color => "blue", :active => true)
|
198
|
+
Light.create(:color => "yellow", :active => true)
|
199
|
+
Light.create(:color => "red", :active => true)
|
200
|
+
Light.create(:color => "green", :active => false)
|
201
|
+
Bike.destroy_all
|
202
|
+
Bike.class_eval do
|
203
|
+
def self.get_yml
|
204
|
+
return {1 => {
|
205
|
+
"lights_by_color_and_active" => [["blue", "yellow", "green"], true]}}
|
206
|
+
end
|
207
|
+
end
|
208
|
+
Bike.parse_yml
|
209
|
+
assert_equal 1, Bike.count
|
210
|
+
assert_equal 2, Bike.first.lights.size
|
211
|
+
assert_equal Light.find_all_by_color(["blue", "yellow"]), Bike.first.lights
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_smart_has_one
|
215
|
+
Creator.create(:name => "Martin")
|
216
|
+
Creator.create(:name => "Mike")
|
217
|
+
Drink.destroy_all
|
218
|
+
Drink.class_eval do
|
219
|
+
def self.get_yml
|
220
|
+
return {1 => {
|
221
|
+
"creator_by_name" => ["Mike"]}}
|
222
|
+
end
|
223
|
+
end
|
224
|
+
Drink.parse_yml
|
225
|
+
assert_equal 1, Drink.count
|
226
|
+
assert_equal Creator.find_by_name("Mike"), Drink.first.creator
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_smart_belongs_to
|
230
|
+
|
231
|
+
Creator.class_eval do
|
232
|
+
def self.get_yml
|
233
|
+
return {1 => {
|
234
|
+
"name" => "Bernd",
|
235
|
+
"drink_by_name" => "water"}}
|
236
|
+
end
|
237
|
+
end
|
238
|
+
Creator.parse_yml
|
239
|
+
c = Creator.find_by_name "Bernd"
|
240
|
+
assert_equal Drink.find_by_name("water"), c.drink
|
241
|
+
end
|
209
242
|
end
|
data/test/test_helper.rb
CHANGED
@@ -25,6 +25,12 @@ silence_stream(STDOUT) do
|
|
25
25
|
create_table :bikes
|
26
26
|
create_table :scooters
|
27
27
|
|
28
|
+
create_table :lights do |t|
|
29
|
+
t.string :color
|
30
|
+
t.boolean :active
|
31
|
+
t.integer :bike_id
|
32
|
+
end
|
33
|
+
|
28
34
|
create_table :tires do |t|
|
29
35
|
t.integer :car_id
|
30
36
|
end
|
@@ -34,6 +40,11 @@ silence_stream(STDOUT) do
|
|
34
40
|
t.string :color
|
35
41
|
end
|
36
42
|
|
43
|
+
create_table :creators do |t|
|
44
|
+
t.string :name
|
45
|
+
t.string :drink_id
|
46
|
+
end
|
47
|
+
|
37
48
|
create_table :sellers do |t|
|
38
49
|
t.string :name
|
39
50
|
end
|
@@ -43,4 +54,45 @@ silence_stream(STDOUT) do
|
|
43
54
|
end
|
44
55
|
|
45
56
|
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
class Seller < ActiveRecord::Base
|
61
|
+
has_and_belongs_to_many :cars
|
62
|
+
has_alter_ego
|
63
|
+
end
|
64
|
+
|
65
|
+
class Car < ActiveRecord::Base
|
66
|
+
has_many :tires
|
67
|
+
has_and_belongs_to_many :sellers
|
68
|
+
has_alter_ego
|
69
|
+
attr_accessor :tires_count
|
70
|
+
|
71
|
+
def on_seed attributes
|
72
|
+
self[:tires_count] = attributes["custom_data"]["tires"] if attributes["custom_data"]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Bike < ActiveRecord::Base
|
77
|
+
has_many :lights
|
78
|
+
end
|
79
|
+
|
80
|
+
class Scooter < ActiveRecord::Base
|
81
|
+
end
|
82
|
+
|
83
|
+
class Light < ActiveRecord::Base
|
84
|
+
end
|
85
|
+
|
86
|
+
class Tire < ActiveRecord::Base
|
87
|
+
end
|
88
|
+
|
89
|
+
class Drink < ActiveRecord::Base
|
90
|
+
set_primary_key :name
|
91
|
+
has_one :creator
|
92
|
+
has_alter_ego
|
93
|
+
end
|
94
|
+
|
95
|
+
class Creator < ActiveRecord::Base
|
96
|
+
belongs_to :drink
|
97
|
+
has_alter_ego
|
46
98
|
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: has_alter_ego
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 23
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
8
|
+
- 5
|
9
|
+
version: 0.0.5
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- "Andr\xC3\xA9 Duffeck"
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-06-
|
17
|
+
date: 2010-06-13 00:00:00 +02:00
|
19
18
|
default_executable:
|
20
19
|
dependencies: []
|
21
20
|
|
@@ -29,24 +28,24 @@ extensions: []
|
|
29
28
|
extra_rdoc_files: []
|
30
29
|
|
31
30
|
files:
|
32
|
-
- lib/has_alter_ego/alter_ego.rb
|
33
|
-
- lib/has_alter_ego/dumper.rb
|
34
31
|
- lib/generators/has_alter_ego_generator.rb
|
35
32
|
- lib/has_alter_ego.rb
|
33
|
+
- lib/has_alter_ego/dumper.rb
|
34
|
+
- lib/has_alter_ego/alter_ego.rb
|
36
35
|
- lib/tasks/has_alter_ego.rake
|
37
|
-
- Changelog.md
|
38
36
|
- README.md
|
37
|
+
- Changelog.md
|
39
38
|
- Rakefile
|
40
39
|
- rails/init.rb
|
41
40
|
- generators/has_alter_ego/templates/create_alter_egos.rb
|
42
41
|
- generators/has_alter_ego/has_alter_ego_generator.rb
|
42
|
+
- test/db/fixtures/alter_egos/drinks.yml
|
43
|
+
- test/db/fixtures/alter_egos/cars.yml
|
43
44
|
- test/db/fixtures/alter_egos/sellers.yml
|
44
45
|
- test/db/fixtures/alter_egos/bikes.yml
|
45
|
-
- test/db/fixtures/alter_egos/cars.yml
|
46
|
-
- test/db/fixtures/alter_egos/drinks.yml
|
47
46
|
- test/test_helper.rb
|
48
47
|
- test/has_alter_ego_test.rb
|
49
|
-
has_rdoc:
|
48
|
+
has_rdoc: true
|
50
49
|
homepage: http://github.com/aduffeck/has_alter_ego
|
51
50
|
licenses: []
|
52
51
|
|
@@ -56,27 +55,23 @@ rdoc_options: []
|
|
56
55
|
require_paths:
|
57
56
|
- lib
|
58
57
|
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
-
none: false
|
60
58
|
requirements:
|
61
59
|
- - ">="
|
62
60
|
- !ruby/object:Gem::Version
|
63
|
-
hash: 3
|
64
61
|
segments:
|
65
62
|
- 0
|
66
63
|
version: "0"
|
67
64
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
-
none: false
|
69
65
|
requirements:
|
70
66
|
- - ">="
|
71
67
|
- !ruby/object:Gem::Version
|
72
|
-
hash: 3
|
73
68
|
segments:
|
74
69
|
- 0
|
75
70
|
version: "0"
|
76
71
|
requirements: []
|
77
72
|
|
78
73
|
rubyforge_project:
|
79
|
-
rubygems_version: 1.3.
|
74
|
+
rubygems_version: 1.3.6
|
80
75
|
signing_key:
|
81
76
|
specification_version: 3
|
82
77
|
summary: A Rails plugin which makes it possible to keep seed and live data in parallel
|