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
data/spec/lib/company.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class Company < BigRecord::Base
|
|
2
|
+
|
|
3
|
+
column 'attribute:name', 'string'
|
|
4
|
+
column 'attribute:address', 'string'
|
|
5
|
+
column 'attribute:employees', 'integer'
|
|
6
|
+
column 'attribute:readonly', 'string'
|
|
7
|
+
|
|
8
|
+
column 'log:change', 'string', :alias => 'change_log', :collection => true
|
|
9
|
+
|
|
10
|
+
attr_create_accessible :name
|
|
11
|
+
attr_protected :employees
|
|
12
|
+
attr_readonly :readonly
|
|
13
|
+
|
|
14
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class Employee < BigRecord::Base
|
|
2
|
+
|
|
3
|
+
column 'attribute:first_name', :string
|
|
4
|
+
column 'attribute:middle_name', :string
|
|
5
|
+
column 'attribute:last_name', :string
|
|
6
|
+
column 'attribute:email', :string
|
|
7
|
+
column 'attribute:title', :string
|
|
8
|
+
column 'attribute:company_id', :string
|
|
9
|
+
column 'attribute:password', :string
|
|
10
|
+
column 'attribute:gender', :string # it's not discrimination
|
|
11
|
+
column 'attribute:age', :integer
|
|
12
|
+
|
|
13
|
+
validates_presence_of :first_name, :last_name
|
|
14
|
+
validates_length_of :first_name, :last_name, :within => 2..50
|
|
15
|
+
validates_length_of :middle_name, :within => 1..50, :allow_nil => true
|
|
16
|
+
validates_format_of :first_name, :last_name, :with => /^[\w-]/
|
|
17
|
+
validates_format_of :middle_name, :with => /^[\w-]/, :allow_nil => true
|
|
18
|
+
#validates_uniqueness_of :name
|
|
19
|
+
validates_exclusion_of :first_name, :last_name, :in => %w( admin superuser )
|
|
20
|
+
validates_exclusion_of :middle_name, :in => %w( admin superuser ), :allow_nil => true
|
|
21
|
+
|
|
22
|
+
validates_presence_of :email
|
|
23
|
+
|
|
24
|
+
validates_inclusion_of :gender, :in => %w( m f )
|
|
25
|
+
|
|
26
|
+
validates_confirmation_of :password
|
|
27
|
+
|
|
28
|
+
validates_acceptance_of :contract
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
belongs_to_big_record :company, :foreign_key => :company_id
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class AddBooksTable < BigRecord::Migration
|
|
2
|
+
|
|
3
|
+
def self.up
|
|
4
|
+
create_table :books, :force => true do |t|
|
|
5
|
+
t.family :attribute, :versions => 100
|
|
6
|
+
t.family :family2
|
|
7
|
+
t.family :log, :versions => 100
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.down
|
|
12
|
+
drop_table :books
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class AddCompaniesTable < BigRecord::Migration
|
|
2
|
+
|
|
3
|
+
def self.up
|
|
4
|
+
create_table :companies, :force => true do |t|
|
|
5
|
+
t.family :attribute, :versions => 100
|
|
6
|
+
t.family :log, :versions => 100
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.down
|
|
11
|
+
drop_table :companies
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
data/spec/lib/novel.rb
ADDED
data/spec/lib/zoo.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class Zoo < BigRecord::Base
|
|
2
|
+
|
|
3
|
+
set_default_family :attr
|
|
4
|
+
|
|
5
|
+
column 'attr:name', 'string'
|
|
6
|
+
column 'attr:address', 'string'
|
|
7
|
+
column 'attr:employees', 'integer'
|
|
8
|
+
column 'attr:readonly', 'string'
|
|
9
|
+
column :description, :string
|
|
10
|
+
column 'attr:weblink', 'Embedded::WebLink', :alias => "weblink"
|
|
11
|
+
column 'attr:animal_ids', :string, :collection => true
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
attr_accessible :name, :address, :description
|
|
15
|
+
|
|
16
|
+
belongs_to_many :animals, :foreign_key => 'attr:animal_ids'
|
|
17
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
|
|
4
|
+
gem 'rspec', '~>1.2'
|
|
5
|
+
require 'spec'
|
|
6
|
+
|
|
7
|
+
SPEC_ROOT = Pathname(__FILE__).dirname.expand_path
|
|
8
|
+
require SPEC_ROOT.parent + 'lib/big_record'
|
|
9
|
+
|
|
10
|
+
BigRecord::Base.configurations = YAML::load(File.open(File.join(File.dirname(__FILE__), "connections", "bigrecord.yml")))
|
|
11
|
+
BigRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
|
|
12
|
+
|
|
13
|
+
begin
|
|
14
|
+
require 'connection'
|
|
15
|
+
rescue LoadError
|
|
16
|
+
BigRecord::Base.logger.info "No data store defined. Using Hbase..."
|
|
17
|
+
require File.join(File.dirname(__FILE__), 'connections', 'hbase', 'connection')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Load the various helpers for the spec suite
|
|
21
|
+
Dir.glob( File.join(File.dirname(__FILE__), "lib", "**", "*.rb") ).each do |model|
|
|
22
|
+
require model
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Redefine the Hash class to include two helper methods used only in the specs.
|
|
27
|
+
class Hash
|
|
28
|
+
# Helper method to determine if a hash is completely contained within other_hash (order is not important).
|
|
29
|
+
# Matches each key/value pair, and returns false as soon as a mismatch occurs. The other_hash might have
|
|
30
|
+
# more pairs, but those aren't considered.
|
|
31
|
+
#
|
|
32
|
+
# hash1 = { :key1 => "value1", :key2 => "value2", :key3 => "value3" }
|
|
33
|
+
#
|
|
34
|
+
# hash2 = { :key1 => "value1", :key2 => "value2", :key3 => "value3", :key4 => "value4" }
|
|
35
|
+
#
|
|
36
|
+
# hash3 = { :key1 => "value4", :key2 => "value3", :key3 => "value1", :key4 => "value2" }
|
|
37
|
+
#
|
|
38
|
+
# hash1.subset_of?(hash2) # => true
|
|
39
|
+
# hash2.subset_of?(hash1) # => false
|
|
40
|
+
# hash3.subset_of?(hash1) # => false
|
|
41
|
+
# hash3.subset_of?(hash2) # => false
|
|
42
|
+
#
|
|
43
|
+
def subset_of?(other_hash)
|
|
44
|
+
self.each_pair do |key, value|
|
|
45
|
+
return false if !other_hash.has_key?(key) || !(other_hash[key] == value)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def superset_of?(other_hash)
|
|
52
|
+
other_hash.subset_of?(self)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Defined as a shared spec because embedded_spec uses it as well
|
|
2
|
+
describe "BigRecord::AbstractBase", :shared => true do
|
|
3
|
+
|
|
4
|
+
it "should provide #primary_key" do
|
|
5
|
+
Book.should respond_to(:primary_key)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe '#columns' do
|
|
9
|
+
|
|
10
|
+
before(:all) do
|
|
11
|
+
# Grab the columns from a simple BigRecord model
|
|
12
|
+
@columns = Book.columns
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'should return a hash of Column objects describing the columns in the model' do
|
|
16
|
+
# Verify that each entry is a Column object
|
|
17
|
+
@columns.each do |column|
|
|
18
|
+
column.should be_a_kind_of(BigRecord::ConnectionAdapters::Column)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Map the names of each of the columns
|
|
22
|
+
column_names = @columns.map{ |column| column.name }
|
|
23
|
+
|
|
24
|
+
# Verify that each attribute we defined in the Book model is present
|
|
25
|
+
expected_names = %w( attribute:title attribute:author attribute:description family2: log:change )
|
|
26
|
+
(column_names & expected_names).sort.should == expected_names.sort
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'should save a default alias name for each column (e.g. attribute:name become alias name automatically)' do
|
|
30
|
+
lookup = { 'attribute:id' => 'id',
|
|
31
|
+
'attribute:title' => 'title',
|
|
32
|
+
'attribute:author' => 'author',
|
|
33
|
+
'attribute:description' => 'description'}
|
|
34
|
+
|
|
35
|
+
# Go through each column and if an attribute name is found that matches the lookup table above,
|
|
36
|
+
# verify that the alias name it creates is the one we expect.
|
|
37
|
+
@columns.each do |column|
|
|
38
|
+
if lookup.has_key?(column.name)
|
|
39
|
+
column.alias.should == lookup[column.name]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe 'column families' do
|
|
47
|
+
|
|
48
|
+
it 'should respond to #default_family with a default value, or with the value defined in the model' do
|
|
49
|
+
Book.should respond_to(:default_family)
|
|
50
|
+
Book.default_family.should == "attribute"
|
|
51
|
+
|
|
52
|
+
Zoo.should respond_to(:default_family)
|
|
53
|
+
Zoo.default_family.should == "attr"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it 'should automatically append the #default_family to columns without one defined' do
|
|
57
|
+
Zoo.columns.map{|column| column.name}.should include("attr:description")
|
|
58
|
+
Zoo.new.should respond_to(:description)
|
|
59
|
+
Zoo.new.should respond_to(:description=)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe '.attributes' do
|
|
65
|
+
|
|
66
|
+
before(:each) do
|
|
67
|
+
@book = Book.new
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'should have getter and setter methods for the attributes from the alias of their names' do
|
|
71
|
+
# Check that the getters are responding
|
|
72
|
+
@book.should respond_to(:title)
|
|
73
|
+
@book.should respond_to(:author)
|
|
74
|
+
@book.should respond_to(:description)
|
|
75
|
+
|
|
76
|
+
# Check that the setters are responding
|
|
77
|
+
@book.should respond_to(:title=)
|
|
78
|
+
@book.should respond_to(:author=)
|
|
79
|
+
@book.should respond_to(:description=)
|
|
80
|
+
|
|
81
|
+
# Now we use the setters
|
|
82
|
+
@book.title = "The Beach"
|
|
83
|
+
@book.author = "Alex Garland"
|
|
84
|
+
@book.description = "A furiously intelligent first novel." # this was written on the cover
|
|
85
|
+
|
|
86
|
+
# And we check that the getters are working
|
|
87
|
+
@book.title.should == "The Beach"
|
|
88
|
+
@book.author.should == "Alex Garland"
|
|
89
|
+
@book.description.should == "A furiously intelligent first novel."
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'should provide a list of modified attributes with #modified_attributes' do
|
|
93
|
+
pending "This was deprecated"
|
|
94
|
+
|
|
95
|
+
book = Book.new( :title => "The Beach",
|
|
96
|
+
:author => "Alex Garland",
|
|
97
|
+
:description => "A furiously intelligent first novel.")
|
|
98
|
+
|
|
99
|
+
book.modified_attributes.each_pair do |key, value|
|
|
100
|
+
%w( title author description ).include?(key.to_s).should be_true
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'should return a hash of attribute-names and values' do
|
|
105
|
+
# Set some attributes, and verify that they get stored in the model
|
|
106
|
+
@book.title = "The Beach"
|
|
107
|
+
@book.author = "Alex Garland"
|
|
108
|
+
@book.description = "A furiously intelligent first novel."
|
|
109
|
+
|
|
110
|
+
expected_hash = {"log:change"=>[], "attribute:description"=>"A furiously intelligent first novel.", "attribute:title"=>"The Beach", "attribute:links"=>[], "attribute:author"=>"Alex Garland"}
|
|
111
|
+
|
|
112
|
+
@book.attributes.superset_of?(expected_hash).should be_true
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "should return a hash with all nil or empty list values if the instance is new and has no default values" do
|
|
116
|
+
@book.attributes.superset_of?({"log:change"=>[], "attribute:description"=>nil, "attribute:title"=>nil, "attribute:links"=>[], "attribute:author"=>nil}).should be_true
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe ".attributes=" do
|
|
122
|
+
|
|
123
|
+
it 'should be able to mass assign attributes' do
|
|
124
|
+
# Check that the mass asssignment of attributes works with #new
|
|
125
|
+
@book = Book.new( :title => "The Beach",
|
|
126
|
+
:author => "Alex Garland",
|
|
127
|
+
:description => "A furiously intelligent first novel.")
|
|
128
|
+
|
|
129
|
+
@book.attributes.superset_of?({"log:change"=>[], "attribute:description"=>"A furiously intelligent first novel.", "attribute:title"=>"The Beach", "attribute:links"=>[], "attribute:author"=>"Alex Garland"}).should be_true
|
|
130
|
+
|
|
131
|
+
# Check that it works with the #attributes= method
|
|
132
|
+
@book.attributes = {:title => "28 Days Later"}
|
|
133
|
+
|
|
134
|
+
@book.attributes.superset_of?({"log:change"=>[], "attribute:description"=>"A furiously intelligent first novel.", "attribute:title"=>"28 Days Later", "attribute:links"=>[], "attribute:author"=>"Alex Garland"}).should be_true
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe "protected attributes" do
|
|
140
|
+
|
|
141
|
+
it 'should respond to the method #protected_attributes' do
|
|
142
|
+
Company.should respond_to(:protected_attributes)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it 'should list #protected_attributes' do
|
|
146
|
+
Company.protected_attributes.should be_a_kind_of(Set)
|
|
147
|
+
Company.protected_attributes.should include("employees")
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'should be handled properly' do
|
|
151
|
+
# Employees is a protected attribute here, so it shouldn't be saved.
|
|
152
|
+
@company = Company.new(:name => "The Company", :address => "Unknown", :employees => 18000, :readonly => "secret")
|
|
153
|
+
|
|
154
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>"secret", "log:change"=>[], "attribute:name"=>"The Company"}).should be_true
|
|
155
|
+
|
|
156
|
+
# Check it against the attributes= method
|
|
157
|
+
@company.attributes = {:employees => 18000}
|
|
158
|
+
|
|
159
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>"secret", "log:change"=>[], "attribute:name"=>"The Company"}).should be_true
|
|
160
|
+
|
|
161
|
+
# Now check that we can access it with the employees= method
|
|
162
|
+
@company.employees = 18000
|
|
163
|
+
|
|
164
|
+
@company.attributes.superset_of?({"attribute:employees"=>18000, "attribute:address"=>"Unknown", "attribute:readonly"=>"secret", "log:change"=>[], "attribute:name"=>"The Company"}).should be_true
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
describe "accessible attributes" do
|
|
170
|
+
|
|
171
|
+
it 'should respond to the method #accessible_attributes' do
|
|
172
|
+
Zoo.should respond_to(:accessible_attributes)
|
|
173
|
+
Zoo.accessible_attributes.should_not be_empty
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it 'should list #accessible_attributes' do
|
|
177
|
+
Zoo.accessible_attributes.should be_a_kind_of(Set)
|
|
178
|
+
Zoo.accessible_attributes.should include("address")
|
|
179
|
+
Zoo.accessible_attributes.should include("description")
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'should be handled properly' do
|
|
183
|
+
# name, address, and description are accessible attributes here
|
|
184
|
+
attributes_hash = { :name => "San Francisco",
|
|
185
|
+
:address => "Some Address",
|
|
186
|
+
:description => "This is a pretty awesome zoo",
|
|
187
|
+
:employees => 10000,
|
|
188
|
+
:readonly => "should not work" }
|
|
189
|
+
|
|
190
|
+
zoo = Zoo.new(attributes_hash)
|
|
191
|
+
|
|
192
|
+
zoo.attributes.superset_of?({"attr:readonly"=>nil, "attr:address"=>"Some Address", "attr:description"=>"This is a pretty awesome zoo", "attr:employees"=>nil, "attr:name"=>"San Francisco"}).should be_true
|
|
193
|
+
|
|
194
|
+
zoo.attributes = {:address => "1 Zoo Rd", :description => "Awesome address", :employees => 1000}
|
|
195
|
+
|
|
196
|
+
zoo.attributes.superset_of?({"attr:readonly"=>nil, "attr:address"=>"1 Zoo Rd", "attr:description"=>"Awesome address", "attr:employees"=>nil, "attr:name"=>"San Francisco"}).should be_true
|
|
197
|
+
|
|
198
|
+
zoo.employees = 1000
|
|
199
|
+
|
|
200
|
+
zoo.attributes.superset_of?({"attr:readonly"=>nil, "attr:address"=>"1 Zoo Rd", "attr:description"=>"Awesome address", "attr:employees"=>1000, "attr:name"=>"San Francisco"})
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
describe "readonly attributes" do
|
|
206
|
+
|
|
207
|
+
it 'should respond to the method #readonly_attributes' do
|
|
208
|
+
Company.should respond_to(:readonly_attributes)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'should list #readonly_attributes' do
|
|
212
|
+
Company.readonly_attributes.should be_a_kind_of(Set)
|
|
213
|
+
Company.readonly_attributes.should include("readonly")
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it 'should be handled properly' do
|
|
217
|
+
pending "this still needs to be implemented in BigRecord::AbstractBase"
|
|
218
|
+
|
|
219
|
+
# readonly is the readonly attribute here
|
|
220
|
+
@company = Company.new(:name => "The Company", :address => "Unknown", :readonly => "secret")
|
|
221
|
+
|
|
222
|
+
# It should've been set successfully since this is a new record
|
|
223
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>"secret", "log:change"=>[], "attribute:name"=>"The Company"}).should be_true
|
|
224
|
+
|
|
225
|
+
# It should still also be accessible with the attributes= method
|
|
226
|
+
@company.attributes = {:readonly => "another secret"}
|
|
227
|
+
|
|
228
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>"another secret", "log:change"=>[], "attribute:name"=>"The Company"}).should be_true
|
|
229
|
+
|
|
230
|
+
# Now when we save it, it should no longer be accessible with mass assignment
|
|
231
|
+
|
|
232
|
+
# Mock new_record? so it's essentially acting like it was saved.
|
|
233
|
+
@company.stub!(:new_record?).and_return(false)
|
|
234
|
+
|
|
235
|
+
@company.attributes = {:readonly => "compromised secret"}
|
|
236
|
+
|
|
237
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>"another secret", "log:change"=>[], "attribute:name"=>"The Company"}).should be_true
|
|
238
|
+
|
|
239
|
+
# And it should still not be accessible with the explicit setter
|
|
240
|
+
@company.readonly = "compromised secret"
|
|
241
|
+
|
|
242
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>"another secret", "log:change"=>[], "attribute:name"=>"Another Company"}).should be_true
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
describe "create_accessible attributes" do
|
|
248
|
+
|
|
249
|
+
it 'should respond to the method #create_accessible_attributes' do
|
|
250
|
+
Company.should respond_to(:create_accessible_attributes)
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
it 'should list #create_accessible_attributes' do
|
|
254
|
+
Company.create_accessible_attributes.should be_a_kind_of(Set)
|
|
255
|
+
Company.create_accessible_attributes.should include("name")
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it 'should be handled properly' do
|
|
259
|
+
# Name is the create_accessible attribute here
|
|
260
|
+
@company = Company.new(:name => "Another Company", :address => "Unknown")
|
|
261
|
+
|
|
262
|
+
# It should've been set successfully since this is a new record
|
|
263
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>nil, "log:change"=>[], "attribute:name"=>"Another Company"}).should be_true
|
|
264
|
+
|
|
265
|
+
# It should still also be accessible with the attributes= method
|
|
266
|
+
@company.attributes = {:name => "The Company"}
|
|
267
|
+
|
|
268
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>nil, "log:change"=>[], "attribute:name"=>"The Company"}).should be_true
|
|
269
|
+
|
|
270
|
+
# Now when we save it, it should no longer be accessible with mass assignment
|
|
271
|
+
|
|
272
|
+
# Mock new_record? so it's essentially acting like it was saved.
|
|
273
|
+
@company.stub!(:new_record?).and_return(false)
|
|
274
|
+
|
|
275
|
+
@company.attributes = {:name => "Another Company"}
|
|
276
|
+
|
|
277
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>nil, "log:change"=>[], "attribute:name"=>"The Company"}).should be_true
|
|
278
|
+
|
|
279
|
+
# But it should still be accessible with the explicit setter
|
|
280
|
+
@company.name = "Another Company"
|
|
281
|
+
|
|
282
|
+
@company.attributes.superset_of?({"attribute:employees"=>nil, "attribute:address"=>"Unknown", "attribute:readonly"=>nil, "log:change"=>[], "attribute:name"=>"Another Company"}).should be_true
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'adapter_shared_spec'))
|
|
3
|
+
|
|
4
|
+
describe BigRecord::ConnectionAdapters::AbstractAdapter do
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
@adapter = BigRecord::ConnectionAdapters::AbstractAdapter.new("")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it_should_behave_like 'a BigRecord Adapter'
|
|
11
|
+
|
|
12
|
+
it "should raise NotImplementedError when #update_raw is called" do
|
|
13
|
+
lambda{ @adapter.update_raw(:table_name, :row, :values, :timestamp) }.should raise_error(NotImplementedError)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should raise NotImplementedError when #update is called" do
|
|
17
|
+
lambda{ @adapter.update(:table_name, :row, :values, :timestamp) }.should raise_error(NotImplementedError)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should raise NotImplementedError when #get_raw is called" do
|
|
21
|
+
lambda{ @adapter.get_raw(:table_name, :row, :column, :options) }.should raise_error(NotImplementedError)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should raise NotImplementedError when #get is called" do
|
|
25
|
+
lambda{ @adapter.get(:table_name, :row, :column, :options) }.should raise_error(NotImplementedError)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should raise NotImplementedError when #get_columns_raw is called" do
|
|
29
|
+
lambda{ @adapter.get_columns_raw(:table_name, :row, :columns, :options) }.should raise_error(NotImplementedError)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should raise NotImplementedError when #get_columns is called" do
|
|
33
|
+
lambda{ @adapter.get_columns(:table_name, :row, :columns, :options) }.should raise_error(NotImplementedError)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should raise NotImplementedError when #delete is called" do
|
|
37
|
+
lambda{ @adapter.delete(:table_name, :row) }.should raise_error(NotImplementedError)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should raise NotImplementedError when #delete_all is called" do
|
|
41
|
+
lambda{ @adapter.delete_all(:table_name) }.should raise_error(NotImplementedError)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should raise NotImplementedError when #table_exists? is called" do
|
|
45
|
+
lambda{ @adapter.table_exists?(:table_name) }.should raise_error(NotImplementedError)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should raise NotImplementedError when #create_table is called" do
|
|
49
|
+
lambda{ @adapter.create_table(:table_name, :column_families) }.should raise_error(NotImplementedError)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should raise NotImplementedError when #drop_table is called" do
|
|
53
|
+
lambda{ @adapter.drop_table(:table_name) }.should raise_error(NotImplementedError)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
describe "a BigRecord Adapter", :shared => true do
|
|
2
|
+
|
|
3
|
+
%w{adapter_name supports_migrations?}.each do |meth|
|
|
4
|
+
it "should have a ##{meth} method" do
|
|
5
|
+
@adapter.should respond_to(meth.intern)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe "with connection management" do
|
|
10
|
+
%w{active? reconnect! disconnect!}.each do |meth|
|
|
11
|
+
it "should have a ##{meth} method" do
|
|
12
|
+
@adapter.should respond_to(meth.intern)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe "with data store statements" do
|
|
18
|
+
%w{update_raw update get_raw get get_columns_raw get_columns get_consecutive_rows_raw get_consecutive_rows delete delete_all}.each do |meth|
|
|
19
|
+
it "should have a ##{meth} method" do
|
|
20
|
+
@adapter.should respond_to(meth.intern)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe "with schema statements" do
|
|
26
|
+
%w{table_exists? create_table drop_table}.each do |meth|
|
|
27
|
+
it "should have a ##{meth} method" do
|
|
28
|
+
@adapter.should respond_to(meth.intern)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should have the methods needed for migrations if supports_migrations? is true" do
|
|
33
|
+
if @adapter.supports_migrations?
|
|
34
|
+
%w{initialize_schema_migrations_table get_all_schema_versions add_column_family remove_column_family modify_column_family}.each do |meth|
|
|
35
|
+
@adapter.should respond_to(meth.intern)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "timestamp functionality" do
|
|
42
|
+
it "should use the default Time.to_bigrecord_timestamp or implement it's own method" do
|
|
43
|
+
Time.now.should respond_to(:to_bigrecord_timestamp)
|
|
44
|
+
Time.should respond_to(:from_bigrecord_timestamp)
|
|
45
|
+
|
|
46
|
+
Time.now.to_bigrecord_timestamp.should_not be_nil
|
|
47
|
+
Time.from_bigrecord_timestamp(Time.now.to_bigrecord_timestamp).should_not be_nil
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'adapter_shared_spec'))
|
|
3
|
+
|
|
4
|
+
describe BigRecord::ConnectionAdapters::HbaseAdapter do
|
|
5
|
+
|
|
6
|
+
before do
|
|
7
|
+
# Make sure the connection is defined in spec/connections/bigrecord.yml
|
|
8
|
+
BigRecord::Base.establish_connection 'hbase'
|
|
9
|
+
|
|
10
|
+
@adapter = BigRecord::Base.connection
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it_should_behave_like 'a BigRecord Adapter'
|
|
14
|
+
|
|
15
|
+
end
|