has_alter_ego 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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].keys.each do |attr|
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].keys.each do |attr|
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
- private
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'
@@ -2,4 +2,7 @@
2
2
  name: Bruno
3
3
 
4
4
  2:
5
- name: Harald
5
+ name: Harald
6
+
7
+ 3:
8
+ name: Hugo
@@ -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
- - 4
10
- version: 0.0.4
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-11 00:00:00 +02:00
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: false
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.7
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