datamapper 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +65 -0
- data/README +193 -1
- data/do_performance.rb +153 -0
- data/environment.rb +45 -0
- data/example.rb +119 -22
- data/lib/data_mapper.rb +36 -16
- data/lib/data_mapper/adapters/abstract_adapter.rb +8 -0
- data/lib/data_mapper/adapters/data_object_adapter.rb +360 -0
- data/lib/data_mapper/adapters/mysql_adapter.rb +30 -179
- data/lib/data_mapper/adapters/postgresql_adapter.rb +90 -199
- data/lib/data_mapper/adapters/sql/coersion.rb +32 -3
- data/lib/data_mapper/adapters/sql/commands/conditions.rb +97 -128
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +234 -231
- data/lib/data_mapper/adapters/sql/commands/loader.rb +99 -0
- data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +30 -0
- data/lib/data_mapper/adapters/sql/mappings/column.rb +68 -6
- data/lib/data_mapper/adapters/sql/mappings/schema.rb +6 -3
- data/lib/data_mapper/adapters/sql/mappings/table.rb +71 -42
- data/lib/data_mapper/adapters/sql/quoting.rb +8 -2
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +32 -201
- data/lib/data_mapper/associations.rb +21 -7
- data/lib/data_mapper/associations/belongs_to_association.rb +96 -80
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +158 -67
- data/lib/data_mapper/associations/has_many_association.rb +96 -78
- data/lib/data_mapper/associations/has_n_association.rb +64 -0
- data/lib/data_mapper/associations/has_one_association.rb +49 -79
- data/lib/data_mapper/associations/reference.rb +47 -0
- data/lib/data_mapper/base.rb +216 -50
- data/lib/data_mapper/callbacks.rb +71 -24
- data/lib/data_mapper/{session.rb → context.rb} +20 -8
- data/lib/data_mapper/database.rb +176 -45
- data/lib/data_mapper/embedded_value.rb +65 -0
- data/lib/data_mapper/identity_map.rb +12 -4
- data/lib/data_mapper/support/active_record_impersonation.rb +12 -8
- data/lib/data_mapper/support/enumerable.rb +8 -0
- data/lib/data_mapper/support/serialization.rb +13 -0
- data/lib/data_mapper/support/string.rb +1 -12
- data/lib/data_mapper/support/symbol.rb +3 -0
- data/lib/data_mapper/validations/unique_validator.rb +1 -2
- data/lib/data_mapper/validations/validation_helper.rb +18 -1
- data/performance.rb +109 -34
- data/plugins/can_has_sphinx/LICENSE +23 -0
- data/plugins/can_has_sphinx/README +4 -0
- data/plugins/can_has_sphinx/REVISION +1 -0
- data/plugins/can_has_sphinx/Rakefile +22 -0
- data/plugins/can_has_sphinx/init.rb +1 -0
- data/plugins/can_has_sphinx/install.rb +1 -0
- data/plugins/can_has_sphinx/lib/acts_as_sphinx.rb +123 -0
- data/plugins/can_has_sphinx/lib/sphinx.rb +460 -0
- data/plugins/can_has_sphinx/scripts/sphinx.sh +47 -0
- data/plugins/can_has_sphinx/tasks/acts_as_sphinx_tasks.rake +41 -0
- data/plugins/dataobjects/REVISION +1 -0
- data/plugins/dataobjects/Rakefile +7 -0
- data/plugins/dataobjects/do.rb +246 -0
- data/plugins/dataobjects/do_mysql.rb +179 -0
- data/plugins/dataobjects/do_postgres.rb +181 -0
- data/plugins/dataobjects/do_sqlite3.rb +153 -0
- data/plugins/dataobjects/spec/do_spec.rb +150 -0
- data/plugins/dataobjects/spec/spec_helper.rb +81 -0
- data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
- data/plugins/dataobjects/swig_mysql/extconf.rb +33 -0
- data/plugins/dataobjects/swig_mysql/mysql_c.c +18800 -0
- data/plugins/dataobjects/swig_mysql/mysql_c.i +8 -0
- data/plugins/dataobjects/swig_mysql/mysql_supp.i +46 -0
- data/plugins/dataobjects/swig_postgres/Makefile +146 -0
- data/plugins/dataobjects/swig_postgres/extconf.rb +29 -0
- data/plugins/dataobjects/swig_postgres/postgres_c.bundle +0 -0
- data/plugins/dataobjects/swig_postgres/postgres_c.c +8185 -0
- data/plugins/dataobjects/swig_postgres/postgres_c.i +73 -0
- data/plugins/dataobjects/swig_sqlite/db +0 -0
- data/plugins/dataobjects/swig_sqlite/extconf.rb +9 -0
- data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +4725 -0
- data/plugins/dataobjects/swig_sqlite/sqlite_c.i +168 -0
- data/rakefile.rb +45 -23
- data/spec/acts_as_tree_spec.rb +39 -0
- data/spec/associations_spec.rb +220 -0
- data/spec/attributes_spec.rb +15 -0
- data/spec/base_spec.rb +44 -0
- data/spec/callbacks_spec.rb +45 -0
- data/spec/can_has_sphinx.rb +6 -0
- data/spec/coersion_spec.rb +34 -0
- data/spec/conditions_spec.rb +49 -0
- data/spec/conversions_to_yaml_spec.rb +17 -0
- data/spec/count_command_spec.rb +11 -0
- data/spec/delete_command_spec.rb +1 -1
- data/spec/embedded_value_spec.rb +23 -0
- data/spec/fixtures/animals_exhibits.yaml +2 -0
- data/spec/fixtures/people.yaml +18 -1
- data/spec/{legacy.rb → legacy_spec.rb} +3 -3
- data/spec/load_command_spec.rb +157 -20
- data/spec/magic_columns_spec.rb +9 -0
- data/spec/mock_adapter.rb +20 -0
- data/spec/models/animal.rb +1 -1
- data/spec/models/animals_exhibit.rb +6 -0
- data/spec/models/exhibit.rb +2 -0
- data/spec/models/person.rb +26 -1
- data/spec/models/project.rb +19 -0
- data/spec/models/sales_person.rb +1 -0
- data/spec/models/section.rb +6 -0
- data/spec/models/zoo.rb +3 -1
- data/spec/query_spec.rb +9 -0
- data/spec/save_command_spec.rb +65 -1
- data/spec/schema_spec.rb +89 -0
- data/spec/single_table_inheritance_spec.rb +27 -0
- data/spec/spec_helper.rb +9 -55
- data/spec/{symbolic_operators.rb → symbolic_operators_spec.rb} +9 -5
- data/spec/{validates_confirmation_of.rb → validates_confirmation_of_spec.rb} +4 -3
- data/spec/{validates_format_of.rb → validates_format_of_spec.rb} +5 -4
- data/spec/{validates_length_of.rb → validates_length_of_spec.rb} +8 -7
- data/spec/{validates_uniqueness_of.rb → validates_uniqueness_of_spec.rb} +7 -10
- data/spec/{validations.rb → validations_spec.rb} +24 -6
- data/tasks/drivers.rb +20 -0
- data/tasks/fixtures.rb +42 -0
- metadata +181 -42
- data/lib/data_mapper/adapters/sql/commands/advanced_load_command.rb +0 -140
- data/lib/data_mapper/adapters/sql/commands/delete_command.rb +0 -113
- data/lib/data_mapper/adapters/sql/commands/save_command.rb +0 -141
- data/lib/data_mapper/adapters/sql/commands/table_exists_command.rb +0 -33
- data/lib/data_mapper/adapters/sql_adapter.rb +0 -163
- data/lib/data_mapper/associations/advanced_has_many_association.rb +0 -55
- data/lib/data_mapper/support/blank_slate.rb +0 -3
- data/lib/data_mapper/support/proc.rb +0 -69
- data/lib/data_mapper/support/struct.rb +0 -26
- data/lib/data_mapper/unit_of_work.rb +0 -38
- data/spec/basic_finder.rb +0 -67
- data/spec/belongs_to.rb +0 -47
- data/spec/has_and_belongs_to_many.rb +0 -25
- data/spec/has_many.rb +0 -34
- data/spec/new_record.rb +0 -24
- data/spec/sub_select.rb +0 -16
- data/spec/support/string_spec.rb +0 -7
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
describe DataMapper::Base do
|
|
2
|
+
|
|
3
|
+
it 'should allow mass-assignment of attributes' do
|
|
4
|
+
zoo = Zoo.new(:name => 'MassAssignment', :notes => 'This is a test.')
|
|
5
|
+
|
|
6
|
+
zoo.name.should eql('MassAssignment')
|
|
7
|
+
zoo.notes.should eql('This is a test.')
|
|
8
|
+
|
|
9
|
+
zoo.attributes = { :name => 'ThroughAttributesEqual', :notes => 'This is another test.' }
|
|
10
|
+
|
|
11
|
+
zoo.name.should eql('ThroughAttributesEqual')
|
|
12
|
+
zoo.notes.should eql('This is another test.')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
data/spec/base_spec.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
describe DataMapper::Base do
|
|
2
|
+
|
|
3
|
+
it "attributes method should load all lazy-loaded values" do
|
|
4
|
+
Animal.first(:name => 'Cup').attributes[:notes].should == 'I am a Cup!'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
it "mass assignment should call methods" do
|
|
8
|
+
class Animal
|
|
9
|
+
attr_reader :test
|
|
10
|
+
def test=(value)
|
|
11
|
+
@test = value + '!'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
a = Animal.new(:test => 'testing')
|
|
16
|
+
a.test.should == 'testing!'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe 'A new record' do
|
|
22
|
+
|
|
23
|
+
before(:each) do
|
|
24
|
+
@bob = Person.new(:name => 'Bob', :age => 30, :occupation => 'Sales')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should be dirty' do
|
|
28
|
+
@bob.dirty?.should == true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'set attributes should be dirty' do
|
|
32
|
+
attributes = @bob.attributes.dup.reject { |k,v| k == :id }
|
|
33
|
+
@bob.dirty_attributes.should == { :name => 'Bob', :age => 30, :occupation => 'Sales' }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'should be marked as new' do
|
|
37
|
+
@bob.new_record?.should == true
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'should have a nil id' do
|
|
41
|
+
@bob.id.should == nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
describe DataMapper::Callbacks do
|
|
2
|
+
|
|
3
|
+
it "should allow for a callback to be set, then called" do
|
|
4
|
+
|
|
5
|
+
example = Class.new do
|
|
6
|
+
include DataMapper::CallbacksHelper
|
|
7
|
+
|
|
8
|
+
attr_accessor :name
|
|
9
|
+
|
|
10
|
+
def initialize(name)
|
|
11
|
+
@name = name
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
before_save 'name = "bob"'
|
|
15
|
+
before_validation { |instance| instance.name = 'Barry White Returns!' }
|
|
16
|
+
|
|
17
|
+
end.new('Barry White')
|
|
18
|
+
|
|
19
|
+
example.class::callbacks.execute(:before_save, example)
|
|
20
|
+
example.name.should == 'Barry White'
|
|
21
|
+
|
|
22
|
+
example.class::callbacks.execute(:before_validation, example)
|
|
23
|
+
example.name.should == 'Barry White Returns!'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should allow method delegation by passing symbols to the callback definitions" do
|
|
27
|
+
|
|
28
|
+
example = Class.new do
|
|
29
|
+
include DataMapper::CallbacksHelper
|
|
30
|
+
|
|
31
|
+
attr_accessor :name
|
|
32
|
+
|
|
33
|
+
before_save :test
|
|
34
|
+
|
|
35
|
+
def test
|
|
36
|
+
@name = 'Walter'
|
|
37
|
+
end
|
|
38
|
+
end.new
|
|
39
|
+
|
|
40
|
+
example.class::callbacks.execute(:before_save, example)
|
|
41
|
+
example.name.should == 'Walter'
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
describe DataMapper::Adapters::Sql::Coersion do
|
|
2
|
+
|
|
3
|
+
before(:all) do
|
|
4
|
+
@coersive = Class.new do
|
|
5
|
+
include DataMapper::Adapters::Sql::Coersion
|
|
6
|
+
end.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'should cast to a BigDecimal' do
|
|
10
|
+
target = BigDecimal.new('7.2')
|
|
11
|
+
@coersive.type_cast_decimal('7.2').should == target
|
|
12
|
+
@coersive.type_cast_decimal(7.2).should == target
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'should store and load a date' do
|
|
16
|
+
dob = Date::today
|
|
17
|
+
bob = Person.create(:name => 'DateCoersionTest', :date_of_birth => dob)
|
|
18
|
+
|
|
19
|
+
bob2 = Person[:name => 'DateCoersionTest']
|
|
20
|
+
|
|
21
|
+
bob.date_of_birth.should eql(dob)
|
|
22
|
+
bob.date_of_birth.should eql(bob2.date_of_birth)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'should cast to a Date' do
|
|
26
|
+
target = Date.civil(2001, 1, 1)
|
|
27
|
+
|
|
28
|
+
@coersive.type_cast_date('2001-1-1').should eql(target)
|
|
29
|
+
@coersive.type_cast_date(target.dup).should eql(target)
|
|
30
|
+
@coersive.type_cast_date(DateTime::parse('2001-1-1')).should eql(target)
|
|
31
|
+
@coersive.type_cast_date(Time::parse('2001-1-1')).should eql(target)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
describe DataMapper::Adapters::Sql::Commands::Conditions do
|
|
2
|
+
|
|
3
|
+
def conditions_for(klass, options = {})
|
|
4
|
+
session = database(:mock)
|
|
5
|
+
DataMapper::Adapters::Sql::Commands::LoadCommand.new(
|
|
6
|
+
session.adapter, session, klass, options
|
|
7
|
+
).conditions
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'empty? should be false if conditions are present' do
|
|
11
|
+
conditions_for(Zoo, :name => 'Galveston').empty?.should == false
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'should map implicit option names to field names' do
|
|
15
|
+
conditions_for(Zoo, :name => 'Galveston').to_parameterized_sql.should == ["(`name` = ?)", 'Galveston']
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'should qualify with table name when using a join' do
|
|
19
|
+
conditions = conditions_for(Zoo, :name => 'Galveston', :include => :exhibits)
|
|
20
|
+
conditions.to_parameterized_sql.should == ["(`zoos`.`name` = ?)", 'Galveston']
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should use Symbol::Operator to determine operator' do
|
|
24
|
+
conditions_for(Person, :age.gt => 28).to_parameterized_sql.should == ["(`age` > ?)", 28]
|
|
25
|
+
conditions_for(Person, :age.gte => 28).to_parameterized_sql.should == ["(`age` >= ?)", 28]
|
|
26
|
+
|
|
27
|
+
conditions_for(Person, :age.lt => 28).to_parameterized_sql.should == ["(`age` < ?)", 28]
|
|
28
|
+
conditions_for(Person, :age.lte => 28).to_parameterized_sql.should == ["(`age` <= ?)", 28]
|
|
29
|
+
|
|
30
|
+
conditions_for(Person, :age.not => 28).to_parameterized_sql.should == ["(`age` <> ?)", 28]
|
|
31
|
+
conditions_for(Person, :age.eql => 28).to_parameterized_sql.should == ["(`age` = ?)", 28]
|
|
32
|
+
|
|
33
|
+
conditions_for(Person, :name.like => 'S%').to_parameterized_sql.should == ["(`name` LIKE ?)", 'S%']
|
|
34
|
+
|
|
35
|
+
conditions_for(Person, :age.in => [ 28, 29 ]).to_parameterized_sql.should == ["(`age` IN ?)", [ 28, 29 ]]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'should use an IN clause for an Array' do
|
|
39
|
+
conditions = conditions_for(Person, :age => [ 28, 29 ])
|
|
40
|
+
conditions.to_parameterized_sql.should == ["(`age` IN ?)", [ 28, 29 ]]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'should use "not" for not-equal operations' do
|
|
44
|
+
conditions_for(Person, :name.not => 'Bob').to_parameterized_sql.should == ["(`name` <> ?)", 'Bob']
|
|
45
|
+
conditions_for(Person, :name.not => nil).to_parameterized_sql.should == ["(`name` IS NOT ?)", nil]
|
|
46
|
+
conditions_for(Person, :name.not => ['Sam', 'Bob']).to_parameterized_sql.should == ["(`name` NOT IN ?)", ['Sam', 'Bob']]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
describe "Conversion to YAML" do
|
|
2
|
+
# check each model to see if the conversion *.to_yaml works.
|
|
3
|
+
Dir[File.dirname(__FILE__) + "/fixtures/*.yaml"].each do |path|
|
|
4
|
+
|
|
5
|
+
name = File::basename(path).sub(/\.yaml$/, '')
|
|
6
|
+
klass = Kernel::const_get(Inflector.classify(Inflector.singularize(name)))
|
|
7
|
+
|
|
8
|
+
it "the first #{klass} converted to YAML should match the YAML in the fixture" do
|
|
9
|
+
|
|
10
|
+
YAML::load(klass.first.to_yaml).to_a.reject do |pair|
|
|
11
|
+
pair.first == "updated_at" || pair.first == "id"
|
|
12
|
+
end.sort.should == YAML::load_file("./spec/fixtures/#{name}.yaml")[0].to_a.sort
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
data/spec/delete_command_spec.rb
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
describe DataMapper::EmbeddedValue do
|
|
2
|
+
|
|
3
|
+
before(:all) do
|
|
4
|
+
@bob = Person[:name => 'Bob']
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
it 'should proxy getting values for you' do
|
|
8
|
+
@bob.address.street.should == '123 Happy Ln.'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'should return a sub-class of the containing class' do
|
|
12
|
+
@bob.address.class.should be(Person::Address)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'should allow definition of instance methods' do
|
|
16
|
+
@bob.address.city_state_zip_code.should == 'Dallas, TX 75000'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'should allow you to use your own classes as well as long as they inherit from EmbeddedValue' do
|
|
20
|
+
@bob.location.to_s.should == 'Dallas, TX'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
data/spec/fixtures/people.yaml
CHANGED
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
- name: Sam
|
|
2
2
|
age: 29
|
|
3
3
|
occupation: Programmer
|
|
4
|
+
type: Person
|
|
5
|
+
street: 1337 Duck Way
|
|
6
|
+
city: Galveston
|
|
7
|
+
state: TX
|
|
8
|
+
zip_code: "75000"
|
|
9
|
+
notes:
|
|
10
|
+
date_of_birth: 2007-10-24T22:48:51-05:00
|
|
4
11
|
- name: Amy
|
|
5
12
|
age: 28
|
|
6
13
|
occupation: Business Analyst Manager
|
|
14
|
+
type: Person
|
|
7
15
|
- name: Scott
|
|
8
16
|
age: 25
|
|
9
17
|
occupation: Programmer
|
|
18
|
+
type: SalesPerson
|
|
19
|
+
commission: 172
|
|
10
20
|
- name: Josh
|
|
11
21
|
age: 23
|
|
12
22
|
occupation: Supervisor
|
|
23
|
+
type:
|
|
13
24
|
- name: Bob
|
|
14
25
|
age: 29
|
|
15
|
-
occupation: Peon
|
|
26
|
+
occupation: Peon
|
|
27
|
+
street: 123 Happy Ln.
|
|
28
|
+
city: Dallas
|
|
29
|
+
state: TX
|
|
30
|
+
zip_code: 75000
|
|
31
|
+
type: SalesPerson
|
|
32
|
+
commission: 40
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
describe 'Legacy mappings' do
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
it('should allow models to map with custom attribute names') do
|
|
4
4
|
Fruit.first.name.should == 'Kiwi'
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
it('should allow custom foreign-key mappings') do
|
|
8
8
|
database do
|
|
9
9
|
Fruit[:name => 'Watermelon'].devourer_of_souls.should == Animal[:name => 'Cup']
|
|
10
10
|
Animal[:name => 'Cup'].favourite_fruit.should == Fruit[:name => 'Watermelon']
|
data/spec/load_command_spec.rb
CHANGED
|
@@ -4,41 +4,178 @@ describe DataMapper::Adapters::Sql::Commands::LoadCommand do
|
|
|
4
4
|
fixtures(:zoos)
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
+
def loader_for(klass, options = {})
|
|
8
|
+
session = database(:mock)
|
|
9
|
+
DataMapper::Adapters::Sql::Commands::LoadCommand.new(session.adapter, session, klass, options)
|
|
10
|
+
end
|
|
11
|
+
|
|
7
12
|
it "should return a Struct for custom queries" do
|
|
8
13
|
results = database.query("SELECT * FROM zoos WHERE name = ?", 'Galveston')
|
|
9
14
|
zoo = results.first
|
|
10
|
-
zoo.class.superclass.should ==
|
|
15
|
+
zoo.class.superclass.should == Struct
|
|
11
16
|
zoo.name.should == "Galveston"
|
|
12
17
|
end
|
|
13
|
-
|
|
14
|
-
end
|
|
15
18
|
|
|
16
|
-
describe DataMapper::Adapters::Sql::Commands::AdvancedLoadCommand do
|
|
17
|
-
|
|
18
|
-
def loader_for(klass, options = {})
|
|
19
|
-
session = database
|
|
20
|
-
DataMapper::Adapters::Sql::Commands::AdvancedLoadCommand.new(session.adapter, session, klass, options)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
19
|
it "should return a simple select statement for a given class" do
|
|
24
|
-
loader_for(Zoo).
|
|
20
|
+
loader_for(Zoo).to_parameterized_sql.first.should == 'SELECT `id`, `name`, `updated_at` FROM `zoos`'
|
|
25
21
|
end
|
|
26
|
-
|
|
22
|
+
|
|
27
23
|
it "should include only the columns specified in the statement" do
|
|
28
|
-
loader_for(Zoo, :select => [:name]).
|
|
24
|
+
loader_for(Zoo, :select => [:name]).to_parameterized_sql.first.should == 'SELECT `name` FROM `zoos`'
|
|
29
25
|
end
|
|
30
|
-
|
|
26
|
+
|
|
31
27
|
it "should optionally include lazy-loaded columns in the statement" do
|
|
32
|
-
loader_for(Zoo, :include => :notes).
|
|
28
|
+
loader_for(Zoo, :include => :notes).to_parameterized_sql.first.should == 'SELECT `id`, `name`, `updated_at`, `notes` FROM `zoos`'
|
|
33
29
|
end
|
|
34
|
-
|
|
30
|
+
|
|
35
31
|
it "should join associations in the statement" do
|
|
36
|
-
loader_for(Zoo, :include => :
|
|
37
|
-
SELECT `zoos`.`id`, `zoos`.`name`,
|
|
32
|
+
loader_for(Zoo, :include => :exhibits).to_parameterized_sql.first.should == <<-EOS.compress_lines
|
|
33
|
+
SELECT `zoos`.`id`, `zoos`.`name`, `zoos`.`updated_at`,
|
|
38
34
|
`exhibits`.`id`, `exhibits`.`name`, `exhibits`.`zoo_id`
|
|
39
35
|
FROM `zoos`
|
|
40
|
-
JOIN `exhibits` ON `exhibits`.`
|
|
36
|
+
JOIN `exhibits` ON `exhibits`.`zoo_id` = `zoos`.`id`
|
|
41
37
|
EOS
|
|
42
38
|
end
|
|
39
|
+
|
|
40
|
+
it "should join has and belongs to many associtions in the statement" do
|
|
41
|
+
loader_for(Animal, :include => :exhibits).to_parameterized_sql.first.should == <<-EOS.compress_lines
|
|
42
|
+
SELECT `animals`.`id`, `animals`.`name`,
|
|
43
|
+
`exhibits`.`id`, `exhibits`.`name`, `exhibits`.`zoo_id`,
|
|
44
|
+
`animals_exhibits`.`animal_id`, `animals_exhibits`.`exhibit_id`
|
|
45
|
+
FROM `animals`
|
|
46
|
+
JOIN `animals_exhibits` ON `animals_exhibits`.`animal_id` = `animals`.`id`
|
|
47
|
+
JOIN `exhibits` ON `exhibits`.`id` = `animals_exhibits`.`exhibit_id`
|
|
48
|
+
EOS
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should shallow-join unmapped tables for has-and-belongs-to-many in the statement" do
|
|
52
|
+
loader_for(Animal, :shallow_include => :exhibits).to_parameterized_sql.first.should == <<-EOS.compress_lines
|
|
53
|
+
SELECT `animals`.`id`, `animals`.`name`,
|
|
54
|
+
`animals_exhibits`.`animal_id`, `animals_exhibits`.`exhibit_id`
|
|
55
|
+
FROM `animals`
|
|
56
|
+
JOIN `animals_exhibits` ON `animals_exhibits`.`animal_id` = `animals`.`id`
|
|
57
|
+
EOS
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "should allow multiple implicit conditions" do
|
|
61
|
+
expected_sql = <<-EOS.compress_lines
|
|
62
|
+
SELECT `id`, `name`, `age`, `occupation`,
|
|
63
|
+
`type`, `street`, `city`, `state`, `zip_code`
|
|
64
|
+
FROM `people`
|
|
65
|
+
WHERE (`name` = ?) AND (`age` = ?)
|
|
66
|
+
EOS
|
|
67
|
+
|
|
68
|
+
# NOTE: I'm actually not sure how to test this since the order of the parameters isn't gauranteed.
|
|
69
|
+
# Maybe an ugly OrderedHash passed as the options...
|
|
70
|
+
# loader_for(Person, :name => 'Sam', :age => 29).to_parameterized_sql.should == [expected_sql, 'Sam', 29]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should allow block-interception during load" do
|
|
74
|
+
result = false
|
|
75
|
+
Person.first(:intercept_load => lambda { result = true })
|
|
76
|
+
result.should == true
|
|
77
|
+
end
|
|
43
78
|
|
|
44
|
-
|
|
79
|
+
it 'database-specific load should not fail' do
|
|
80
|
+
|
|
81
|
+
DataMapper::database do |db|
|
|
82
|
+
froggy = db.first(Animal, :conditions => ['name = ?', 'Frog'])
|
|
83
|
+
froggy.name.should == 'Frog'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'current-database load should not fail' do
|
|
89
|
+
froggy = DataMapper::database.first(Animal).name.should == 'Frog'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'load through ActiveRecord impersonation should not fail' do
|
|
93
|
+
Animal.find(:all).size.should == 16
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'load through Og impersonation should not fail' do
|
|
97
|
+
Animal.all.size.should == 16
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it ':conditions option should accept a hash' do
|
|
101
|
+
Animal.all(:conditions => { :name => 'Frog' }).size.should == 1
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'non-standard options should be considered part of the conditions' do
|
|
105
|
+
database.log.debug { 'non-standard options should be considered part of the conditions' }
|
|
106
|
+
zebra = Animal.first(:name => 'Zebra')
|
|
107
|
+
zebra.name.should == 'Zebra'
|
|
108
|
+
|
|
109
|
+
elephant = Animal[:name => 'Elephant']
|
|
110
|
+
elephant.name.should == 'Elephant'
|
|
111
|
+
|
|
112
|
+
aged = Person.all(:age => 29)
|
|
113
|
+
aged.size.should == 2
|
|
114
|
+
aged.first.name.should == 'Sam'
|
|
115
|
+
aged.last.name.should == 'Bob'
|
|
116
|
+
|
|
117
|
+
fixtures(:animals)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'should not find deleted objects' do
|
|
121
|
+
database do
|
|
122
|
+
wally = Animal[:name => 'Whale']
|
|
123
|
+
wally.new_record?.should == false
|
|
124
|
+
wally.destroy!.should == true
|
|
125
|
+
|
|
126
|
+
wallys_evil_twin = Animal[:name => 'Whale']
|
|
127
|
+
wallys_evil_twin.should == nil
|
|
128
|
+
|
|
129
|
+
wally.new_record?.should == true
|
|
130
|
+
wally.save
|
|
131
|
+
wally.new_record?.should == false
|
|
132
|
+
|
|
133
|
+
Animal[:name => 'Whale'].should == wally
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'lazy-loads should issue for whole sets' do
|
|
138
|
+
people = Person.all
|
|
139
|
+
|
|
140
|
+
people.each do |person|
|
|
141
|
+
person.notes
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "should only query once" do
|
|
146
|
+
database do
|
|
147
|
+
zoo = Zoo.first
|
|
148
|
+
same_zoo = Zoo[zoo.id]
|
|
149
|
+
|
|
150
|
+
zoo.should == same_zoo
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "should return a single object" do
|
|
155
|
+
Zoo.first.should be_a_kind_of(Zoo)
|
|
156
|
+
Zoo[1].should be_a_kind_of(Zoo)
|
|
157
|
+
Zoo.find(1).should be_a_kind_of(Zoo)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "should be able to search on UTF-8 strings" do
|
|
161
|
+
Zoo.create(:name => 'Danish Vowels: Smøøt!')
|
|
162
|
+
Zoo.first(:name.like => '%Smøøt%').should be_a_kind_of(Zoo)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
=begin
|
|
167
|
+
context 'Sub-selection' do
|
|
168
|
+
|
|
169
|
+
specify 'should return a Cup' do
|
|
170
|
+
Animal[:id.select => { :name => 'cup' }].name.should == 'Cup'
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
specify 'should return all exhibits for Galveston zoo' do
|
|
174
|
+
Exhibit.all(:zoo_id.select(Zoo) => { :name => 'Galveston' }).size.should == 3
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
specify 'should allow a sub-select in the select-list' do
|
|
178
|
+
Animal[:select => [ :id.count ]]
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
=end
|