tenacity 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/EXTEND.rdoc +11 -1
- data/README.rdoc +4 -1
- data/Rakefile +20 -9
- data/history.txt +21 -0
- data/lib/tenacity.rb +12 -4
- data/lib/tenacity/associates_proxy.rb +67 -0
- data/lib/tenacity/association.rb +19 -6
- data/lib/tenacity/associations/has_many.rb +6 -0
- data/lib/tenacity/class_methods.rb +52 -1
- data/lib/tenacity/instance_methods.rb +7 -3
- data/lib/tenacity/orm_ext/activerecord.rb +30 -13
- data/lib/tenacity/orm_ext/couchrest.rb +140 -0
- data/lib/tenacity/orm_ext/datamapper.rb +139 -0
- data/lib/tenacity/orm_ext/mongo_mapper.rb +88 -80
- data/lib/tenacity/orm_ext/mongoid.rb +108 -0
- data/lib/tenacity/orm_ext/sequel.rb +134 -0
- data/lib/tenacity/version.rb +1 -1
- data/tenacity.gemspec +14 -3
- data/test/association_features/belongs_to_test.rb +42 -0
- data/test/association_features/has_many_test.rb +110 -0
- data/test/association_features/has_one_test.rb +41 -0
- data/test/associations/belongs_to_test.rb +36 -127
- data/test/associations/has_many_test.rb +77 -196
- data/test/associations/has_one_test.rb +22 -84
- data/test/core/classmethods_test.rb +24 -22
- data/test/fixtures/active_record_has_many_target.rb +10 -0
- data/test/fixtures/active_record_has_one_target.rb +10 -0
- data/test/fixtures/{active_record_nuts.rb → active_record_nut.rb} +0 -0
- data/test/fixtures/active_record_object.rb +17 -0
- data/test/fixtures/couch_rest_door.rb +0 -2
- data/test/fixtures/couch_rest_has_many_target.rb +12 -0
- data/test/fixtures/couch_rest_has_one_target.rb +12 -0
- data/test/fixtures/couch_rest_object.rb +19 -0
- data/test/fixtures/couch_rest_windshield.rb +0 -2
- data/test/fixtures/data_mapper_has_many_target.rb +19 -0
- data/test/fixtures/data_mapper_has_one_target.rb +19 -0
- data/test/fixtures/data_mapper_object.rb +20 -0
- data/test/fixtures/mongo_mapper_ash_tray.rb +0 -2
- data/test/fixtures/mongo_mapper_dashboard.rb +0 -2
- data/test/fixtures/mongo_mapper_has_many_target.rb +11 -0
- data/test/fixtures/mongo_mapper_has_one_target.rb +11 -0
- data/test/fixtures/mongo_mapper_object.rb +18 -0
- data/test/fixtures/mongo_mapper_vent.rb +0 -2
- data/test/fixtures/mongo_mapper_wheel.rb +0 -2
- data/test/fixtures/mongoid_has_many_target.rb +13 -0
- data/test/fixtures/mongoid_has_one_target.rb +13 -0
- data/test/fixtures/mongoid_object.rb +20 -0
- data/test/fixtures/sequel_has_many_target.rb +10 -0
- data/test/fixtures/sequel_has_one_target.rb +10 -0
- data/test/fixtures/sequel_object.rb +17 -0
- data/test/helpers/active_record_test_helper.rb +51 -0
- data/test/helpers/data_mapper_test_helper.rb +44 -0
- data/test/helpers/mongoid_test_helper.rb +21 -0
- data/test/helpers/sequel_test_helper.rb +60 -0
- data/test/orm_ext/activerecord_test.rb +55 -35
- data/test/orm_ext/couchrest_test.rb +66 -46
- data/test/orm_ext/datamapper_test.rb +112 -0
- data/test/orm_ext/mongo_mapper_test.rb +64 -44
- data/test/orm_ext/mongoid_test.rb +121 -0
- data/test/orm_ext/sequel_test.rb +113 -0
- data/test/test_helper.rb +87 -11
- metadata +159 -59
- data/lib/tenacity/orm_ext/couchrest/couchrest_extended_document.rb +0 -42
- data/lib/tenacity/orm_ext/couchrest/couchrest_model.rb +0 -44
- data/lib/tenacity/orm_ext/couchrest/tenacity_class_methods.rb +0 -43
- data/lib/tenacity/orm_ext/couchrest/tenacity_instance_methods.rb +0 -21
- data/test/fixtures/couch_rest_radio.rb +0 -10
- data/test/fixtures/mongo_mapper_button.rb +0 -6
data/.gitignore
CHANGED
data/EXTEND.rdoc
CHANGED
@@ -30,7 +30,8 @@ return nil.
|
|
30
30
|
_t_find_bulk(ids=[])
|
31
31
|
|
32
32
|
Find many objects by the specified ids, and return them in an array.
|
33
|
-
If no objects could be found, return an empty array.
|
33
|
+
If no objects could be found, return an empty array. If only some of
|
34
|
+
the objects could be found, then simply return those objects in the array.
|
34
35
|
|
35
36
|
_t_find_first_by_associate(property, id)
|
36
37
|
|
@@ -41,6 +42,15 @@ and return it. If no object could be found, return nil.
|
|
41
42
|
|
42
43
|
Find all objects by the specified property name, with the specified id, and
|
43
44
|
return them in an array. If no objects could be found, return an empty array.
|
45
|
+
If only some of the objects could be found, then simply return those objects
|
46
|
+
in the array.
|
47
|
+
|
48
|
+
_t_delete(ids, run_callbacks=true)
|
49
|
+
|
50
|
+
Delete all objects with the specified ids. If <tt>run_callbacks</tt> is true, the
|
51
|
+
objects should be deleted in such a way that their delete callback methods
|
52
|
+
are run. If false, the objects should be deleted in such a way that their
|
53
|
+
delete callback meethods are not run. Return nothing.
|
44
54
|
|
45
55
|
_t_initialize_has_many_association(association)
|
46
56
|
|
data/README.rdoc
CHANGED
@@ -83,8 +83,11 @@ much the same way, supporting many of the same options.
|
|
83
83
|
== Supported Database Clients
|
84
84
|
|
85
85
|
* ActiveRecord
|
86
|
-
* MongoMapper
|
87
86
|
* CouchRest (CouchModel and ExtendedDocument)
|
87
|
+
* DataMapper
|
88
|
+
* MongoMapper
|
89
|
+
* Mongoid
|
90
|
+
* Sequel
|
88
91
|
|
89
92
|
See EXTEND.rdoc for information on extending Tenacity to work with other database clients.
|
90
93
|
|
data/Rakefile
CHANGED
@@ -10,16 +10,21 @@ rescue Bundler::BundlerError => e
|
|
10
10
|
$stderr.puts "Run `bundle install` to install missing gems"
|
11
11
|
exit e.status_code
|
12
12
|
end
|
13
|
-
require 'rake'
|
14
13
|
|
14
|
+
require 'rake'
|
15
15
|
require 'rake/testtask'
|
16
|
+
require 'rcov/rcovtask'
|
17
|
+
require 'rake/rdoctask'
|
18
|
+
require 'yard'
|
19
|
+
|
20
|
+
task :default => :test
|
21
|
+
|
16
22
|
Rake::TestTask.new(:test) do |test|
|
17
23
|
test.libs << 'lib' << 'test' << 'test/fixtures'
|
18
|
-
test.pattern = 'test/**/*_test.rb
|
24
|
+
test.pattern = ENV['TEST'] || "test/**/*_test.rb"
|
19
25
|
test.verbose = true
|
20
26
|
end
|
21
27
|
|
22
|
-
require 'rcov/rcovtask'
|
23
28
|
Rcov::RcovTask.new do |test|
|
24
29
|
test.libs << 'test' << 'test/fixtures'
|
25
30
|
test.pattern = 'test/**/*_test.rb'
|
@@ -27,12 +32,8 @@ Rcov::RcovTask.new do |test|
|
|
27
32
|
test.rcov_opts << '--exclude "gems/*"'
|
28
33
|
end
|
29
34
|
|
30
|
-
task :default => :test
|
31
|
-
|
32
|
-
require 'rake/rdoctask'
|
33
35
|
Rake::RDocTask.new do |rdoc|
|
34
36
|
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
35
|
-
|
36
37
|
rdoc.rdoc_dir = 'rdoc'
|
37
38
|
rdoc.title = "tenacity #{version}"
|
38
39
|
rdoc.rdoc_files.include('README*')
|
@@ -40,6 +41,16 @@ Rake::RDocTask.new do |rdoc|
|
|
40
41
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
41
42
|
end
|
42
43
|
|
43
|
-
|
44
|
-
|
44
|
+
YARD::Rake::YardocTask.new do |t|
|
45
|
+
t.files = ['lib/**/*.rb', '-', 'EXTEND.rdoc']
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'Delete rcov, rdoc, yard, and other generated files'
|
49
|
+
task :clobber => [:clobber_rcov, :clobber_rdoc, :clobber_yard]
|
50
|
+
|
51
|
+
desc 'Delete yard generated files'
|
52
|
+
task :clobber_yard do
|
53
|
+
puts 'rm -rf doc .yardoc'
|
54
|
+
FileUtils.rm_rf ['doc', '.yardoc']
|
55
|
+
end
|
45
56
|
|
data/history.txt
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
== 0.3.0
|
2
|
+
|
3
|
+
* Major enhancements
|
4
|
+
|
5
|
+
* Added support for Mongoid
|
6
|
+
* Added support for DataMapper
|
7
|
+
* Added support for Sequel
|
8
|
+
|
9
|
+
* Minor enhancements
|
10
|
+
|
11
|
+
* Automatically save object when added to a t_has_many association, unless the
|
12
|
+
parent object is not yet saved itself.
|
13
|
+
* Added suport for destroy_all to the t_has_many association
|
14
|
+
* Added suport for delete_all to the t_has_many association
|
15
|
+
* Added support for push and concat to t_has_many association
|
16
|
+
|
17
|
+
* Bug fixes
|
18
|
+
|
19
|
+
* Found and fixed many minor bugs thanks to a new test suite that tests all
|
20
|
+
associations against all supported database clients.
|
21
|
+
|
1
22
|
== 0.2.0
|
2
23
|
|
3
24
|
* Major enhancements
|
data/lib/tenacity.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require File.join('active_support', 'inflector')
|
2
2
|
|
3
|
+
require File.join(File.dirname(__FILE__), 'tenacity', 'associates_proxy')
|
3
4
|
require File.join(File.dirname(__FILE__), 'tenacity', 'association')
|
4
5
|
require File.join(File.dirname(__FILE__), 'tenacity', 'class_methods')
|
5
6
|
require File.join(File.dirname(__FILE__), 'tenacity', 'instance_methods')
|
@@ -7,11 +8,11 @@ require File.join(File.dirname(__FILE__), 'tenacity', 'associations', 'belongs_t
|
|
7
8
|
require File.join(File.dirname(__FILE__), 'tenacity', 'associations', 'has_many')
|
8
9
|
require File.join(File.dirname(__FILE__), 'tenacity', 'associations', 'has_one')
|
9
10
|
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', 'activerecord')
|
10
|
-
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', 'couchrest'
|
11
|
-
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', '
|
12
|
-
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', 'couchrest', 'couchrest_extended_document')
|
13
|
-
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', 'couchrest', 'couchrest_model')
|
11
|
+
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', 'couchrest')
|
12
|
+
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', 'datamapper')
|
14
13
|
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', 'mongo_mapper')
|
14
|
+
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', 'mongoid')
|
15
|
+
require File.join(File.dirname(__FILE__), 'tenacity', 'orm_ext', 'sequel')
|
15
16
|
|
16
17
|
module Tenacity #:nodoc:
|
17
18
|
include InstanceMethods
|
@@ -21,6 +22,13 @@ module Tenacity #:nodoc:
|
|
21
22
|
include HasOne
|
22
23
|
|
23
24
|
def self.included(model)
|
25
|
+
ActiveRecord.setup(model)
|
26
|
+
CouchRest.setup(model)
|
27
|
+
DataMapper.setup(model)
|
28
|
+
MongoMapper.setup(model)
|
29
|
+
Mongoid.setup(model)
|
30
|
+
Sequel.setup(model)
|
31
|
+
|
24
32
|
raise "Tenacity does not support the database client used by #{model}" unless model.respond_to?(:_t_find)
|
25
33
|
model.extend(ClassMethods)
|
26
34
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Tenacity
|
2
|
+
class AssociatesProxy #:nodoc:
|
3
|
+
alias_method :proxy_respond_to?, :respond_to?
|
4
|
+
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ }
|
5
|
+
|
6
|
+
def initialize(parent, target, association)
|
7
|
+
@parent = parent
|
8
|
+
@target = target
|
9
|
+
@association = association
|
10
|
+
end
|
11
|
+
|
12
|
+
def respond_to?(*args)
|
13
|
+
proxy_respond_to?(*args) || @target.respond_to?(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Explicitly proxy === because the instance method removal above doesn't catch it.
|
17
|
+
def ===(other)
|
18
|
+
other === @target
|
19
|
+
end
|
20
|
+
|
21
|
+
def <<(object)
|
22
|
+
object.save unless @parent.id.nil?
|
23
|
+
@target << object
|
24
|
+
end
|
25
|
+
|
26
|
+
def push(*objects)
|
27
|
+
objects.each { |object| object.save } unless @parent.id.nil?
|
28
|
+
@target.push(*objects)
|
29
|
+
end
|
30
|
+
|
31
|
+
def concat(objects)
|
32
|
+
objects.each { |object| object.save } unless @parent.id.nil?
|
33
|
+
@target.concat(objects)
|
34
|
+
end
|
35
|
+
|
36
|
+
def destroy_all
|
37
|
+
ids = prepare_for_delete
|
38
|
+
@association.associate_class._t_delete(ids)
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete_all
|
42
|
+
ids = prepare_for_delete
|
43
|
+
@association.associate_class._t_delete(ids, false)
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect
|
47
|
+
@target.inspect
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def prepare_for_delete
|
53
|
+
ids = @parent._t_get_associate_ids(@association)
|
54
|
+
@parent._t_remove_associates(@association)
|
55
|
+
@parent.save
|
56
|
+
ids
|
57
|
+
end
|
58
|
+
|
59
|
+
def method_missing(method, *args)
|
60
|
+
if block_given?
|
61
|
+
@target.send(method, *args) { |*block_args| yield(*block_args) }
|
62
|
+
else
|
63
|
+
@target.send(method, *args)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/tenacity/association.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module Tenacity
|
2
|
+
|
3
|
+
# The Associaiton class represents a Tenacity association. Using this class,
|
4
|
+
# you can retrieve all sorts of information about the association, including
|
5
|
+
# it name, type, source, target class, etc.
|
2
6
|
class Association
|
7
|
+
|
3
8
|
# Type type of the association (<tt>:t_has_one</tt>, <tt>:t_has_many</tt>, or <tt>:t_belongs_to</tt>)
|
4
9
|
attr_reader :type
|
5
10
|
|
@@ -62,21 +67,29 @@ module Tenacity
|
|
62
67
|
|
63
68
|
# Get the name of the join table used by this association
|
64
69
|
def join_table
|
65
|
-
|
66
|
-
|
67
|
-
end
|
70
|
+
table_name = fetch_table_name
|
71
|
+
@join_table || (name.to_s < table_name ? "#{name}_#{table_name}" : "#{table_name}_#{name}")
|
68
72
|
end
|
69
73
|
|
70
74
|
# Get the name of the column in the join table that represents this object
|
71
75
|
def association_key
|
72
|
-
|
73
|
-
|
74
|
-
end
|
76
|
+
table_name = fetch_table_name
|
77
|
+
@association_key || table_name.singularize + '_id'
|
75
78
|
end
|
76
79
|
|
77
80
|
# Get the name of the column in the join table that represents the associated object
|
78
81
|
def association_foreign_key
|
79
82
|
@association_foreign_key || name.to_s.singularize + '_id'
|
80
83
|
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def fetch_table_name
|
88
|
+
if @source.respond_to?(:table_name)
|
89
|
+
@source.table_name.to_s
|
90
|
+
else
|
91
|
+
"#{ActiveSupport::Inflector.underscore(@source)}s"
|
92
|
+
end
|
93
|
+
end
|
81
94
|
end
|
82
95
|
end
|
@@ -1,6 +1,11 @@
|
|
1
1
|
module Tenacity
|
2
2
|
module HasMany #:nodoc:
|
3
3
|
|
4
|
+
def _t_remove_associates(association)
|
5
|
+
instance_variable_set _t_ivar_name(association), []
|
6
|
+
_t_clear_associates(association)
|
7
|
+
end
|
8
|
+
|
4
9
|
private
|
5
10
|
|
6
11
|
def has_many_associates(association)
|
@@ -39,6 +44,7 @@ module Tenacity
|
|
39
44
|
|
40
45
|
associates = (record.instance_variable_get record._t_ivar_name(association)) || []
|
41
46
|
associates.each do |associate|
|
47
|
+
associate._t_reload
|
42
48
|
associate.send("#{association.foreign_key(record.class)}=", record.id.to_s)
|
43
49
|
save_associate(associate)
|
44
50
|
end
|
@@ -7,6 +7,7 @@ module Tenacity
|
|
7
7
|
# methods.
|
8
8
|
#
|
9
9
|
# class Project
|
10
|
+
# include SupportedDatabaseClient
|
10
11
|
# include Tenacity
|
11
12
|
#
|
12
13
|
# t_belongs_to :portfolio
|
@@ -57,6 +58,47 @@ module Tenacity
|
|
57
58
|
# t_belongs_to :manager # foreign key - manager_id
|
58
59
|
# end
|
59
60
|
#
|
61
|
+
# == Is it a +t_belongs_to+ or +t_has_one+ association?
|
62
|
+
#
|
63
|
+
# Both express a 1-1 relationship. The difference is mostly where to place
|
64
|
+
# the foreign key, which is owned by the class declaring the +t_belongs_to+
|
65
|
+
# relationship. Example:
|
66
|
+
#
|
67
|
+
# class Employee < ActiveRecord::Base
|
68
|
+
# include Tenacity
|
69
|
+
# t_has_one :office
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
# class Office
|
73
|
+
# include MongoMapper::Document
|
74
|
+
# include Tenacity
|
75
|
+
# t_belongs_to :employee
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# In this example, the foreign key, <tt>employee_id</tt>, would belong to the
|
79
|
+
# Office class. If possible, tenacity will define the property to hold the
|
80
|
+
# foreign key. When it cannot, it assumes that the foreign key has been
|
81
|
+
# defined. See the documentation for the respective database client
|
82
|
+
# extension to see if tenacity will declare the foreign_key property.
|
83
|
+
#
|
84
|
+
# == Unsaved objects and associations
|
85
|
+
#
|
86
|
+
# You can manipulate objects and associations before they are saved to the database, but there is some special behavior you should be
|
87
|
+
# aware of, mostly involving the saving of associated objects.
|
88
|
+
#
|
89
|
+
# === One-to-one associations
|
90
|
+
#
|
91
|
+
# * Assigning an object to a +t_has_one+ association automatically saves that object and the object being replaced (if there is one), in
|
92
|
+
# order to update their primary keys - except if the parent object is not yet stored in the database.
|
93
|
+
# * Assigning an object to a +t_belongs_to+ association does not save the object, since the foreign key field belongs on the parent. It
|
94
|
+
# does not save the parent either.
|
95
|
+
#
|
96
|
+
# === Collections
|
97
|
+
#
|
98
|
+
# * Adding an object to a collection (+t_has_many+) automatically saves that object, except if the parent object
|
99
|
+
# (the owner of the collection) is not yet stored in the database.
|
100
|
+
# * All unsaved members of the collection are automatically saved when the parent is saved.
|
101
|
+
#
|
60
102
|
# == Caching
|
61
103
|
#
|
62
104
|
# All of the methods are built on a simple caching principle that will keep the result
|
@@ -218,9 +260,18 @@ module Tenacity
|
|
218
260
|
# An empty array is returned if none are found.
|
219
261
|
# [collection<<(object, ...)]
|
220
262
|
# Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
|
221
|
-
#
|
263
|
+
# [collection.push(object, ...)]
|
264
|
+
# Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
|
265
|
+
# [collection.concat(other_array)]
|
266
|
+
# Adds the objects in the other array to the collection by setting their foreign keys to the collection's primary key.
|
222
267
|
# [collection.delete(object, ...)]
|
223
268
|
# Removes one or more objects from the collection.
|
269
|
+
# [collection.destroy_all]
|
270
|
+
# Removes all objects from the collection, and deletes them from their respective
|
271
|
+
# database. If the deleted objects have any delete callbacks defined, they will be called.
|
272
|
+
# [collection.delete_all]
|
273
|
+
# Removes all objects from the collection, and deletes them from their respective
|
274
|
+
# database. No delete callbacks will be called, regardless of whether or not they are defined.
|
224
275
|
# [collection=objects]
|
225
276
|
# Replaces the collections content by setting it to the list of specified objects.
|
226
277
|
# [collection_singular_ids]
|
@@ -8,11 +8,11 @@ module Tenacity
|
|
8
8
|
private
|
9
9
|
|
10
10
|
def get_associate(association, params)
|
11
|
-
_t_reload
|
11
|
+
_t_reload unless id.nil?
|
12
12
|
force_reload = params.first unless params.empty?
|
13
|
-
value = instance_variable_get
|
13
|
+
value = create_proxy(instance_variable_get(_t_ivar_name(association)), association)
|
14
14
|
if value.nil? || force_reload
|
15
|
-
value = yield
|
15
|
+
value = create_proxy(yield, association)
|
16
16
|
instance_variable_set _t_ivar_name(association), value
|
17
17
|
end
|
18
18
|
value
|
@@ -23,5 +23,9 @@ module Tenacity
|
|
23
23
|
instance_variable_set _t_ivar_name(association), associate
|
24
24
|
end
|
25
25
|
|
26
|
+
def create_proxy(value, association)
|
27
|
+
value.respond_to?(:each) ? AssociatesProxy.new(self, value, association) : value
|
28
|
+
end
|
29
|
+
|
26
30
|
end
|
27
31
|
end
|
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'active_record'
|
3
|
-
|
1
|
+
module Tenacity
|
4
2
|
# Tenacity relationships on ActiveRecord objects require that certain columns
|
5
3
|
# exist on the associated table, and that join tables exist for one-to-many
|
6
4
|
# relationships. Take the following class for example:
|
@@ -43,33 +41,53 @@ begin
|
|
43
41
|
# end
|
44
42
|
#
|
45
43
|
module ActiveRecord
|
46
|
-
class Base #:nodoc:
|
47
44
|
|
48
|
-
|
45
|
+
def self.setup(model)
|
46
|
+
require 'active_record'
|
47
|
+
if model.ancestors.include?(::ActiveRecord::Base)
|
48
|
+
model.send :include, ActiveRecord::InstanceMethods
|
49
|
+
model.extend ActiveRecord::ClassMethods
|
50
|
+
end
|
51
|
+
rescue LoadError
|
52
|
+
# ActiveRecord not available
|
53
|
+
end
|
54
|
+
|
55
|
+
module ClassMethods #:nodoc:
|
56
|
+
def _t_find(id)
|
49
57
|
find_by_id(id)
|
50
58
|
end
|
51
59
|
|
52
|
-
def
|
60
|
+
def _t_find_bulk(ids)
|
53
61
|
return [] if ids.nil? || ids.empty?
|
54
62
|
find(:all, :conditions => ["id in (?)", ids])
|
55
63
|
end
|
56
64
|
|
57
|
-
def
|
65
|
+
def _t_find_first_by_associate(property, id)
|
58
66
|
find(:first, :conditions => ["#{property} = ?", id.to_s])
|
59
67
|
end
|
60
68
|
|
61
|
-
def
|
69
|
+
def _t_find_all_by_associate(property, id)
|
62
70
|
find(:all, :conditions => ["#{property} = ?", id.to_s])
|
63
71
|
end
|
64
72
|
|
65
|
-
def
|
73
|
+
def _t_initialize_has_many_association(association)
|
66
74
|
after_save { |record| record.class._t_save_associates(record, association) }
|
67
75
|
end
|
68
76
|
|
69
|
-
def
|
77
|
+
def _t_initialize_belongs_to_association(association)
|
70
78
|
before_save { |record| record.class._t_stringify_belongs_to_value(record, association) }
|
71
79
|
end
|
72
80
|
|
81
|
+
def _t_delete(ids, run_callbacks=true)
|
82
|
+
if run_callbacks
|
83
|
+
destroy_all(["id in (?)", ids])
|
84
|
+
else
|
85
|
+
delete_all(["id in (?)", ids])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
module InstanceMethods #:nodoc:
|
73
91
|
def _t_reload
|
74
92
|
reload
|
75
93
|
end
|
@@ -88,12 +106,11 @@ begin
|
|
88
106
|
end
|
89
107
|
|
90
108
|
def _t_get_associate_ids(association)
|
109
|
+
return [] if self.id.nil?
|
91
110
|
rows = self.connection.execute("select #{association.association_foreign_key} from #{association.join_table} where #{association.association_key} = #{self.id}")
|
92
111
|
ids = []; rows.each { |r| ids << r[0] }; ids
|
93
112
|
end
|
94
|
-
|
95
113
|
end
|
114
|
+
|
96
115
|
end
|
97
|
-
rescue LoadError
|
98
|
-
# ActiveRecord not available
|
99
116
|
end
|