bigrecord 0.0.5
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/MIT-LICENSE +20 -0
- data/README.rdoc +44 -0
- data/Rakefile +17 -0
- data/VERSION +1 -0
- data/doc/bigrecord_specs.rdoc +36 -0
- data/doc/getting_started.rdoc +157 -0
- data/examples/bigrecord.yml +25 -0
- data/generators/bigrecord/bigrecord_generator.rb +17 -0
- data/generators/bigrecord/templates/bigrecord.rake +47 -0
- data/generators/bigrecord_migration/bigrecord_migration_generator.rb +13 -0
- data/generators/bigrecord_migration/templates/migration.rb +9 -0
- data/generators/bigrecord_model/bigrecord_model_generator.rb +28 -0
- data/generators/bigrecord_model/templates/migration.rb +13 -0
- data/generators/bigrecord_model/templates/model.rb +7 -0
- data/generators/bigrecord_model/templates/model_spec.rb +12 -0
- data/init.rb +9 -0
- data/install.rb +22 -0
- data/lib/big_record/abstract_base.rb +1088 -0
- data/lib/big_record/action_view_extensions.rb +266 -0
- data/lib/big_record/ar_associations/association_collection.rb +194 -0
- data/lib/big_record/ar_associations/association_proxy.rb +158 -0
- data/lib/big_record/ar_associations/belongs_to_association.rb +57 -0
- data/lib/big_record/ar_associations/belongs_to_many_association.rb +57 -0
- data/lib/big_record/ar_associations/has_and_belongs_to_many_association.rb +164 -0
- data/lib/big_record/ar_associations/has_many_association.rb +191 -0
- data/lib/big_record/ar_associations/has_one_association.rb +80 -0
- data/lib/big_record/ar_associations.rb +1608 -0
- data/lib/big_record/ar_reflection.rb +223 -0
- data/lib/big_record/attribute_methods.rb +75 -0
- data/lib/big_record/base.rb +618 -0
- data/lib/big_record/br_associations/association_collection.rb +194 -0
- data/lib/big_record/br_associations/association_proxy.rb +153 -0
- data/lib/big_record/br_associations/belongs_to_association.rb +52 -0
- data/lib/big_record/br_associations/belongs_to_many_association.rb +293 -0
- data/lib/big_record/br_associations/cached_item_proxy.rb +194 -0
- data/lib/big_record/br_associations/cached_item_proxy_factory.rb +62 -0
- data/lib/big_record/br_associations/has_and_belongs_to_many_association.rb +168 -0
- data/lib/big_record/br_associations/has_one_association.rb +80 -0
- data/lib/big_record/br_associations.rb +978 -0
- data/lib/big_record/br_reflection.rb +151 -0
- data/lib/big_record/callbacks.rb +367 -0
- data/lib/big_record/connection_adapters/abstract/connection_specification.rb +279 -0
- data/lib/big_record/connection_adapters/abstract/database_statements.rb +175 -0
- data/lib/big_record/connection_adapters/abstract/quoting.rb +58 -0
- data/lib/big_record/connection_adapters/abstract_adapter.rb +190 -0
- data/lib/big_record/connection_adapters/column.rb +491 -0
- data/lib/big_record/connection_adapters/hbase_adapter.rb +432 -0
- data/lib/big_record/connection_adapters/view.rb +27 -0
- data/lib/big_record/connection_adapters.rb +10 -0
- data/lib/big_record/deletion.rb +73 -0
- data/lib/big_record/dynamic_schema.rb +92 -0
- data/lib/big_record/embedded.rb +71 -0
- data/lib/big_record/embedded_associations/association_proxy.rb +148 -0
- data/lib/big_record/family_span_columns.rb +89 -0
- data/lib/big_record/fixtures.rb +1025 -0
- data/lib/big_record/migration.rb +380 -0
- data/lib/big_record/routing_ext.rb +65 -0
- data/lib/big_record/timestamp.rb +51 -0
- data/lib/big_record/validations.rb +830 -0
- data/lib/big_record.rb +125 -0
- data/lib/bigrecord.rb +1 -0
- data/rails/init.rb +9 -0
- data/spec/connections/bigrecord.yml +13 -0
- data/spec/connections/cassandra/connection.rb +2 -0
- data/spec/connections/hbase/connection.rb +2 -0
- data/spec/debug.log +281 -0
- data/spec/integration/br_associations_spec.rb +80 -0
- data/spec/lib/animal.rb +12 -0
- data/spec/lib/book.rb +10 -0
- data/spec/lib/broken_migrations/duplicate_name/20090706182535_add_animals_table.rb +14 -0
- data/spec/lib/broken_migrations/duplicate_name/20090706193019_add_animals_table.rb +9 -0
- data/spec/lib/broken_migrations/duplicate_version/20090706190623_add_books_table.rb +9 -0
- data/spec/lib/broken_migrations/duplicate_version/20090706190623_add_companies_table.rb +9 -0
- data/spec/lib/company.rb +14 -0
- data/spec/lib/embedded/web_link.rb +12 -0
- data/spec/lib/employee.rb +33 -0
- data/spec/lib/migrations/20090706182535_add_animals_table.rb +13 -0
- data/spec/lib/migrations/20090706190623_add_books_table.rb +15 -0
- data/spec/lib/migrations/20090706193019_add_companies_table.rb +14 -0
- data/spec/lib/migrations/20090706194512_add_employees_table.rb +13 -0
- data/spec/lib/migrations/20090706195741_add_zoos_table.rb +13 -0
- data/spec/lib/novel.rb +5 -0
- data/spec/lib/zoo.rb +17 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +55 -0
- data/spec/unit/abstract_base_spec.rb +287 -0
- data/spec/unit/adapters/abstract_adapter_spec.rb +56 -0
- data/spec/unit/adapters/adapter_shared_spec.rb +51 -0
- data/spec/unit/adapters/hbase_adapter_spec.rb +15 -0
- data/spec/unit/ar_associations_spec.rb +8 -0
- data/spec/unit/base_spec.rb +6 -0
- data/spec/unit/br_associations_spec.rb +58 -0
- data/spec/unit/embedded_spec.rb +43 -0
- data/spec/unit/find_spec.rb +34 -0
- data/spec/unit/hash_helper_spec.rb +44 -0
- data/spec/unit/migration_spec.rb +144 -0
- data/spec/unit/model_spec.rb +315 -0
- data/spec/unit/validations_spec.rb +182 -0
- data/tasks/bigrecord_tasks.rake +47 -0
- data/tasks/data_store.rb +46 -0
- data/tasks/gem.rb +22 -0
- data/tasks/rdoc.rb +8 -0
- data/tasks/spec.rb +34 -0
- metadata +189 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
describe BigRecord::BrAssociations do
|
|
4
|
+
|
|
5
|
+
# Clear the tables before and after these tests
|
|
6
|
+
before(:all) do
|
|
7
|
+
Animal.delete_all
|
|
8
|
+
Employee.delete_all
|
|
9
|
+
Zoo.delete_all
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should list associations in #reflections" do
|
|
13
|
+
Animal.reflections.should have_key(:zoo)
|
|
14
|
+
Animal.reflections.should have_key(:books)
|
|
15
|
+
|
|
16
|
+
Animal.reflections[:zoo].macro.should == :belongs_to_big_record
|
|
17
|
+
Animal.reflections[:books].macro.should == :belongs_to_many
|
|
18
|
+
|
|
19
|
+
Employee.reflections.should have_key(:company)
|
|
20
|
+
Employee.reflections[:company].macro.should == :belongs_to_big_record
|
|
21
|
+
|
|
22
|
+
Zoo.reflections.should have_key(:animals)
|
|
23
|
+
Zoo.reflections[:animals].macro.should == :belongs_to_many
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should mixin all the helper methods into the model for :belongs_to associations" do
|
|
27
|
+
animal = Animal.new
|
|
28
|
+
|
|
29
|
+
animal.should respond_to(:zoo)
|
|
30
|
+
animal.should respond_to(:zoo=)
|
|
31
|
+
animal.should respond_to(:build_zoo)
|
|
32
|
+
animal.should respond_to(:create_zoo)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should mixin all the helper methods into the model for :belongs_to_many associations" do
|
|
36
|
+
zoo = Zoo.new
|
|
37
|
+
|
|
38
|
+
zoo.should respond_to(:animals)
|
|
39
|
+
zoo.should respond_to(:animals=)
|
|
40
|
+
zoo.should respond_to(:animal_ids)
|
|
41
|
+
zoo.should respond_to(:animal_ids=)
|
|
42
|
+
zoo.animals.should respond_to(:<<)
|
|
43
|
+
zoo.animals.should respond_to(:delete)
|
|
44
|
+
zoo.animals.should respond_to(:clear)
|
|
45
|
+
zoo.animals.should respond_to(:empty?)
|
|
46
|
+
zoo.animals.should respond_to(:size)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "should mixin build() and create() methods into collection assocations" do
|
|
50
|
+
pending "This needs to be implemented"
|
|
51
|
+
|
|
52
|
+
zoo = Zoo.new
|
|
53
|
+
|
|
54
|
+
zoo.animals.should respond_to(:build)
|
|
55
|
+
zoo.animals.should respond_to(:create)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'abstract_base_spec'))
|
|
3
|
+
|
|
4
|
+
describe BigRecord::Embedded do
|
|
5
|
+
|
|
6
|
+
# Clear the tables before and after these tests
|
|
7
|
+
before(:all) do
|
|
8
|
+
Zoo.delete_all
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
after(:all) do
|
|
12
|
+
Zoo.delete_all
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it_should_behave_like "BigRecord::AbstractBase"
|
|
16
|
+
|
|
17
|
+
describe "embedded within a BigRecord::Base model" do
|
|
18
|
+
|
|
19
|
+
it "should save successfully" do
|
|
20
|
+
zoo = Zoo.new( :name => "African Lion Safari",
|
|
21
|
+
:address => "RR #1 Cambridge, Ontario Canada\nN1R 5S2",
|
|
22
|
+
:description => "Canada's Original Safari Adventure")
|
|
23
|
+
|
|
24
|
+
zoo.weblink = Embedded::WebLink.new(:title => "African Lion Safari - Wikipedia", :url => "http://en.wikipedia.org/wiki/African_Lion_Safari")
|
|
25
|
+
zoo.save.should be_true
|
|
26
|
+
zoo.reload
|
|
27
|
+
|
|
28
|
+
zoo.weblink.should_not be_nil
|
|
29
|
+
zoo.weblink.should be_a_kind_of(Embedded::WebLink)
|
|
30
|
+
zoo.weblink.title.should == "African Lion Safari - Wikipedia"
|
|
31
|
+
zoo.weblink.url.should == "http://en.wikipedia.org/wiki/African_Lion_Safari"
|
|
32
|
+
|
|
33
|
+
zoo.weblink = Embedded::WebLink.new(:title => "African Lion Safari", :url => "http://www.lionsafari.com/")
|
|
34
|
+
zoo.save.should be_true
|
|
35
|
+
zoo.reload
|
|
36
|
+
|
|
37
|
+
zoo.weblink.title.should == "African Lion Safari"
|
|
38
|
+
zoo.weblink.url.should == "http://www.lionsafari.com/"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
describe BigRecord::Base do
|
|
4
|
+
|
|
5
|
+
describe "#find" do
|
|
6
|
+
|
|
7
|
+
it "should dispatch properly to #find_every when given :first" do
|
|
8
|
+
zoo = Zoo.new
|
|
9
|
+
|
|
10
|
+
Zoo.should_receive(:find_every).with(hash_including(:limit => 1)).and_return([zoo])
|
|
11
|
+
|
|
12
|
+
Zoo.find(:first).should == zoo
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should dispatch properly to #find_every when given :all" do
|
|
16
|
+
zoo = Zoo.new
|
|
17
|
+
|
|
18
|
+
Zoo.should_receive(:find_every).and_return([zoo])
|
|
19
|
+
|
|
20
|
+
Zoo.find(:all).should == [zoo]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should dispatch properly to #find_from_ids when given anything else" do
|
|
24
|
+
zoo = Zoo.new
|
|
25
|
+
id = "c6e2cf62-332d-44f0-a558-dfdfe2c7ee1e"
|
|
26
|
+
|
|
27
|
+
Zoo.should_receive(:find_from_ids).with([id], an_instance_of(Hash)).and_return([zoo])
|
|
28
|
+
|
|
29
|
+
Zoo.find(id).should == [zoo]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
# Not exactly the most comprehensive testing for this function.
|
|
4
|
+
describe Hash do
|
|
5
|
+
|
|
6
|
+
before(:each) do
|
|
7
|
+
@hash1 = { :key1 => "value1", :key2 => "value2", :key3 => "value3" }
|
|
8
|
+
@hash2 = { :key1 => "value1", :key2 => "value2", :key3 => "value3", :key4 => "value4" }
|
|
9
|
+
@hash3 = { :key1 => "value4", :key2 => "value3", :key3 => "value1", :key4 => "value2" }
|
|
10
|
+
@hash4 = { :key2 => "value2", :key3 => "value3" }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "#subset_of? should compare 2 hashes correctly (when one really is a subset of the other)" do
|
|
14
|
+
@hash1.subset_of?(@hash2).should be_true
|
|
15
|
+
@hash2.subset_of?(@hash1).should be_false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "#superset_of? should compare 2 hashes correctly (when one really is a superset of the other)" do
|
|
19
|
+
@hash1.superset_of?(@hash2).should be_false
|
|
20
|
+
@hash2.superset_of?(@hash1).should be_true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "#subset_of? and #superset_of? should be true when comparing the same hash to itself" do
|
|
24
|
+
@hash1.subset_of?(@hash1).should be_true
|
|
25
|
+
@hash1.superset_of?(@hash1).should be_true
|
|
26
|
+
|
|
27
|
+
@hash2.subset_of?(@hash2).should be_true
|
|
28
|
+
@hash2.superset_of?(@hash2).should be_true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should return false when there's a mismatch of key/value pairs" do
|
|
32
|
+
@hash2.subset_of?(@hash3).should be_false
|
|
33
|
+
@hash2.superset_of?(@hash3).should be_false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should compare properly with missing keys in one of the hashes (even if all the other pairs match)" do
|
|
37
|
+
# false because @hash4 is missing :key1
|
|
38
|
+
@hash1.subset_of?(@hash4).should be_false
|
|
39
|
+
|
|
40
|
+
# it is a superset because all of the key/value pairs of @hash4 are contained within @hash1
|
|
41
|
+
@hash1.superset_of?(@hash4).should be_true
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
describe BigRecord::Migration do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@migrations_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "migrations"))
|
|
7
|
+
@migration_files = Dir["#{@migrations_path}/[0-9]*_*.rb"]
|
|
8
|
+
|
|
9
|
+
@broken_migrations_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "broken_migrations"))
|
|
10
|
+
@broken_migration_files = Dir["#{@broken_migrations_path}/[0-9]*_*.rb"]
|
|
11
|
+
|
|
12
|
+
# It doesn't matter whether the adapter works for this spec, so we'll mock it
|
|
13
|
+
@mock_connection = mock(BigRecord::ConnectionAdapters::AbstractAdapter, :null_object => true)
|
|
14
|
+
@mock_connection.stub!(:supports_ddl_transactions?).and_return(false)
|
|
15
|
+
|
|
16
|
+
# Replace BigRecord::Base.connection to always return the mock_connection
|
|
17
|
+
BigRecord::Base.stub!(:connection).and_return(@mock_connection)
|
|
18
|
+
|
|
19
|
+
# We don't want it outputting to stdout
|
|
20
|
+
BigRecord::Migration.verbose = false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "class methods and initialization" do
|
|
24
|
+
|
|
25
|
+
it "#proper_table_name should return the corresponding table name for the data store (with different arguments types)" do
|
|
26
|
+
# Check that it works with a symbol, BigRecord model, or string.
|
|
27
|
+
BigRecord::Migrator.proper_table_name(:animals).should == "animals"
|
|
28
|
+
BigRecord::Migrator.proper_table_name(Animal).should == "animals"
|
|
29
|
+
BigRecord::Migrator.proper_table_name("animals").should == "animals"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "#get_all_versions should query from the data store" do
|
|
33
|
+
@mock_connection.should_receive(:get_all_schema_versions).and_return(["version1"])
|
|
34
|
+
|
|
35
|
+
BigRecord::Migrator.get_all_versions.should == ["version1"]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should initialize the migrator given a directory of migration files" do
|
|
39
|
+
# Assuming that the adapter supports migrations
|
|
40
|
+
@mock_connection.should_receive(:supports_migrations?).and_return(true)
|
|
41
|
+
|
|
42
|
+
# Setting up the migrator will initialize the schema migration table
|
|
43
|
+
@mock_connection.should_receive(:initialize_schema_migrations_table)
|
|
44
|
+
|
|
45
|
+
# Initializing the migrator
|
|
46
|
+
migrator = BigRecord::Migrator.new(:up, @migrations_path)
|
|
47
|
+
|
|
48
|
+
# Now assuming that the adapter doesn't supports migrations
|
|
49
|
+
@mock_connection.should_receive(:supports_migrations?).and_return(false)
|
|
50
|
+
|
|
51
|
+
# Setting up the migrator should not initialize the schema migration table
|
|
52
|
+
@mock_connection.should_not_receive(:initialize_schema_migrations_table)
|
|
53
|
+
|
|
54
|
+
lambda{
|
|
55
|
+
migrator = BigRecord::Migrator.new(:up, @migrations_path)
|
|
56
|
+
}.should raise_error(StandardError)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "migrator methods" do
|
|
62
|
+
|
|
63
|
+
before(:each) do
|
|
64
|
+
# Setting up the migrator will initialize the schema migration table
|
|
65
|
+
@mock_connection.should_receive(:initialize_schema_migrations_table)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should show all the pending migrations" do
|
|
69
|
+
# Initializing the migrator
|
|
70
|
+
@migrator = BigRecord::Migrator.new(:up, @migrations_path)
|
|
71
|
+
|
|
72
|
+
# And request all the schema versions currently within the data store
|
|
73
|
+
@mock_connection.should_receive(:get_all_schema_versions).and_return([])
|
|
74
|
+
|
|
75
|
+
# Verify that our migrations are listed as pending
|
|
76
|
+
@migration_files.each do |migration_file|
|
|
77
|
+
@migrator.pending_migrations.map(&:filename).should include(migration_file)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should run the migrations and update the schema migration table in the data store" do
|
|
82
|
+
# Initializing the migrator
|
|
83
|
+
@migrator = BigRecord::Migrator.new(:up, @migrations_path)
|
|
84
|
+
|
|
85
|
+
# And request all the schema versions currently within the data store
|
|
86
|
+
@mock_connection.should_receive(:get_all_schema_versions).and_return([])
|
|
87
|
+
|
|
88
|
+
# The data store will be updated once for each migration file
|
|
89
|
+
@mock_connection.should_receive(:update).exactly(@migration_files.size).times.and_return(true)
|
|
90
|
+
result = @migrator.migrate
|
|
91
|
+
|
|
92
|
+
# The pending migrations should now be listed in the migrated #migrated method and removed from #pending_migrations
|
|
93
|
+
result.size.should == @migration_files.size
|
|
94
|
+
@migrator.migrated.size.should == @migration_files.size
|
|
95
|
+
@migrator.pending_migrations.should be_empty
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should call the appropriate adapter connection methods when migrating :up" do
|
|
99
|
+
# Initializing the migrator
|
|
100
|
+
@migrator = BigRecord::Migrator.new(:up, @migrations_path, 20090706182535) # Hard-coded target. Don't change the migration!
|
|
101
|
+
|
|
102
|
+
# And request all the schema versions currently within the data store
|
|
103
|
+
@mock_connection.should_receive(:get_all_schema_versions).and_return([])
|
|
104
|
+
|
|
105
|
+
@mock_connection.should_receive(:create_table).with("animals", {:force => true}).once.and_return(true)
|
|
106
|
+
@migrator.migrate
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "should call the appropriate adapter connection methods when reverting :down" do
|
|
110
|
+
# Initializing the migrator
|
|
111
|
+
@migrator = BigRecord::Migrator.new(:down, @migrations_path) # Hard-coded target. Don't change the migration!
|
|
112
|
+
|
|
113
|
+
# And request all the schema versions currently within the data store.
|
|
114
|
+
@mock_connection.should_receive(:get_all_schema_versions).and_return([20090706182535]) # Hard-coded target. Don't change the migration!
|
|
115
|
+
|
|
116
|
+
@mock_connection.should_receive(:drop_table).with("animals").once.and_return(true)
|
|
117
|
+
@migrator.migrate
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
describe "error handling" do
|
|
123
|
+
|
|
124
|
+
it "should raise an error on duplicate version numbers" do
|
|
125
|
+
# Initializing the migrator
|
|
126
|
+
@migrator = BigRecord::Migrator.new(:up, @broken_migrations_path+"/duplicate_version")
|
|
127
|
+
|
|
128
|
+
lambda {
|
|
129
|
+
@migrator.migrations
|
|
130
|
+
}.should raise_error(BigRecord::DuplicateMigrationVersionError)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "should raise an error on duplicate migration names" do
|
|
134
|
+
# Initializing the migrator
|
|
135
|
+
@migrator = BigRecord::Migrator.new(:up, @broken_migrations_path+"/duplicate_name")
|
|
136
|
+
|
|
137
|
+
lambda {
|
|
138
|
+
@migrator.migrations
|
|
139
|
+
}.should raise_error(BigRecord::DuplicateMigrationNameError)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
end
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
describe BigRecord::Base do
|
|
4
|
+
|
|
5
|
+
# Clear the tables before and after these tests
|
|
6
|
+
before(:all) do
|
|
7
|
+
Book.delete_all
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
after(:all) do
|
|
11
|
+
Book.delete_all
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should provide .id" do
|
|
15
|
+
Book.new.should respond_to(:id)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should provide hash-like attribute accessors, i.e. [] and []=" do
|
|
19
|
+
Book.new.should respond_to(:[])
|
|
20
|
+
Book.new.should respond_to(:[]=)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should provide #create' do
|
|
24
|
+
Book.should respond_to(:create)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#create' do
|
|
28
|
+
|
|
29
|
+
it 'should create a new record in the data store' do
|
|
30
|
+
book = Book.create(:title => "I Am Legend", :author => "Richard Matheson")
|
|
31
|
+
|
|
32
|
+
book.should be_a_kind_of(Book)
|
|
33
|
+
book.id.should_not be_nil
|
|
34
|
+
book.new_record?.should be_false
|
|
35
|
+
|
|
36
|
+
book_confirm = Book.find(book.id)
|
|
37
|
+
|
|
38
|
+
book_confirm.title.should == "I Am Legend"
|
|
39
|
+
book_confirm.author.should == "Richard Matheson"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'should return the unsaved object even if a record could not be created' do
|
|
43
|
+
attributes = {:title => "I Am Legend", :author => "Richard Matheson"}
|
|
44
|
+
book = Book.new(attributes)
|
|
45
|
+
|
|
46
|
+
# Mocking the #create method in Base to return a specific book object we define
|
|
47
|
+
Book.should_receive(:new).and_return(book)
|
|
48
|
+
|
|
49
|
+
# When #save is called on our book object, it'll return false.
|
|
50
|
+
book.should_receive(:save).and_return(false)
|
|
51
|
+
|
|
52
|
+
# Now we'll try the #create method on the Book class
|
|
53
|
+
created_book = Book.create(attributes)
|
|
54
|
+
|
|
55
|
+
# The save shouldn't have succeeded
|
|
56
|
+
created_book.new_record?.should be_true
|
|
57
|
+
|
|
58
|
+
# But we should still receive a book object that's the same
|
|
59
|
+
created_book.should == book
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Protected instance method called by .save (different than Class#create)
|
|
65
|
+
it 'should provide .create' do
|
|
66
|
+
Book.new.should respond_to(:create)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Protected instance method called by .save
|
|
70
|
+
it 'should provide .update' do
|
|
71
|
+
Book.new.should respond_to(:update)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'should provide .save and .save!' do
|
|
75
|
+
Book.new.should respond_to(:save)
|
|
76
|
+
Book.new.should respond_to(:save!)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe '.save and .save!' do
|
|
80
|
+
|
|
81
|
+
describe 'with a new resource' do
|
|
82
|
+
|
|
83
|
+
it 'should create new entries in the data store' do
|
|
84
|
+
# Create a new object
|
|
85
|
+
book = Book.new( :title => "I Am Legend",
|
|
86
|
+
:author => "Richard Matheson",
|
|
87
|
+
:description => "The most clever and riveting vampire novel since Dracula.")
|
|
88
|
+
|
|
89
|
+
book.new_record?.should be_true
|
|
90
|
+
book.id.should be_nil
|
|
91
|
+
book.save.should be_true
|
|
92
|
+
|
|
93
|
+
book.new_record?.should be_false
|
|
94
|
+
book.id.should_not be_nil
|
|
95
|
+
|
|
96
|
+
# Verify that the object was saved
|
|
97
|
+
book2 = Book.find(book.id)
|
|
98
|
+
|
|
99
|
+
book2.title.should == "I Am Legend"
|
|
100
|
+
book2.author.should == "Richard Matheson"
|
|
101
|
+
book2.description.should == "The most clever and riveting vampire novel since Dracula."
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'should raise an exception with .save! if a record was not saved or true if successful' do
|
|
105
|
+
book = Book.new( :title => "I Am Legend",
|
|
106
|
+
:author => "Richard Matheson",
|
|
107
|
+
:description => "The most clever and riveting vampire novel since Dracula.")
|
|
108
|
+
|
|
109
|
+
# The actual method that's called just before the data store write is #update_big_record, which returns
|
|
110
|
+
# a boolean. We're going to mock this method and have it return false.
|
|
111
|
+
book.should_receive(:update_bigrecord).and_return(false)
|
|
112
|
+
|
|
113
|
+
# Verify that an exception is raised
|
|
114
|
+
lambda { book.save! }.should raise_error(BigRecord::RecordNotSaved)
|
|
115
|
+
|
|
116
|
+
# Verify that true gets returned on success
|
|
117
|
+
book.should_receive(:update_bigrecord).and_return(true)
|
|
118
|
+
book.save.should be_true
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe 'with an existing record' do
|
|
124
|
+
|
|
125
|
+
before(:each) do
|
|
126
|
+
# Just want to verify that the book is created properly everytime
|
|
127
|
+
new_book = Book.new( :title => "I Am Legend",
|
|
128
|
+
:author => "Richard Matheson",
|
|
129
|
+
:description => "The most clever and riveting vampire novel since Dracula.")
|
|
130
|
+
|
|
131
|
+
new_book.save.should be_true
|
|
132
|
+
|
|
133
|
+
# Maybe a little paranoid...
|
|
134
|
+
new_book.new_record?.should be_false
|
|
135
|
+
new_book.id.should_not be_nil
|
|
136
|
+
|
|
137
|
+
# Grab the entry from the data store and verify
|
|
138
|
+
@book = Book.find(new_book)
|
|
139
|
+
@book.title.should == "I Am Legend"
|
|
140
|
+
@book.author.should == "Richard Matheson"
|
|
141
|
+
@book.description.should == "The most clever and riveting vampire novel since Dracula."
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'should update that record' do
|
|
145
|
+
@book.description = "One of the Ten All-Time Best Novels of Vampirism."
|
|
146
|
+
@book.save.should be_true
|
|
147
|
+
|
|
148
|
+
book_verify = Book.find(@book)
|
|
149
|
+
book_verify.description.should == "One of the Ten All-Time Best Novels of Vampirism."
|
|
150
|
+
book_verify.id.should == @book.id
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
describe 'modified attribute tracking' do
|
|
158
|
+
|
|
159
|
+
it "should not mark attributes as modified if they are similar" do
|
|
160
|
+
pending "attribute tracking needs to be implemented in BigRecord::Base"
|
|
161
|
+
|
|
162
|
+
attributes = { :title => "I Am Legend",
|
|
163
|
+
:author => "Richard Matheson",
|
|
164
|
+
:description => "The most clever and riveting vampire novel since Dracula." }
|
|
165
|
+
|
|
166
|
+
book = Book.new(attributes)
|
|
167
|
+
book.save.should be_true
|
|
168
|
+
|
|
169
|
+
book.attributes = attributes
|
|
170
|
+
|
|
171
|
+
book.modified_attributes.should be_empty
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "should track modified attributes" do
|
|
175
|
+
pending "attribute tracking needs to be implemented in BigRecord::Base"
|
|
176
|
+
|
|
177
|
+
attributes = { :title => "I Am Legend",
|
|
178
|
+
:author => "Richard Matheson",
|
|
179
|
+
:description => "The most clever and riveting vampire novel since Dracula." }
|
|
180
|
+
|
|
181
|
+
book = Book.new(attributes)
|
|
182
|
+
book.save.should be_true
|
|
183
|
+
|
|
184
|
+
book.attributes = {:description => "One of the Ten All-Time Best Novels of Vampirism."}
|
|
185
|
+
|
|
186
|
+
book.modified_attributes.has_key?(:description).should be_true
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
describe 'attribute functionality' do
|
|
192
|
+
|
|
193
|
+
it "should return a list of attribute names with .attribute_names" do
|
|
194
|
+
(Book.new.attribute_names & ["attribute:author", "attribute:description", "attribute:links", "attribute:title"]).should == ["attribute:author", "attribute:description", "attribute:links", "attribute:title"]
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it "should provide hash-like attribute accessors, i.e. [] and []=" do
|
|
198
|
+
Book.new.should respond_to(:[])
|
|
199
|
+
Book.new.should respond_to(:[]=)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it "should provide attribute accessing with .read_attribute" do
|
|
203
|
+
book = Book.new( :title => "I Am Legend",
|
|
204
|
+
:author => "Richard Matheson",
|
|
205
|
+
:description => "The most clever and riveting vampire novel since Dracula.")
|
|
206
|
+
|
|
207
|
+
book.save.should be_true
|
|
208
|
+
|
|
209
|
+
book.read_attribute("attribute:title").should == "I Am Legend"
|
|
210
|
+
book.read_attribute("attribute:author").should == "Richard Matheson"
|
|
211
|
+
book.read_attribute("attribute:description").should == "The most clever and riveting vampire novel since Dracula."
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "should determine whether an attribute is present with .has_attribute?" do
|
|
215
|
+
book = Book.new
|
|
216
|
+
|
|
217
|
+
["attribute:author", "attribute:description", "attribute:links", "attribute:title"].each do |attr|
|
|
218
|
+
book.has_attribute?(attr).should be_true
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it "should determine whether an attribute is present (i.e. set either by the user or db) with .attribute_present?" do
|
|
223
|
+
book = Book.new
|
|
224
|
+
|
|
225
|
+
# Initially they should all be false
|
|
226
|
+
["attribute:author", "attribute:description", "attribute:title"].each do |attr|
|
|
227
|
+
book.attribute_present?(attr).should be_false
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
book.attributes = { :title => "I Am Legend", :author => "Richard Matheson", :description => "The most clever and riveting vampire novel since Dracula." }
|
|
231
|
+
|
|
232
|
+
["attribute:author", "attribute:description", "attribute:title"].each do |attr|
|
|
233
|
+
book.attribute_present?(attr).should be_true
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it '.update_attribute(nil) should raise an exception' do
|
|
238
|
+
lambda {
|
|
239
|
+
Book.new.update_attribute(nil)
|
|
240
|
+
}.should raise_error(ArgumentError)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it ".update_attribute should update a single attribute of a record" do
|
|
244
|
+
book = Book.new( :title => "I Am Legend",
|
|
245
|
+
:author => "Richard Matheson",
|
|
246
|
+
:description => "The most clever and riveting vampire novel since Dracula.")
|
|
247
|
+
|
|
248
|
+
book.new_record?.should be_true
|
|
249
|
+
book.id.should be_nil
|
|
250
|
+
book.save.should be_true
|
|
251
|
+
|
|
252
|
+
book.update_attribute(:description, "One of the Ten All-Time Best Novels of Vampirism.")
|
|
253
|
+
|
|
254
|
+
book.description.should == "One of the Ten All-Time Best Novels of Vampirism."
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
it ".update_attribute should return false if the attribute could not be updated" do
|
|
258
|
+
book = Book.new( :title => "I Am Legend",
|
|
259
|
+
:author => "Richard Matheson",
|
|
260
|
+
:description => "The most clever and riveting vampire novel since Dracula.")
|
|
261
|
+
|
|
262
|
+
book.new_record?.should be_true
|
|
263
|
+
book.id.should be_nil
|
|
264
|
+
book.save.should be_true
|
|
265
|
+
|
|
266
|
+
book.should_receive(:save).and_return(false)
|
|
267
|
+
book.update_attribute(:description, "One of the Ten All-Time Best Novels of Vampirism.").should be_false
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
describe '' do
|
|
271
|
+
|
|
272
|
+
before(:each) do
|
|
273
|
+
@book = Book.new( :title => "I Am Legend",
|
|
274
|
+
:author => "Richard Matheson",
|
|
275
|
+
:description => "The most clever and riveting vampire novel since Dracula.")
|
|
276
|
+
|
|
277
|
+
@book.new_record?.should be_true
|
|
278
|
+
@book.id.should be_nil
|
|
279
|
+
@book.save.should be_true
|
|
280
|
+
|
|
281
|
+
@new_attributes = {:title => "A Stir of Echoes", :description => "One of the most important writers of the twentieth century."}
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
it ".update_attributes should update all attributes of a record" do
|
|
285
|
+
@book.update_attributes(@new_attributes).should be_true
|
|
286
|
+
|
|
287
|
+
@new_attributes.each do |key, value|
|
|
288
|
+
@book.send(key).should == value
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
it ".update_attributes should return false if the record couldn't be updated with those attributes" do
|
|
293
|
+
@book.should_receive(:save).and_return(false)
|
|
294
|
+
@book.update_attributes(@new_attributes).should be_false
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
it ".update_attributes! should update all attributes of a record" do
|
|
298
|
+
@book.update_attributes(@new_attributes).should be_true
|
|
299
|
+
|
|
300
|
+
@new_attributes.each do |key, value|
|
|
301
|
+
@book.send(key).should == value
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it ".update_attributes! should raise an error when the record couldn't be updated" do
|
|
306
|
+
@book.should_receive(:save!).and_raise(BigRecord::RecordNotSaved)
|
|
307
|
+
|
|
308
|
+
lambda { @book.update_attributes!(@new_attributes) }.should raise_error(BigRecord::RecordNotSaved)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
end
|