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,55 +0,0 @@
1
- module DataMapper
2
- module Associations
3
-
4
- class AdvancedHasManyAssociation
5
- include Enumerable
6
-
7
- def initialize(klass, association_name, options)
8
- @association_name = association_name.to_sym
9
- @options = options
10
-
11
- # Define the association instance method (i.e. Project#tasks)
12
- klass.class_eval <<-EOS
13
- def #{association_name}
14
- @#{association_name} || (@#{association_name} = HasManyAssociation.new(self, "#{association_name}", #{options.inspect}))
15
- end
16
- EOS
17
- end
18
-
19
- def name
20
- @association_name
21
- end
22
-
23
- def constant
24
- @associated_class || @associated_class = if @options.has_key?(:class) || @options.has_key?(:class_name)
25
- associated_class_name = (@options[:class] || @options[:class_name])
26
- if associated_class_name.kind_of?(String)
27
- Kernel.const_get(Inflector.classify(associated_class_name))
28
- else
29
- associated_class_name
30
- end
31
- else
32
- Kernel.const_get(Inflector.classify(association_name))
33
- end
34
- end
35
-
36
- def foreign_key
37
- @foreign_key || (@foreign_key = (@options[:foreign_key] || @instance.session.schema[@instance.class].default_foreign_key))
38
- end
39
-
40
- end
41
-
42
- module AdvancedHasMany
43
- def self.included(base)
44
- base.extend(ClassMethods)
45
- end
46
-
47
- module ClassMethods
48
- def advanced_has_many(association_name, options = {})
49
- database.schema[self].associations << AdvancedHasManyAssociation.new(self, association_name, options)
50
- end
51
- end
52
- end
53
-
54
- end
55
- end
@@ -1,3 +0,0 @@
1
- class BlankSlate #:nodoc:
2
- instance_methods.each { |m| undef_method m unless m =~ /^(__|instance_eval)/ }
3
- end
@@ -1,69 +0,0 @@
1
- require File.dirname(__FILE__) + '/blank_slate'
2
-
3
- class Proc
4
-
5
- # Yeah, all this is kinda the suck.
6
- def to_hash
7
- Conditions.new(&self).__to_hash__
8
- end
9
-
10
- class Conditions < BlankSlate
11
-
12
- def initialize(&block)
13
- @block = block
14
- @conditions = []
15
- end
16
-
17
- def method_missing(sym, *args)
18
- attribute = Attribute.new(sym)
19
- @conditions << attribute
20
- attribute
21
- end
22
-
23
- def __to_hash__
24
- instance_eval(&@block)
25
- @conditions.inject({}) do |h,attribute|
26
- h[attribute.__operator__] = *attribute.__args__; h
27
- end
28
- end
29
-
30
- class Attribute < BlankSlate
31
-
32
- def initialize(message)
33
- @message = message
34
- @args = nil
35
- @operator = nil
36
- end
37
-
38
- def method_missing(sym, *args)
39
- op = case sym
40
- when :==, :===, :in then :eql
41
- when :=~ then :like
42
- when :"<=>" then :not
43
- when :< then :lt
44
- when :<= then :lte
45
- when :> then :gt
46
- when :>= then :gte
47
- else sym
48
- end
49
-
50
- @operator = Symbol::Operator.new(@message, op)
51
- @args = args
52
- end
53
-
54
- def __operator__
55
- @operator
56
- end
57
-
58
- def __args__
59
- @args
60
- end
61
-
62
- def __message__
63
- @message
64
- end
65
-
66
- end
67
-
68
- end
69
- end
@@ -1,26 +0,0 @@
1
- module DataMapper
2
- module Support
3
- class Struct
4
-
5
- def self.define(raw_fields)
6
-
7
- normalized_fields = raw_fields.map { |field| Inflector.underscore(field).to_sym }
8
-
9
- Class.new(self) do
10
- define_method(:fields) do
11
- normalized_fields
12
- end
13
- end
14
- end
15
-
16
- def initialize(values)
17
- @values = values
18
- end
19
-
20
- def method_missing(sym, *args)
21
- @values[fields.index(sym)]
22
- end
23
-
24
- end # class Struct
25
- end # module Support
26
- end # module DataMapper
@@ -1,38 +0,0 @@
1
- module DataMapper
2
-
3
- # Should this track relations?
4
- module UnitOfWork
5
-
6
- def new_record?
7
- @new_record.nil? || @new_record
8
- end
9
-
10
- def dirty?(name = nil)
11
- if name.nil?
12
- session.schema[self.class].columns.any? { |column| self.instance_variable_get(column.instance_variable_name).hash != original_hashes[column.name] }
13
- else
14
- key = name.kind_of?(Symbol) ? name : name.to_sym
15
- self.instance_variable_get("@#{name}").hash != original_hashes[key]
16
- end
17
- end
18
-
19
- def dirty_attributes
20
- if new_record?
21
- session.schema[self.class].columns.reject do |column|
22
- instance_variable_get(column.instance_variable_name).nil?
23
- end
24
- else
25
- session.schema[self.class].columns.select do |column|
26
- column.name != :id && instance_variable_get(column.instance_variable_name).hash != original_hashes[column.name]
27
- end
28
- end.inject({}) do |fields, column|
29
- fields[column.name] = instance_variable_get(column.instance_variable_name); fields
30
- end
31
- end
32
-
33
- def original_hashes
34
- @original_hashes || (@original_hashes = {})
35
- end
36
- end
37
-
38
- end
data/spec/basic_finder.rb DELETED
@@ -1,67 +0,0 @@
1
- context 'Finder' do
2
-
3
- specify 'database-specific load should not fail' do
4
-
5
- DataMapper::database do |db|
6
- froggy = db.first(Animal, :conditions => ['name = ?', 'Frog'])
7
- froggy.name.should == 'Frog'
8
- end
9
-
10
- end
11
-
12
- specify 'current-database load should not fail' do
13
- froggy = DataMapper::database.first(Animal).name.should == 'Frog'
14
- end
15
-
16
- specify 'load through ActiveRecord impersonation should not fail' do
17
- Animal.find(:all).size.should == 16
18
- end
19
-
20
- specify 'load through Og impersonation should not fail' do
21
- Animal.all.size.should == 16
22
- end
23
-
24
- specify ':conditions option should accept a hash' do
25
- Animal.all(:conditions => { :name => 'Frog' }).size.should == 1
26
- end
27
-
28
- specify 'non-standard options should be considered part of the conditions' do
29
- database.log.debug('non-standard options should be considered part of the conditions')
30
- zebra = Animal.first(:name => 'Zebra')
31
- zebra.name.should == 'Zebra'
32
-
33
- elephant = Animal[:name => 'Elephant']
34
- elephant.name.should == 'Elephant'
35
-
36
- aged = Person.all(:age => 29)
37
- aged.size.should == 2
38
- aged.first.name.should == 'Sam'
39
- aged.last.name.should == 'Bob'
40
-
41
- fixtures(:animals)
42
- end
43
-
44
- specify 'should not find deleted objects' do
45
- database do
46
- wally = Animal[:name => 'Whale']
47
- wally.destroy!.should == true
48
-
49
- wallys_evil_twin = Animal[:name => 'Whale']
50
- wallys_evil_twin.should == nil
51
-
52
- wally.new_record?.should == true
53
- wally.save
54
-
55
- Animal[:name => 'Whale'].should == wally
56
- end
57
- end
58
-
59
- specify 'lazy-loads should issue for whole sets' do
60
- people = Person.all
61
-
62
- people.each do |person|
63
- person.notes
64
- end
65
- end
66
-
67
- end
data/spec/belongs_to.rb DELETED
@@ -1,47 +0,0 @@
1
- context 'An Exhibit' do
2
-
3
- setup do
4
- @aviary = Exhibit[:name => 'Monkey Mayhem']
5
- end
6
-
7
- specify 'has a zoo association' do
8
- @aviary.zoo.class.should == Zoo
9
- Exhibit.new.zoo.should == nil
10
- end
11
-
12
- specify 'belongs to a zoo' do
13
- database do |db|
14
- @aviary.zoo.should == @aviary.session.first(Zoo, :name => 'San Diego')
15
- end
16
- end
17
-
18
- specify 'can build its zoo' do
19
- database do |db|
20
- e = Exhibit.new({:name => 'Super Extra Crazy Monkey Cage'})
21
- e.zoo.should == nil
22
- e.build_zoo({:name => 'Monkey Zoo'})
23
- e.zoo.class == Zoo
24
- e.zoo.new_record?.should == true
25
-
26
- # Need to get associations working properly before this works ....
27
- e.save
28
- end
29
- end
30
-
31
- specify 'can build its zoo' do
32
- database do |db|
33
- e = Exhibit.new({:name => 'Super Extra Crazy Monkey Cage'})
34
- e.zoo.should == nil
35
- e.create_zoo({:name => 'Monkey Zoo'})
36
- e.zoo.class == Zoo
37
- e.zoo.new_record?.should == false
38
- e.save
39
- end
40
- end
41
-
42
- teardown do
43
- fixtures('zoos')
44
- fixtures('exhibits')
45
- end
46
-
47
- end
@@ -1,25 +0,0 @@
1
- # context 'An Exhibit' do
2
- #
3
- # setup do
4
- # @amazonia = Exhibit[:name => 'Amazonia']
5
- # end
6
- #
7
- # specify 'has an animals association' do
8
- # [@amazonia, Exhibit.new].each do |exhibit|
9
- # exhibit.animals.class.should == DataMapper::Associations::HasAndBelongsToManyAssociation
10
- # end
11
- # end
12
- #
13
- # specify 'has many animals' do
14
- # @amazonia.animals.size.should == 2
15
- # end
16
- #
17
- # specify 'should load associations magically' do
18
- # Exhibit.all.each do |exhibit|
19
- # exhibit.animals.each do |animal|
20
- # animal.exhibits.should.include?(exhibit)
21
- # end
22
- # end
23
- # end
24
- #
25
- # end
data/spec/has_many.rb DELETED
@@ -1,34 +0,0 @@
1
- describe DataMapper::Associations::HasManyAssociation do
2
-
3
- before(:all) do
4
- fixtures(:zoos)
5
- fixtures(:exhibits)
6
-
7
- @san_diego = Zoo[:name => 'San Diego']
8
- @dallas = Zoo[:name => 'Dallas']
9
- @miami = Zoo[:name => 'Miami']
10
- end
11
-
12
- it 'should expose a proxy for the accessor' do
13
- [@miami, Zoo.new].each do |z|
14
- z.exhibits.class.should == DataMapper::Associations::HasManyAssociation
15
- end
16
- end
17
-
18
- it 'should lazily-load the association when Enumerable methods are called' do
19
- database do |db|
20
- @san_diego.exhibits.size.should == 2
21
- @san_diego.exhibits.should include(@san_diego.session.first(Exhibit, :name => 'Monkey Mayhem'))
22
- end
23
- end
24
-
25
- it 'should eager-load associations for an entire set' do
26
- zoos = Zoo.all
27
- zoos.each do |zoo|
28
- zoo.exhibits.each do |exhibit|
29
- exhibit.zoo.should == zoo
30
- end
31
- end
32
- end
33
-
34
- end
data/spec/new_record.rb DELETED
@@ -1,24 +0,0 @@
1
- context 'A new record' do
2
-
3
- setup do
4
- @bob = Person.new(:name => 'Bob', :age => 30, :occupation => 'Sales')
5
- end
6
-
7
- specify 'should be dirty' do
8
- @bob.dirty?.should == true
9
- end
10
-
11
- specify 'set attributes should be dirty' do
12
- attributes = @bob.attributes.dup.reject { |k,v| k == :id }
13
- @bob.dirty_attributes.should == { :name => 'Bob', :age => 30, :occupation => 'Sales' }
14
- end
15
-
16
- specify 'should be marked as new' do
17
- @bob.new_record?.should == true
18
- end
19
-
20
- specify 'should have a nil id' do
21
- @bob.id.should == nil
22
- end
23
-
24
- end
data/spec/sub_select.rb DELETED
@@ -1,16 +0,0 @@
1
- =begin
2
- context 'Sub-selection' do
3
-
4
- specify 'should return a Cup' do
5
- Animal[:id.select => { :name => 'cup' }].name.should == 'Cup'
6
- end
7
-
8
- specify 'should return all exhibits for Galveston zoo' do
9
- Exhibit.all(:zoo_id.select(Zoo) => { :name => 'Galveston' }).size.should == 3
10
- end
11
-
12
- specify 'should allow a sub-select in the select-list' do
13
- Animal[:select => [ :id.count ]]
14
- end
15
- end
16
- =end
@@ -1,7 +0,0 @@
1
- describe DataMapper::Support::String do
2
-
3
- it 'should underscore camel-cased words' do
4
- String::memoized_underscore('DataMapper').should == 'data_mapper'
5
- end
6
-
7
- end