activerecord 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +65 -0
- data/install.rb +2 -2
- data/lib/active_record.rb +1 -1
- data/lib/active_record/acts/list.rb +13 -13
- data/lib/active_record/associations.rb +38 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +2 -1
- data/lib/active_record/base.rb +44 -20
- data/lib/active_record/connection_adapters/abstract_adapter.rb +10 -11
- data/lib/active_record/connection_adapters/mysql_adapter.rb +6 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +7 -2
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +10 -2
- data/lib/active_record/fixtures.rb +18 -0
- data/lib/active_record/support/binding_of_caller.rb +81 -0
- data/lib/active_record/support/breakpoint.rb +525 -0
- data/lib/active_record/timestamp.rb +17 -5
- data/lib/active_record/transactions.rb +11 -13
- data/lib/active_record/validations.rb +31 -13
- data/rakefile +1 -1
- data/test/abstract_unit.rb +2 -0
- data/test/base_test.rb +29 -9
- data/test/fixtures/db_definitions/mysql.sql +5 -3
- data/test/fixtures/db_definitions/postgresql.sql +2 -0
- data/test/fixtures/db_definitions/sqlite.sql +3 -1
- data/test/fixtures/db_definitions/sqlserver.sql +2 -0
- data/test/fixtures/developer.rb +2 -4
- data/test/fixtures/developers.yml +3 -0
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
- data/test/fixtures/mixin.rb +5 -2
- data/test/fixtures/mixins.yml +27 -11
- data/test/mixin_test.rb +154 -56
- data/test/transactions_test.rb +1 -1
- data/test/validations_test.rb +50 -3
- metadata +4 -2
@@ -7,19 +7,31 @@ module ActiveRecord
|
|
7
7
|
module Timestamp
|
8
8
|
def self.append_features(base) # :nodoc:
|
9
9
|
super
|
10
|
-
|
11
|
-
base.
|
10
|
+
|
11
|
+
base.class_eval do
|
12
|
+
alias_method :create_without_timestamps, :create
|
13
|
+
alias_method :create, :create_with_timestamps
|
14
|
+
|
15
|
+
alias_method :update_without_timestamps, :update
|
16
|
+
alias_method :update, :update_with_timestamps
|
17
|
+
end
|
12
18
|
end
|
13
19
|
|
14
|
-
def
|
20
|
+
def create_with_timestamps
|
15
21
|
write_attribute("created_at", Time.now) if record_timestamps && respond_to?(:created_at) && created_at.nil?
|
16
22
|
write_attribute("created_on", Time.now) if record_timestamps && respond_to?(:created_on) && created_on.nil?
|
17
|
-
|
23
|
+
|
24
|
+
write_attribute("updated_at", Time.now) if record_timestamps && respond_to?(:updated_at)
|
25
|
+
write_attribute("updated_on", Time.now) if record_timestamps && respond_to?(:updated_on)
|
26
|
+
|
27
|
+
create_without_timestamps
|
18
28
|
end
|
19
29
|
|
20
|
-
def
|
30
|
+
def update_with_timestamps
|
21
31
|
write_attribute("updated_at", Time.now) if record_timestamps && respond_to?(:updated_at)
|
22
32
|
write_attribute("updated_on", Time.now) if record_timestamps && respond_to?(:updated_on)
|
33
|
+
|
34
|
+
update_without_timestamps
|
23
35
|
end
|
24
36
|
end
|
25
37
|
|
@@ -77,13 +77,17 @@ module ActiveRecord
|
|
77
77
|
# Tribute: Object-level transactions are implemented by Transaction::Simple by Austin Ziegler.
|
78
78
|
module ClassMethods
|
79
79
|
def transaction(*objects, &block)
|
80
|
-
TRANSACTION_MUTEX.
|
80
|
+
TRANSACTION_MUTEX.synchronize do
|
81
|
+
Thread.current['open_transactions'] ||= 0
|
82
|
+
Thread.current['start_db_transaction'] = (Thread.current['open_transactions'] == 0)
|
83
|
+
Thread.current['open_transactions'] += 1
|
84
|
+
end
|
81
85
|
|
82
86
|
begin
|
83
87
|
objects.each { |o| o.extend(Transaction::Simple) }
|
84
88
|
objects.each { |o| o.start_transaction }
|
85
89
|
|
86
|
-
result = connection.transaction(&block)
|
90
|
+
result = connection.transaction(Thread.current['start_db_transaction'], &block)
|
87
91
|
|
88
92
|
objects.each { |o| o.commit_transaction }
|
89
93
|
return result
|
@@ -91,7 +95,9 @@ module ActiveRecord
|
|
91
95
|
objects.each { |o| o.abort_transaction }
|
92
96
|
raise
|
93
97
|
ensure
|
94
|
-
TRANSACTION_MUTEX.
|
98
|
+
TRANSACTION_MUTEX.synchronize do
|
99
|
+
Thread.current['open_transactions'] -= 1
|
100
|
+
end
|
95
101
|
end
|
96
102
|
end
|
97
103
|
end
|
@@ -101,19 +107,11 @@ module ActiveRecord
|
|
101
107
|
end
|
102
108
|
|
103
109
|
def destroy_with_transactions #:nodoc:
|
104
|
-
|
105
|
-
destroy_without_transactions
|
106
|
-
else
|
107
|
-
transaction { destroy_without_transactions }
|
108
|
-
end
|
110
|
+
transaction { destroy_without_transactions }
|
109
111
|
end
|
110
112
|
|
111
113
|
def save_with_transactions(perform_validation = true) #:nodoc:
|
112
|
-
|
113
|
-
save_without_transactions(perform_validation)
|
114
|
-
else
|
115
|
-
transaction { save_without_transactions(perform_validation) }
|
116
|
-
end
|
114
|
+
transaction { save_without_transactions(perform_validation) }
|
117
115
|
end
|
118
116
|
end
|
119
117
|
end
|
@@ -74,7 +74,8 @@ module ActiveRecord
|
|
74
74
|
# <%= password_field "person", "password_confirmation" %>
|
75
75
|
#
|
76
76
|
# The person has to already have a password attribute (a column in the people table), but the password_confirmation is virtual.
|
77
|
-
# It exists only as an in-memory variable for validating the password. This check is performed
|
77
|
+
# It exists only as an in-memory variable for validating the password. This check is performed only if password_confirmation
|
78
|
+
# is not nil and by default on save.
|
78
79
|
#
|
79
80
|
# Configuration options:
|
80
81
|
# * <tt>message</tt> - A custom error message (default is: "doesn't match confirmation")
|
@@ -85,7 +86,7 @@ module ActiveRecord
|
|
85
86
|
|
86
87
|
for attr_name in attr_names
|
87
88
|
attr_accessor "#{attr_name}_confirmation"
|
88
|
-
class_eval(%(#{validation_method(configuration[:on])} %{errors.add('#{attr_name}', "#{configuration[:message]}") unless #{attr_name} == #{attr_name}_confirmation}))
|
89
|
+
class_eval(%(#{validation_method(configuration[:on])} %{errors.add('#{attr_name}', "#{configuration[:message]}") unless #{attr_name}_confirmation.nil? or #{attr_name} == #{attr_name}_confirmation}))
|
89
90
|
end
|
90
91
|
end
|
91
92
|
|
@@ -96,10 +97,11 @@ module ActiveRecord
|
|
96
97
|
# validates_acceptance_of :eula, :message => "must be abided"
|
97
98
|
# end
|
98
99
|
#
|
99
|
-
# The terms_of_service attribute is entirely virtual. No database column is needed. This check is performed
|
100
|
+
# The terms_of_service attribute is entirely virtual. No database column is needed. This check is performed only if
|
101
|
+
# terms_of_service is not nil and by default on save.
|
100
102
|
#
|
101
103
|
# Configuration options:
|
102
|
-
# * <tt>message</tt> - A custom error message (default is: "
|
104
|
+
# * <tt>message</tt> - A custom error message (default is: "can't be empty")
|
103
105
|
# * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update)
|
104
106
|
#
|
105
107
|
# NOTE: The agreement is considered valid if it's set to the string "1". This makes it easy to relate it to an HTML checkbox.
|
@@ -109,11 +111,11 @@ module ActiveRecord
|
|
109
111
|
|
110
112
|
for attr_name in attr_names
|
111
113
|
attr_accessor(attr_name)
|
112
|
-
class_eval(%(#{validation_method(configuration[:on])} %{errors.add('#{attr_name}', '#{configuration[:message]}') unless #{attr_name} == "1"}))
|
114
|
+
class_eval(%(#{validation_method(configuration[:on])} %{errors.add('#{attr_name}', '#{configuration[:message]}') unless #{attr_name}.nil? or #{attr_name} == "1"}))
|
113
115
|
end
|
114
116
|
end
|
115
117
|
|
116
|
-
# Validates that the specified attributes are neither nil nor empty. Happens by default on
|
118
|
+
# Validates that the specified attributes are neither nil nor empty. Happens by default on save.
|
117
119
|
#
|
118
120
|
# Configuration options:
|
119
121
|
# * <tt>message</tt> - A custom error message (default is: "has already been taken")
|
@@ -196,7 +198,7 @@ module ActiveRecord
|
|
196
198
|
# can be named "davidhh".
|
197
199
|
#
|
198
200
|
# class Person < ActiveRecord::Base
|
199
|
-
# validates_uniqueness_of :user_name
|
201
|
+
# validates_uniqueness_of :user_name, :scope => "account_id"
|
200
202
|
# end
|
201
203
|
#
|
202
204
|
# When the record is created, a check is performed to make sure that no record exist in the database with the given value for the specified
|
@@ -204,12 +206,17 @@ module ActiveRecord
|
|
204
206
|
#
|
205
207
|
# Configuration options:
|
206
208
|
# * <tt>message</tt> - Specifies a custom error message (default is: "has already been taken")
|
209
|
+
# * <tt>scope</tt> - Ensures that the uniqueness is restricted to a condition of "scope = record.scope"
|
207
210
|
def validates_uniqueness_of(*attr_names)
|
208
211
|
configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken] }
|
209
212
|
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
|
210
213
|
|
211
214
|
for attr_name in attr_names
|
212
|
-
|
215
|
+
if scope = configuration[:scope]
|
216
|
+
class_eval(%(validate %{errors.add('#{attr_name}', '#{configuration[:message]}') if self.class.find_first(new_record? ? ['#{attr_name} = ? AND #{scope} = ?', #{attr_name}, #{scope}] : ["#{attr_name} = ? AND id <> ? AND #{scope} = ?", #{attr_name}, id, #{scope}])}))
|
217
|
+
else
|
218
|
+
class_eval(%(validate %{errors.add('#{attr_name}', '#{configuration[:message]}') if self.class.find_first(new_record? ? ['#{attr_name} = ?', #{attr_name}] : ["#{attr_name} = ? AND id <> ?", #{attr_name}, id])}))
|
219
|
+
end
|
213
220
|
end
|
214
221
|
end
|
215
222
|
|
@@ -247,15 +254,21 @@ module ActiveRecord
|
|
247
254
|
# Configuration options:
|
248
255
|
# * <tt>in</tt> - An enumerable object of available items
|
249
256
|
# * <tt>message</tt> - Specifieds a customer error message (default is: "is not included in the list")
|
257
|
+
# * <tt>allows_nil</tt> - If set to true, skips this validation if the attribute is null (default is: false)
|
250
258
|
def validates_inclusion_of(*attr_names)
|
251
259
|
configuration = { :message => ActiveRecord::Errors.default_error_messages[:inclusion], :on => :save }
|
252
260
|
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
|
253
261
|
enum = configuration[:in] || configuration[:within]
|
262
|
+
allow_nil = configuration[:allow_nil]
|
254
263
|
|
255
264
|
raise(ArgumentError, "An object with the method include? is required must be supplied as the :in option of the configuration hash") unless enum.respond_to?("include?")
|
256
265
|
|
257
266
|
for attr_name in attr_names
|
258
|
-
|
267
|
+
if allow_nil
|
268
|
+
class_eval(%(#{validation_method(configuration[:on])} %{errors.add("#{attr_name}", "#{configuration[:message]}") unless #{attr_name}.nil? or (#{enum.inspect}).include?(#{attr_name}) }))
|
269
|
+
else
|
270
|
+
class_eval(%(#{validation_method(configuration[:on])} %{errors.add("#{attr_name}", "#{configuration[:message]}") unless (#{enum.inspect}).include?(#{attr_name}) }))
|
271
|
+
end
|
259
272
|
end
|
260
273
|
end
|
261
274
|
|
@@ -393,19 +406,24 @@ module ActiveRecord
|
|
393
406
|
|
394
407
|
# Will add an error message to each of the attributes in +attributes+ that is empty (defined by <tt>attribute_present?</tt>).
|
395
408
|
def add_on_empty(attributes, msg = @@default_error_messages[:empty])
|
396
|
-
[attributes].flatten
|
409
|
+
for attr in [attributes].flatten
|
410
|
+
value = @base.respond_to?(attr.to_s) ? @base.send(attr.to_s) : @base[attr.to_s]
|
411
|
+
is_empty = value.respond_to?("empty?") ? value.empty? : false
|
412
|
+
add(attr, msg) unless !value.nil? && !is_empty
|
413
|
+
end
|
397
414
|
end
|
398
415
|
|
399
416
|
# Will add an error message to each of the attributes in +attributes+ that has a length outside of the passed boundary +range+.
|
400
417
|
# If the length is above the boundary, the too_long_msg message will be used. If below, the too_short_msg.
|
401
418
|
def add_on_boundary_breaking(attributes, range, too_long_msg = @@default_error_messages[:too_long], too_short_msg = @@default_error_messages[:too_short])
|
402
419
|
for attr in [attributes].flatten
|
403
|
-
|
404
|
-
add(attr,
|
420
|
+
value = @base.respond_to?(attr.to_s) ? @base.send(attr.to_s) : @base[attr.to_s]
|
421
|
+
add(attr, too_short_msg % range.begin) if value && value.length < range.begin
|
422
|
+
add(attr, too_long_msg % range.end) if value && value.length > range.end
|
405
423
|
end
|
406
424
|
end
|
407
425
|
|
408
|
-
alias :
|
426
|
+
alias :add_on_boundry_breaking :add_on_boundary_breaking
|
409
427
|
|
410
428
|
# Returns true if the specified +attribute+ has errors associated with it.
|
411
429
|
def invalid?(attribute)
|
data/rakefile
CHANGED
@@ -8,7 +8,7 @@ require 'rake/contrib/rubyforgepublisher'
|
|
8
8
|
|
9
9
|
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
10
10
|
PKG_NAME = 'activerecord'
|
11
|
-
PKG_VERSION = '1.
|
11
|
+
PKG_VERSION = '1.3.0' + PKG_BUILD
|
12
12
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
13
13
|
|
14
14
|
PKG_FILES = FileList[
|
data/test/abstract_unit.rb
CHANGED
@@ -4,6 +4,8 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
|
|
4
4
|
require 'test/unit'
|
5
5
|
require 'active_record'
|
6
6
|
require 'active_record/fixtures'
|
7
|
+
require 'active_record/support/binding_of_caller'
|
8
|
+
require 'active_record/support/breakpoint'
|
7
9
|
require 'connection'
|
8
10
|
|
9
11
|
class Test::Unit::TestCase #:nodoc:
|
data/test/base_test.rb
CHANGED
@@ -26,9 +26,7 @@ end
|
|
26
26
|
class Booleantest < ActiveRecord::Base; end
|
27
27
|
|
28
28
|
class BasicsTest < Test::Unit::TestCase
|
29
|
-
|
30
|
-
@topic_fixtures, @companies = create_fixtures "topics", "companies"
|
31
|
-
end
|
29
|
+
fixtures :topics, :companies
|
32
30
|
|
33
31
|
def test_set_attributes
|
34
32
|
topic = Topic.find(1)
|
@@ -36,7 +34,7 @@ class BasicsTest < Test::Unit::TestCase
|
|
36
34
|
topic.save
|
37
35
|
assert_equal("Budget", topic.title)
|
38
36
|
assert_equal("Jason", topic.author_name)
|
39
|
-
assert_equal(@
|
37
|
+
assert_equal(@topics["first"]["author_email_address"], Topic.find(1).author_email_address)
|
40
38
|
end
|
41
39
|
|
42
40
|
def test_integers_as_nil
|
@@ -187,14 +185,14 @@ class BasicsTest < Test::Unit::TestCase
|
|
187
185
|
def test_load
|
188
186
|
topics = Topic.find_all nil, "id"
|
189
187
|
assert_equal(2, topics.size)
|
190
|
-
assert_equal(@
|
188
|
+
assert_equal(@topics["first"]["title"], topics.first.title)
|
191
189
|
end
|
192
190
|
|
193
191
|
def test_load_with_condition
|
194
192
|
topics = Topic.find_all "author_name = 'Mary'"
|
195
193
|
|
196
194
|
assert_equal(1, topics.size)
|
197
|
-
assert_equal(@
|
195
|
+
assert_equal(@topics["second"]["title"], topics.first.title)
|
198
196
|
end
|
199
197
|
|
200
198
|
def test_table_name_guesses
|
@@ -262,11 +260,15 @@ class BasicsTest < Test::Unit::TestCase
|
|
262
260
|
end
|
263
261
|
|
264
262
|
def test_update_all
|
265
|
-
Topic.update_all
|
263
|
+
assert_equal 2, Topic.update_all("content = 'bulk updated!'")
|
266
264
|
assert_equal "bulk updated!", Topic.find(1).content
|
267
265
|
assert_equal "bulk updated!", Topic.find(2).content
|
268
266
|
end
|
269
|
-
|
267
|
+
|
268
|
+
def test_delete_all
|
269
|
+
assert_equal 2, Topic.delete_all
|
270
|
+
end
|
271
|
+
|
270
272
|
def test_update_by_condition
|
271
273
|
Topic.update_all "content = 'bulk updated!'", "approved = 1"
|
272
274
|
assert_equal "Have a nice day", Topic.find(1).content
|
@@ -556,4 +558,22 @@ class BasicsTest < Test::Unit::TestCase
|
|
556
558
|
topic = Topic.create('content' => content)
|
557
559
|
assert_equal content, Topic.find(topic.id).content
|
558
560
|
end
|
559
|
-
|
561
|
+
|
562
|
+
def test_class_level_destroy
|
563
|
+
should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
|
564
|
+
@first.replies << should_be_destroyed_reply
|
565
|
+
|
566
|
+
Topic.destroy(1)
|
567
|
+
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1) }
|
568
|
+
assert_raises(ActiveRecord::RecordNotFound) { Reply.find(should_be_destroyed_reply.id) }
|
569
|
+
end
|
570
|
+
|
571
|
+
def test_class_level_delete
|
572
|
+
should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
|
573
|
+
@first.replies << should_be_destroyed_reply
|
574
|
+
|
575
|
+
Topic.delete(1)
|
576
|
+
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1) }
|
577
|
+
assert_nothing_raised { Reply.find(should_be_destroyed_reply.id) }
|
578
|
+
end
|
579
|
+
end
|
@@ -36,6 +36,7 @@ CREATE TABLE `topics` (
|
|
36
36
|
CREATE TABLE `developers` (
|
37
37
|
`id` int(11) NOT NULL auto_increment,
|
38
38
|
`name` varchar(100) default NULL,
|
39
|
+
`salary` int(11) default 70000,
|
39
40
|
PRIMARY KEY (`id`)
|
40
41
|
);
|
41
42
|
|
@@ -101,10 +102,11 @@ CREATE TABLE `mixins` (
|
|
101
102
|
`id` int(11) NOT NULL auto_increment,
|
102
103
|
`parent_id` int(11) default NULL,
|
103
104
|
`pos` int(11) default NULL,
|
104
|
-
`lft` int(11) default NULL,
|
105
|
-
`rgt` int(11) default NULL,
|
106
|
-
`root_id` int(11) default NULL,
|
107
105
|
`created_at` datetime default NULL,
|
108
106
|
`updated_at` datetime default NULL,
|
107
|
+
`lft` int(11) default NULL,
|
108
|
+
`rgt` int(11) default NULL,
|
109
|
+
`root_id` int(11) default NULL,
|
110
|
+
`type` varchar(40) default NULL,
|
109
111
|
PRIMARY KEY (`id`)
|
110
112
|
);
|
@@ -29,6 +29,7 @@ CREATE TABLE developers_projects (
|
|
29
29
|
CREATE TABLE developers (
|
30
30
|
id serial,
|
31
31
|
name character varying(100),
|
32
|
+
salary integer DEFAULT 70000,
|
32
33
|
PRIMARY KEY (id)
|
33
34
|
);
|
34
35
|
SELECT setval('developers_id_seq', 100);
|
@@ -117,6 +118,7 @@ CREATE TABLE colnametests (
|
|
117
118
|
CREATE TABLE mixins (
|
118
119
|
id serial,
|
119
120
|
parent_id integer,
|
121
|
+
type character varying,
|
120
122
|
pos integer,
|
121
123
|
lft integer,
|
122
124
|
rgt integer,
|
@@ -32,7 +32,8 @@ CREATE TABLE 'topics' (
|
|
32
32
|
|
33
33
|
CREATE TABLE 'developers' (
|
34
34
|
'id' INTEGER PRIMARY KEY NOT NULL,
|
35
|
-
'name' TEXT DEFAULT NULL
|
35
|
+
'name' TEXT DEFAULT NULL,
|
36
|
+
'salary' INTEGER DEFAULT 70000
|
36
37
|
);
|
37
38
|
|
38
39
|
CREATE TABLE 'projects' (
|
@@ -89,6 +90,7 @@ CREATE TABLE 'colnametests' (
|
|
89
90
|
CREATE TABLE 'mixins' (
|
90
91
|
'id' INTEGER NOT NULL PRIMARY KEY,
|
91
92
|
'parent_id' INTEGER DEFAULT NULL,
|
93
|
+
'type' VARCHAR(40) DEFAULT NULL,
|
92
94
|
'pos' INTEGER DEFAULT NULL,
|
93
95
|
'lft' INTEGER DEFAULT NULL,
|
94
96
|
'rgt' INTEGER DEFAULT NULL,
|
@@ -41,6 +41,7 @@ CREATE TABLE developers (
|
|
41
41
|
CREATE TABLE projects (
|
42
42
|
id int NOT NULL IDENTITY(1, 1),
|
43
43
|
name varchar(100) default NULL,
|
44
|
+
salary int default 70000,
|
44
45
|
PRIMARY KEY (id)
|
45
46
|
);
|
46
47
|
|
@@ -98,6 +99,7 @@ CREATE TABLE colnametests (
|
|
98
99
|
CREATE TABLE mixins (
|
99
100
|
id int NOT NULL IDENTITY(1, 1),
|
100
101
|
parent_id int default NULL,
|
102
|
+
type varchar(40) default NULL,
|
101
103
|
pos int default NULL,
|
102
104
|
lft int default NULL,
|
103
105
|
rgt int default NULL,
|
data/test/fixtures/developer.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
class Developer < ActiveRecord::Base
|
2
2
|
has_and_belongs_to_many :projects
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
errors.add_on_boundary_breaking("name", 3..20)
|
7
|
-
end
|
4
|
+
validates_inclusion_of :salary, :in => 50000..200000
|
5
|
+
validates_length_of :name, :within => 3..20
|
8
6
|
end
|
Binary file
|
Binary file
|
data/test/fixtures/mixin.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
class Mixin < ActiveRecord::Base
|
2
|
-
acts_as_tree :foreign_key => "parent_id", :order => "id"
|
3
2
|
|
4
3
|
end
|
5
4
|
|
6
|
-
class
|
5
|
+
class TreeMixin < Mixin
|
6
|
+
acts_as_tree :foreign_key => "parent_id", :order => "id"
|
7
|
+
end
|
8
|
+
|
9
|
+
class ListMixin < Mixin
|
7
10
|
acts_as_list :column => "pos", :scope => :parent
|
8
11
|
|
9
12
|
def self.table_name() "mixins" end
|
data/test/fixtures/mixins.yml
CHANGED
@@ -1,14 +1,30 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# tree mixins
|
2
|
+
tree_1:
|
3
|
+
id: 1001
|
4
|
+
type: TreeMixin
|
4
5
|
parent_id: 0
|
5
6
|
|
6
|
-
|
7
|
-
id:
|
8
|
-
|
9
|
-
parent_id:
|
7
|
+
tree_2:
|
8
|
+
id: 1002
|
9
|
+
type: TreeMixin
|
10
|
+
parent_id: 1001
|
10
11
|
|
11
|
-
|
12
|
-
id:
|
13
|
-
|
14
|
-
parent_id:
|
12
|
+
tree_3:
|
13
|
+
id: 1003
|
14
|
+
type: TreeMixin
|
15
|
+
parent_id: 1002
|
16
|
+
|
17
|
+
tree_4:
|
18
|
+
id: 1004
|
19
|
+
type: TreeMixin
|
20
|
+
parent_id: 1001
|
21
|
+
|
22
|
+
# List mixins
|
23
|
+
|
24
|
+
<% (1..4).each do |counter| %>
|
25
|
+
list_<%= counter %>:
|
26
|
+
id: <%= counter+1006 %>
|
27
|
+
pos: <%= counter %>
|
28
|
+
type: ListMixin
|
29
|
+
parent_id: 5
|
30
|
+
<% end %>
|