datamapper 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/CHANGELOG +65 -0
  2. data/README +193 -1
  3. data/do_performance.rb +153 -0
  4. data/environment.rb +45 -0
  5. data/example.rb +119 -22
  6. data/lib/data_mapper.rb +36 -16
  7. data/lib/data_mapper/adapters/abstract_adapter.rb +8 -0
  8. data/lib/data_mapper/adapters/data_object_adapter.rb +360 -0
  9. data/lib/data_mapper/adapters/mysql_adapter.rb +30 -179
  10. data/lib/data_mapper/adapters/postgresql_adapter.rb +90 -199
  11. data/lib/data_mapper/adapters/sql/coersion.rb +32 -3
  12. data/lib/data_mapper/adapters/sql/commands/conditions.rb +97 -128
  13. data/lib/data_mapper/adapters/sql/commands/load_command.rb +234 -231
  14. data/lib/data_mapper/adapters/sql/commands/loader.rb +99 -0
  15. data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +30 -0
  16. data/lib/data_mapper/adapters/sql/mappings/column.rb +68 -6
  17. data/lib/data_mapper/adapters/sql/mappings/schema.rb +6 -3
  18. data/lib/data_mapper/adapters/sql/mappings/table.rb +71 -42
  19. data/lib/data_mapper/adapters/sql/quoting.rb +8 -2
  20. data/lib/data_mapper/adapters/sqlite3_adapter.rb +32 -201
  21. data/lib/data_mapper/associations.rb +21 -7
  22. data/lib/data_mapper/associations/belongs_to_association.rb +96 -80
  23. data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +158 -67
  24. data/lib/data_mapper/associations/has_many_association.rb +96 -78
  25. data/lib/data_mapper/associations/has_n_association.rb +64 -0
  26. data/lib/data_mapper/associations/has_one_association.rb +49 -79
  27. data/lib/data_mapper/associations/reference.rb +47 -0
  28. data/lib/data_mapper/base.rb +216 -50
  29. data/lib/data_mapper/callbacks.rb +71 -24
  30. data/lib/data_mapper/{session.rb → context.rb} +20 -8
  31. data/lib/data_mapper/database.rb +176 -45
  32. data/lib/data_mapper/embedded_value.rb +65 -0
  33. data/lib/data_mapper/identity_map.rb +12 -4
  34. data/lib/data_mapper/support/active_record_impersonation.rb +12 -8
  35. data/lib/data_mapper/support/enumerable.rb +8 -0
  36. data/lib/data_mapper/support/serialization.rb +13 -0
  37. data/lib/data_mapper/support/string.rb +1 -12
  38. data/lib/data_mapper/support/symbol.rb +3 -0
  39. data/lib/data_mapper/validations/unique_validator.rb +1 -2
  40. data/lib/data_mapper/validations/validation_helper.rb +18 -1
  41. data/performance.rb +109 -34
  42. data/plugins/can_has_sphinx/LICENSE +23 -0
  43. data/plugins/can_has_sphinx/README +4 -0
  44. data/plugins/can_has_sphinx/REVISION +1 -0
  45. data/plugins/can_has_sphinx/Rakefile +22 -0
  46. data/plugins/can_has_sphinx/init.rb +1 -0
  47. data/plugins/can_has_sphinx/install.rb +1 -0
  48. data/plugins/can_has_sphinx/lib/acts_as_sphinx.rb +123 -0
  49. data/plugins/can_has_sphinx/lib/sphinx.rb +460 -0
  50. data/plugins/can_has_sphinx/scripts/sphinx.sh +47 -0
  51. data/plugins/can_has_sphinx/tasks/acts_as_sphinx_tasks.rake +41 -0
  52. data/plugins/dataobjects/REVISION +1 -0
  53. data/plugins/dataobjects/Rakefile +7 -0
  54. data/plugins/dataobjects/do.rb +246 -0
  55. data/plugins/dataobjects/do_mysql.rb +179 -0
  56. data/plugins/dataobjects/do_postgres.rb +181 -0
  57. data/plugins/dataobjects/do_sqlite3.rb +153 -0
  58. data/plugins/dataobjects/spec/do_spec.rb +150 -0
  59. data/plugins/dataobjects/spec/spec_helper.rb +81 -0
  60. data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
  61. data/plugins/dataobjects/swig_mysql/extconf.rb +33 -0
  62. data/plugins/dataobjects/swig_mysql/mysql_c.c +18800 -0
  63. data/plugins/dataobjects/swig_mysql/mysql_c.i +8 -0
  64. data/plugins/dataobjects/swig_mysql/mysql_supp.i +46 -0
  65. data/plugins/dataobjects/swig_postgres/Makefile +146 -0
  66. data/plugins/dataobjects/swig_postgres/extconf.rb +29 -0
  67. data/plugins/dataobjects/swig_postgres/postgres_c.bundle +0 -0
  68. data/plugins/dataobjects/swig_postgres/postgres_c.c +8185 -0
  69. data/plugins/dataobjects/swig_postgres/postgres_c.i +73 -0
  70. data/plugins/dataobjects/swig_sqlite/db +0 -0
  71. data/plugins/dataobjects/swig_sqlite/extconf.rb +9 -0
  72. data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +4725 -0
  73. data/plugins/dataobjects/swig_sqlite/sqlite_c.i +168 -0
  74. data/rakefile.rb +45 -23
  75. data/spec/acts_as_tree_spec.rb +39 -0
  76. data/spec/associations_spec.rb +220 -0
  77. data/spec/attributes_spec.rb +15 -0
  78. data/spec/base_spec.rb +44 -0
  79. data/spec/callbacks_spec.rb +45 -0
  80. data/spec/can_has_sphinx.rb +6 -0
  81. data/spec/coersion_spec.rb +34 -0
  82. data/spec/conditions_spec.rb +49 -0
  83. data/spec/conversions_to_yaml_spec.rb +17 -0
  84. data/spec/count_command_spec.rb +11 -0
  85. data/spec/delete_command_spec.rb +1 -1
  86. data/spec/embedded_value_spec.rb +23 -0
  87. data/spec/fixtures/animals_exhibits.yaml +2 -0
  88. data/spec/fixtures/people.yaml +18 -1
  89. data/spec/{legacy.rb → legacy_spec.rb} +3 -3
  90. data/spec/load_command_spec.rb +157 -20
  91. data/spec/magic_columns_spec.rb +9 -0
  92. data/spec/mock_adapter.rb +20 -0
  93. data/spec/models/animal.rb +1 -1
  94. data/spec/models/animals_exhibit.rb +6 -0
  95. data/spec/models/exhibit.rb +2 -0
  96. data/spec/models/person.rb +26 -1
  97. data/spec/models/project.rb +19 -0
  98. data/spec/models/sales_person.rb +1 -0
  99. data/spec/models/section.rb +6 -0
  100. data/spec/models/zoo.rb +3 -1
  101. data/spec/query_spec.rb +9 -0
  102. data/spec/save_command_spec.rb +65 -1
  103. data/spec/schema_spec.rb +89 -0
  104. data/spec/single_table_inheritance_spec.rb +27 -0
  105. data/spec/spec_helper.rb +9 -55
  106. data/spec/{symbolic_operators.rb → symbolic_operators_spec.rb} +9 -5
  107. data/spec/{validates_confirmation_of.rb → validates_confirmation_of_spec.rb} +4 -3
  108. data/spec/{validates_format_of.rb → validates_format_of_spec.rb} +5 -4
  109. data/spec/{validates_length_of.rb → validates_length_of_spec.rb} +8 -7
  110. data/spec/{validates_uniqueness_of.rb → validates_uniqueness_of_spec.rb} +7 -10
  111. data/spec/{validations.rb → validations_spec.rb} +24 -6
  112. data/tasks/drivers.rb +20 -0
  113. data/tasks/fixtures.rb +42 -0
  114. metadata +181 -42
  115. data/lib/data_mapper/adapters/sql/commands/advanced_load_command.rb +0 -140
  116. data/lib/data_mapper/adapters/sql/commands/delete_command.rb +0 -113
  117. data/lib/data_mapper/adapters/sql/commands/save_command.rb +0 -141
  118. data/lib/data_mapper/adapters/sql/commands/table_exists_command.rb +0 -33
  119. data/lib/data_mapper/adapters/sql_adapter.rb +0 -163
  120. data/lib/data_mapper/associations/advanced_has_many_association.rb +0 -55
  121. data/lib/data_mapper/support/blank_slate.rb +0 -3
  122. data/lib/data_mapper/support/proc.rb +0 -69
  123. data/lib/data_mapper/support/struct.rb +0 -26
  124. data/lib/data_mapper/unit_of_work.rb +0 -38
  125. data/spec/basic_finder.rb +0 -67
  126. data/spec/belongs_to.rb +0 -47
  127. data/spec/has_and_belongs_to_many.rb +0 -25
  128. data/spec/has_many.rb +0 -34
  129. data/spec/new_record.rb +0 -24
  130. data/spec/sub_select.rb +0 -16
  131. data/spec/support/string_spec.rb +0 -7
@@ -1,16 +1,62 @@
1
1
  module DataMapper
2
2
 
3
+ # CallbacksHelper adds a class-method ClassMethods#callbacks
4
+ # when included in a class, and defines short-cut class-methods to
5
+ # add delegates to callbacks for the built-in Callbacks::EVENTS.
6
+ module CallbacksHelper
7
+
8
+ # The ::included callback extends the included class with a
9
+ # ::callbacks method, and sets up helper methods for the standard
10
+ # events declared in Callbacks::EVENTS.
11
+ def self.included(base)
12
+ base.extend(ClassMethods)
13
+
14
+ # Declare helpers for the standard EVENTS
15
+ Callbacks::EVENTS.each do |name|
16
+ base.class_eval <<-EOS
17
+ def self.#{name}(string = nil, &block)
18
+ if string.nil?
19
+ callbacks.add(:#{name}, block)
20
+ else
21
+ callbacks.add(:#{name}, string)
22
+ end
23
+ end
24
+ EOS
25
+ end
26
+ end
27
+
28
+ # Defines class-methods for the class that CallbacksHelper is
29
+ # included in.
30
+ module ClassMethods
31
+
32
+ # Provides lazily initialized access to a Callbacks instance.
33
+ def callbacks
34
+ @callbacks || ( @callbacks = DataMapper::Callbacks.new )
35
+ end
36
+ end
37
+ end
38
+
39
+ # Callbacks is a collection to assign and execute blocks of code when
40
+ # hooks throughout the DataMapper call Callbacks#execute. A set of the
41
+ # standard callbacks is declared in the Callbacks::EVENTS array.
3
42
  class Callbacks
4
43
 
44
+ # These are a collection of default callbacks that are hooked
45
+ # into the DataMapper. You're free to add your own events just by
46
+ # calling #add, but you'll have add the appropriate hooks into the
47
+ # system to actually execute them yourself.
5
48
  EVENTS = [
6
49
  :before_materialize, :after_materialize,
7
50
  :before_save, :after_save,
8
51
  :before_create, :after_create,
9
52
  :before_update, :after_update,
10
53
  :before_destroy, :after_destroy,
11
- :before_validate, :after_validate
54
+ :before_validation, :after_validation
12
55
  ]
13
-
56
+
57
+ # Initializes an internal Hash that ensures callback names are always
58
+ # of type Symbol, and assigns an Array to store your delegating code
59
+ # when the callback is looked-up by name.
14
60
  def initialize
15
61
  @callbacks = Hash.new do |h,k|
16
62
  raise 'Callback names must be Symbols' unless k.kind_of?(Symbol)
@@ -18,32 +64,33 @@ module DataMapper
18
64
  end
19
65
  end
20
66
 
21
- alias ruby_method_missing method_missing
22
- def method_missing(sym, *args)
23
- if EVENTS.include?(sym)
24
- self.class.send(:define_method, sym) { @callbacks[sym] }
25
- return send(sym)
26
- elsif sym.to_s =~ /^execute_(\w+)/ && EVENTS.include?($1.to_sym)
27
- return execute(args.first, $1.to_sym)
28
- end
29
-
30
- super
31
- end
32
-
33
- def execute(name, instance)
34
- @callbacks[name].each do |callback|
35
- if callback.kind_of?(String)
36
- instance.instance_eval(callback)
37
- else
38
- instance.instance_eval(&callback)
67
+ # Executes a given callback and returns TRUE or FALSE depending on the
68
+ # return value of the callbacks. All callbacks must return successfully
69
+ # in order for the call to #execute to return TRUE. Callbacks always
70
+ # execute against an +instance+. You may pass additional arguments
71
+ # which will in turn be passed to any Proc objects assigned to a specific
72
+ # callback. Strings assigned to callbacks do not accept parameters.
73
+ # They are instance-eval'ed instead. When the callback is a Symbol,
74
+ # it is sent to the instance under the assumption it is a method call.
75
+ def execute(name, instance, *args)
76
+ @callbacks[name].all? do |callback|
77
+ case callback
78
+ when String then instance.instance_eval(callback)
79
+ when Proc then callback[instance, *args]
80
+ when Symbol then instance.send(callback, *args)
81
+ else raise ''
39
82
  end
40
83
  end
41
84
  end
42
85
 
43
- def add(name, string = nil, &block)
44
- callback = send(name)
45
- raise ArgumentError.new("You didn't specify a callback in either string or block form.") if string.nil? && block.nil?
46
- callback << (string.nil? ? block : string)
86
+ # Asign delegating code to a callback. The +block+ parameter
87
+ # can be a Proc object, a String which will be eval'ed when
88
+ # the callback is executed, or a Symbol, which will be sent to
89
+ # the instance executed against (as a method call).
90
+ def add(name, block)
91
+ callback = @callbacks[name]
92
+ raise ArgumentError.new("You didn't specify a callback in String, Symbol or Proc form.") if block.nil?
93
+ callback << block
47
94
  end
48
95
  end
49
96
 
@@ -2,7 +2,7 @@ require 'data_mapper/identity_map'
2
2
 
3
3
  module DataMapper
4
4
 
5
- class Session
5
+ class Context
6
6
 
7
7
  class MaterializationError < StandardError
8
8
  end
@@ -17,7 +17,7 @@ module DataMapper
17
17
  @identity_map || ( @identity_map = IdentityMap.new )
18
18
  end
19
19
 
20
- def first(klass, *args, &b)
20
+ def first(klass, *args)
21
21
  id = nil
22
22
  options = nil
23
23
 
@@ -44,32 +44,40 @@ module DataMapper
44
44
  @adapter.load(self, klass, options)
45
45
  end
46
46
 
47
+ def count(klass, options = {})
48
+ @adapter.count(klass, options)
49
+ end
50
+
47
51
  def save(instance)
48
52
  @adapter.save(self, instance)
49
53
  end
50
54
 
51
55
  def destroy(instance)
52
- @adapter.delete(instance, :session => self)
56
+ @adapter.delete(self, instance)
53
57
  end
54
58
 
55
59
  def delete_all(klass)
56
- @adapter.delete(klass, :session => self)
60
+ @adapter.delete(self, klass)
57
61
  end
58
62
 
59
63
  def truncate(klass)
60
- @adapter.delete(klass, :truncate => true, :session => self)
64
+ @adapter.truncate(self, klass)
61
65
  end
62
66
 
63
67
  def create_table(klass)
64
- @adapter[klass].create!
68
+ @adapter.create_table(klass)
65
69
  end
66
70
 
67
71
  def drop_table(klass)
68
- @adapter[klass].drop!
72
+ @adapter.drop(self, klass)
69
73
  end
70
74
 
71
75
  def table_exists?(klass)
72
- @adapter[klass].exists?
76
+ @adapter.table_exists?(klass)
77
+ end
78
+
79
+ def execute(*args)
80
+ @adapter.execute(*args)
73
81
  end
74
82
 
75
83
  def query(*args)
@@ -80,6 +88,10 @@ module DataMapper
80
88
  @adapter.schema
81
89
  end
82
90
 
91
+ def table(klass)
92
+ @adapter.table(klass)
93
+ end
94
+
83
95
  def log
84
96
  @adapter.log
85
97
  end
@@ -1,5 +1,6 @@
1
1
  require 'logger'
2
- require 'data_mapper/session'
2
+ require 'data_mapper/context'
3
+ require 'data_mapper/adapters/abstract_adapter'
3
4
 
4
5
  # Delegates to DataMapper::database.
5
6
  # Will not overwrite if a method of the same name is pre-defined.
@@ -9,17 +10,24 @@ end unless methods.include?(:database)
9
10
 
10
11
  module DataMapper
11
12
 
12
- # Block Syntax:
13
- # Pushes the named database onto the context-stack,
14
- # yields a new session, and pops the context-stack.
15
- # Non-Block Syntax:
16
- # Returns the current session, or if there is none,
17
- # a new Session.
18
- def self.database(name = :default)
13
+ # ===Block Syntax:
14
+ # Pushes the named database onto the context-stack,
15
+ # yields a new session, and pops the context-stack.
16
+ #
17
+ # results = DataMapper.database(:second_database) do |current_context|
18
+ # ...
19
+ # end
20
+ #
21
+ # ===Non-Block Syntax:
22
+ # Returns the current session, or if there is none,
23
+ # a new Session.
24
+ #
25
+ # current_database = DataMapper.database
26
+ def self.database(name = :default) # :yields: current_context
19
27
  unless block_given?
20
- Database.context.last || Session.new(Database[name].adapter)
28
+ Database.context.last || Context.new(Database[name].adapter)
21
29
  else
22
- Database.context.push(Session.new(Database[name].adapter))
30
+ Database.context.push(Context.new(Database[name].adapter))
23
31
  result = yield(Database.context.last)
24
32
  Database.context.pop
25
33
  result
@@ -30,70 +38,193 @@ module DataMapper
30
38
  attr_accessor :options
31
39
  end
32
40
 
41
+ # The Database class allows us to setup a default database for use throughout our applications
42
+ # or allows us to setup a collection of databases to use.
43
+ #
44
+ # === Example
45
+ # ==== To setup a default database
46
+ # DataMapper::Database.setup({
47
+ # :adapter => 'mysql'
48
+ # :host => 'localhost'
49
+ # :username => 'root'
50
+ # :password => 'R00tPaswooooord'
51
+ # :database => 'selecta_development'
52
+ # })
53
+ #
54
+ # ==== To setup a named database
55
+ # DataMapper::Database.setup(:second_database, {
56
+ # :adapter => 'postgresql'
57
+ # :host => 'localhost'
58
+ # :username => 'second_user'
59
+ # :password => 'second_password'
60
+ # :database => 'second_database'
61
+ # })
62
+ #
63
+ #
64
+ # ==== Working with multiple databases (see #DataMapper::database)
65
+ # DataMapper.database(:second_database) do
66
+ # ...
67
+ # end
68
+ #
69
+ # DataMapper.database(:default) do
70
+ # ...
71
+ # end
72
+ #
73
+ # or even...
74
+ #
75
+ # #The below variables still hold on to their database sessions.
76
+ # #So no confusion happens when passing variables around scopes.
77
+ #
78
+ # DataMapper.database(:second_database) do
79
+ #
80
+ # animal = Animal.first
81
+ #
82
+ # DataMapper.database(:default) do
83
+ # Animal.new(animal).save
84
+ # end # :default database
85
+ #
86
+ # end # :second_database
33
87
  class Database
34
88
 
35
89
  @databases = {}
36
90
  @context = []
37
91
 
92
+ # Allows you to access any of the named databases you have already setup.
93
+ #
94
+ # default_db = DataMapper::Database[:default]
95
+ # second_db = DataMapper::Database[:second_database]
38
96
  def self.[](name)
39
97
  @databases[name]
40
98
  end
41
99
 
100
+ # Returns the array of Database sessions currently being used
101
+ #
102
+ # This is what gives us thread safety, boys and girls
42
103
  def self.context
43
104
  @context
44
105
  end
45
106
 
46
- def self.setup(name = :default, &initializer)
107
+ # Setup creates a database and sets all of your properties for that database.
108
+ # Setup looks for either a hash of options passed in to the database or a symbolized name
109
+ # for your database, as well as it's hash of parameters
110
+ #
111
+ # If no options are passed, an ArgumentException will be raised.
112
+ #
113
+ # DataMapper::Database.setup(name = :default, options_hash)
114
+ #
115
+ # DataMapper::Database.setup({
116
+ # :adapter => 'mysql'
117
+ # :host => 'localhost'
118
+ # :username => 'root'
119
+ # :password => 'R00tPaswooooord'
120
+ # :database => 'selecta_development'
121
+ # })
122
+ #
123
+ #
124
+ # DataMapper::Database.setup(:named_database, {
125
+ # :adapter => 'mysql'
126
+ # :host => 'localhost'
127
+ # :username => 'root'
128
+ # :password => 'R00tPaswooooord'
129
+ # :database => 'selecta_development'
130
+ # })
131
+
132
+ def self.setup(*args)
133
+
134
+ name, options = nil
135
+
136
+ if (args.nil?) || (args[1].nil? && args[0].class != Hash)
137
+ raise ArgumentError.new('Database cannot be setup without at least an options hash.')
138
+ end
139
+
140
+ if args.size == 1
141
+ name, options = :default, args[0]
142
+ elsif args.size == 2
143
+ name, options = args[0], args[1]
144
+ end
145
+
47
146
  current = self.new(name)
48
- current.instance_eval(&initializer)
147
+
148
+ current.single_threaded = false if options[:single_threaded] == false
149
+
150
+ options.each_pair do |k,v|
151
+ current.send("#{k}=", v)
152
+ end
153
+
49
154
  @databases[name] = current
50
155
  end
51
156
 
157
+ # Creates a new database object with the name you specify, and a default set of options.
158
+ #
159
+ # The default options are as follows:
160
+ # {:single_threaded => true, :host => 'localhost', :database => nil, :username => 'root', :password => '', :adapter = nil }
52
161
  def initialize(name)
53
162
  @name = name
54
- end
55
-
56
- attr_reader :name
57
-
58
- def adapter(value = nil)
59
- return @adapter if value.nil?
60
-
61
- raise ArgumentError.new('The adapter is readonly after being set') unless @adapter.nil?
62
163
 
63
- require "data_mapper/adapters/#{String::memoized_underscore(value)}_adapter"
64
- adapter_class = Adapters::const_get(Inflector.classify(value) + "Adapter")
164
+ @single_threaded = true
165
+ @adapter = nil
166
+ @host = 'localhost'
167
+ @database = nil
168
+ @schema_search_path = nil
169
+ @username = 'root'
170
+ @password = ''
171
+ @index_path = (Dir::pwd + "/indexes")
65
172
 
66
- @adapter = adapter_class.new(self)
173
+ @log_level = Logger::WARN
174
+ @log_stream = nil
67
175
  end
68
176
 
69
- def host(value = nil); value.nil? ? (@host || 'localhost') : @host = value end
70
- def database(value = nil); value.nil? ? @database : @database = value end
71
- def username(value = nil); value.nil? ? @username : @username = value end
72
- def password(value = nil); value.nil? ? (@password || '') : @password = value end
177
+ attr_reader :name, :adapter
178
+ attr_writer :single_threaded
179
+ attr_accessor :host, :database, :schema_search_path, :username, :password, :log_stream, :log_level, :index_path, :socket
73
180
 
74
- # single_threaded mode is disabled by default currently since it's buggy.
75
- def single_threaded(value = nil); value.nil? ? (@single_threaded.nil? ? @single_threaded = false : @single_threaded) : @single_threaded = value end
181
+ # Returns true or false
182
+ #
183
+ # NOTE: single_threaded is true unless explicitly set to false.
184
+ def single_threaded?
185
+ @single_threaded
186
+ end
76
187
 
77
- def log(value = nil)
78
- @log = value unless value.nil?
79
-
80
- if @log.nil?
81
- @log = log_stream.nil? ? Logger.new(nil) : Logger.new(log_stream, File::WRONLY | File::APPEND | File::CREAT)
82
- @log.level = log_level || Logger::WARN
83
- at_exit { @log.close }
188
+ # Allows us to set the adapter for this database object. It can only be set once, and expects two types of values.
189
+ #
190
+ # You may pass in either a class inheriting from DataMapper::Adapters::AbstractAdapter
191
+ # or pass in a string indicating the type of adapter you would like to use.
192
+ #
193
+ # To create your own adapters, create a file in data_mapper/adapters/new_adapter.rb that inherits from AbstractAdapter
194
+ #
195
+ # database.adapter=("postgresql")
196
+ def adapter=(value)
197
+ if @adapter
198
+ raise ArgumentError.new('The adapter is readonly after being set')
84
199
  end
85
200
 
86
- @log
87
- end
88
-
89
- def log_level(value = nil)
90
- return @log_level if value.nil?
91
- @log_level = value
201
+ if value.is_a?(DataMapper::Adapters::AbstractAdapter)
202
+ @adapter = value
203
+ elsif value.is_a?(Class)
204
+ @adapter = value.new(self)
205
+ else
206
+ begin
207
+ require "data_mapper/adapters/#{Inflector.underscore(value)}_adapter"
208
+ rescue LoadError
209
+ require "#{Inflector.underscore(value)}_adapter"
210
+ end
211
+ adapter_class = Adapters::const_get(Inflector.classify(value) + "Adapter")
212
+
213
+ @adapter = adapter_class.new(self)
214
+ end
92
215
  end
93
216
 
94
- def log_stream(value = nil)
95
- return @log_stream if value.nil?
96
- @log_stream = value
217
+ # Default Logger from Ruby's logger.rb
218
+ def log
219
+ @log = Logger.new(@log_stream, File::WRONLY | File::APPEND | File::CREAT)
220
+ @log.level = @log_level
221
+ at_exit { @log.close }
222
+
223
+ class << self
224
+ attr_reader :log
225
+ end
226
+
227
+ return @log
97
228
  end
98
229
 
99
230
  end