bigrecord 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +5 -4
- data/VERSION +1 -1
- data/lib/big_record/abstract_base.rb +21 -14
- data/lib/big_record/base.rb +38 -30
- data/lib/big_record/br_associations.rb +100 -773
- data/lib/big_record/br_reflection.rb +1 -3
- data/lib/big_record/connection_adapters/abstract/database_statements.rb +1 -161
- data/lib/big_record/connection_adapters/abstract_adapter.rb +1 -17
- data/lib/big_record/connection_adapters/column.rb +1 -30
- data/lib/big_record/connection_adapters/hbase_adapter.rb +18 -16
- data/lib/big_record/connection_adapters/hbase_rest_adapter.rb +64 -61
- data/lib/big_record/dynamic_schema.rb +14 -0
- data/lib/big_record/embedded_associations/association_proxy.rb +0 -6
- data/lib/big_record/timestamp.rb +28 -2
- data/lib/big_record.rb +1 -4
- data/lib/bigrecord.rb +1 -1
- data/spec/connections/bigrecord.yml +2 -2
- data/spec/debug.log +215 -172
- data/spec/unit/ar_associations_spec.rb +0 -7
- data/spec/unit/{abstract_base_spec.rb → attributes_spec.rb} +20 -3
- data/spec/unit/callback_spec.rb +1 -0
- data/spec/unit/{base_spec.rb → columns_spec.rb} +2 -2
- data/spec/unit/embedded_spec.rb +1 -1
- data/spec/unit/find_spec.rb +10 -0
- data/spec/unit/model_spec.rb +13 -4
- data/spec/unit/scanner_spec.rb +44 -0
- data/tasks/gem.rb +0 -1
- data/tasks/rdoc.rb +1 -1
- metadata +6 -14
data/README.rdoc
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
A Ruby Object/Data Mapper for distributed column-oriented data stores (inspired by BigTable) such as HBase. Intended to work as a drop-in for Rails applications.
|
4
4
|
|
5
5
|
== Features
|
6
|
-
* Dynamic schemas (due to the schema-less design of BigTable).
|
6
|
+
* {BigRecord::DynamicSchema Dynamic schemas} (due to the schema-less design of BigTable).
|
7
7
|
* Support for column-oriented data stores.
|
8
8
|
* Similar usage to Active Record.
|
9
|
-
* Embedded records that store within a single table row.
|
9
|
+
* {BigRecord::Embedded Embedded records} that store within a single table row.
|
10
10
|
* Automatic versioning.
|
11
11
|
* Scalability (depending on the data store used).
|
12
12
|
|
@@ -31,11 +31,11 @@ Beyond this though, there are two basic motivations that almost immediately dema
|
|
31
31
|
|
32
32
|
== Getting Started
|
33
33
|
|
34
|
-
Check out the guides/getting_started.rdoc file for more information.
|
34
|
+
Check out the {file:guides/getting_started.rdoc guides/getting_started.rdoc} file for more information.
|
35
35
|
|
36
36
|
== Deployment
|
37
37
|
|
38
|
-
Refer to guides/deployment.rdoc for more information.
|
38
|
+
Refer to {file:guides/deployment.rdoc guides/deployment.rdoc} for more information.
|
39
39
|
|
40
40
|
== Documentation
|
41
41
|
|
@@ -48,5 +48,6 @@ Big Record is released under the MIT license.
|
|
48
48
|
== Links
|
49
49
|
|
50
50
|
* Contact Us
|
51
|
+
* Google Group - http://groups.google.com/group/bigrecord
|
51
52
|
* Website - http://www.bigrecord.org
|
52
53
|
* IRC Channel - <tt>#bigrecord</tt> on irc.freenode.net
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.9
|
@@ -367,14 +367,14 @@ module BigRecord
|
|
367
367
|
write_attribute(self.class.primary_key, value)
|
368
368
|
end
|
369
369
|
|
370
|
-
# Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't
|
371
|
-
# yet exist in the data store.
|
370
|
+
# Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet.
|
372
371
|
def new_record?
|
373
372
|
false
|
374
373
|
end
|
375
374
|
|
376
|
-
#
|
377
|
-
# *
|
375
|
+
# Method that saves the BigRecord object into the database. It will do one of two things:
|
376
|
+
# * If no record currently exists: Creates a new record with values matching those of the object attributes.
|
377
|
+
# * If a record already exist: Updates the record with values matching those of the object attributes.
|
378
378
|
def save
|
379
379
|
raise NotImplemented
|
380
380
|
end
|
@@ -435,6 +435,7 @@ module BigRecord
|
|
435
435
|
end
|
436
436
|
|
437
437
|
protected
|
438
|
+
|
438
439
|
def clone_in_persistence_format
|
439
440
|
validate_attributes_schema
|
440
441
|
|
@@ -682,6 +683,7 @@ module BigRecord
|
|
682
683
|
end
|
683
684
|
|
684
685
|
protected
|
686
|
+
|
685
687
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
|
686
688
|
# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
|
687
689
|
def read_attribute(attr_name)
|
@@ -701,7 +703,8 @@ module BigRecord
|
|
701
703
|
@attributes[attr_name.to_s]
|
702
704
|
end
|
703
705
|
|
704
|
-
private
|
706
|
+
private
|
707
|
+
|
705
708
|
# Called on first read access to any given column and generates reader
|
706
709
|
# methods for all columns in the columns_hash if
|
707
710
|
# BigRecord::Base.generate_read_methods is set to true.
|
@@ -778,6 +781,7 @@ private
|
|
778
781
|
end
|
779
782
|
|
780
783
|
public
|
784
|
+
|
781
785
|
class << self
|
782
786
|
|
783
787
|
# Evaluate the name of the column of the primary key only once
|
@@ -884,7 +888,8 @@ private
|
|
884
888
|
# adds the new column into the model's column hash.
|
885
889
|
#
|
886
890
|
# @param type [Symbol, String] Column type as defined in the source of {ConnectionAdapters::Column#klass}
|
887
|
-
# @
|
891
|
+
# @param [Hash] options The options to define the column with.
|
892
|
+
# @option options [TrueClass,FalseClass] :collection Whether this column is a collection.
|
888
893
|
# @option options [String] :alias Define an alias for the column that cannot be inferred. By default, 'attribute:name' will be aliased to 'name'.
|
889
894
|
# @option options [String] :default Default value to set for this column.
|
890
895
|
#
|
@@ -918,7 +923,7 @@ private
|
|
918
923
|
end
|
919
924
|
|
920
925
|
# Contains the names of the generated reader methods.
|
921
|
-
def read_methods
|
926
|
+
def read_methods
|
922
927
|
@read_methods ||= Set.new
|
923
928
|
end
|
924
929
|
|
@@ -1045,7 +1050,15 @@ private
|
|
1045
1050
|
read_inheritable_attribute(:attr_create_accessible)
|
1046
1051
|
end
|
1047
1052
|
|
1053
|
+
# Guesses the table name, but does not decorate it with prefix and suffix information.
|
1054
|
+
def undecorated_table_name(class_name = base_class.name)
|
1055
|
+
table_name = Inflector.underscore(Inflector.demodulize(class_name))
|
1056
|
+
table_name = Inflector.pluralize(table_name) if pluralize_table_names
|
1057
|
+
table_name
|
1058
|
+
end
|
1059
|
+
|
1048
1060
|
protected
|
1061
|
+
|
1049
1062
|
def invalidate_views
|
1050
1063
|
@views = nil
|
1051
1064
|
@view_names = nil
|
@@ -1081,16 +1094,10 @@ private
|
|
1081
1094
|
type_name.constantize
|
1082
1095
|
end
|
1083
1096
|
|
1084
|
-
public
|
1085
|
-
# Guesses the table name, but does not decorate it with prefix and suffix information.
|
1086
|
-
def undecorated_table_name(class_name = base_class.name)
|
1087
|
-
table_name = Inflector.underscore(Inflector.demodulize(class_name))
|
1088
|
-
table_name = Inflector.pluralize(table_name) if pluralize_table_names
|
1089
|
-
table_name
|
1090
|
-
end
|
1091
1097
|
end
|
1092
1098
|
|
1093
1099
|
protected
|
1100
|
+
|
1094
1101
|
# Handle *? for method_missing.
|
1095
1102
|
def attribute?(attribute_name)
|
1096
1103
|
query_attribute(attribute_name)
|
data/lib/big_record/base.rb
CHANGED
@@ -12,8 +12,10 @@ module BigRecord
|
|
12
12
|
super
|
13
13
|
end
|
14
14
|
|
15
|
+
public
|
16
|
+
|
15
17
|
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
|
16
|
-
# attributes but not yet saved (pass a hash with key names matching the associated
|
18
|
+
# attributes but not yet saved (pass a hash with key names matching the associated column names).
|
17
19
|
# In both instances, valid attribute keys are determined by the column names of the associated table --
|
18
20
|
# hence you can't have attributes that aren't part of the table columns.
|
19
21
|
def initialize(attrs = nil)
|
@@ -24,7 +26,6 @@ module BigRecord
|
|
24
26
|
|
25
27
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
|
26
28
|
# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
|
27
|
-
# (Alias for the protected read_attribute method).
|
28
29
|
def [](attr_name)
|
29
30
|
if attr_name.ends_with?(":")
|
30
31
|
read_family_attributes(attr_name)
|
@@ -80,7 +81,7 @@ module BigRecord
|
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
83
|
-
# Read an attribute that defines a column family.
|
84
|
+
# Read an attribute that defines a column family, as opposed to a column qualifier.
|
84
85
|
def read_family_attributes(attr_name)
|
85
86
|
attr_name = attr_name.to_s
|
86
87
|
column = column_for_attribute(attr_name)
|
@@ -130,24 +131,14 @@ module BigRecord
|
|
130
131
|
end
|
131
132
|
end
|
132
133
|
|
133
|
-
def set_loaded(name)
|
134
|
-
@loaded_columns ||= []
|
135
|
-
@loaded_columns << name
|
136
|
-
end
|
137
|
-
|
138
|
-
def is_loaded?(name)
|
139
|
-
@loaded_columns ||= []
|
140
|
-
@loaded_columns.include?(name)
|
141
|
-
end
|
142
|
-
|
143
|
-
public
|
144
134
|
# Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet.
|
145
135
|
def new_record?
|
146
136
|
@new_record
|
147
137
|
end
|
148
138
|
|
149
|
-
#
|
150
|
-
# *
|
139
|
+
# Method that saves the BigRecord object into the database. It will do one of two things:
|
140
|
+
# * If no record currently exists: Creates a new record with values matching those of the object attributes.
|
141
|
+
# * If a record already exist: Updates the record with values matching those of the object attributes.
|
151
142
|
def save
|
152
143
|
create_or_update
|
153
144
|
end
|
@@ -158,8 +149,7 @@ module BigRecord
|
|
158
149
|
create_or_update || raise(RecordNotSaved)
|
159
150
|
end
|
160
151
|
|
161
|
-
# Deletes the record in the database
|
162
|
-
# be made (since they can't be persisted).
|
152
|
+
# Deletes the record in the database.
|
163
153
|
def destroy
|
164
154
|
unless new_record?
|
165
155
|
connection.delete(self.class.table_name, self.id)
|
@@ -197,6 +187,16 @@ module BigRecord
|
|
197
187
|
|
198
188
|
protected
|
199
189
|
|
190
|
+
def set_loaded(name)
|
191
|
+
@loaded_columns ||= []
|
192
|
+
@loaded_columns << name
|
193
|
+
end
|
194
|
+
|
195
|
+
def is_loaded?(name)
|
196
|
+
@loaded_columns ||= []
|
197
|
+
@loaded_columns.include?(name)
|
198
|
+
end
|
199
|
+
|
200
200
|
# Invoke {#create} if {#new_record} returns true, otherwise it's an {#update}
|
201
201
|
def create_or_update
|
202
202
|
raise ReadOnlyRecord if readonly?
|
@@ -218,8 +218,8 @@ module BigRecord
|
|
218
218
|
update_bigrecord
|
219
219
|
end
|
220
220
|
|
221
|
-
# Update this record in
|
222
|
-
# therefore weird
|
221
|
+
# Update this record in the database. Cannot be directly in the method 'update' because it would trigger callbacks and
|
222
|
+
# therefore weird behavior.
|
223
223
|
def update_bigrecord
|
224
224
|
timestamp = self.respond_to?(:updated_at) ? self.updated_at.to_bigrecord_timestamp : Time.now.to_bigrecord_timestamp
|
225
225
|
|
@@ -229,6 +229,7 @@ module BigRecord
|
|
229
229
|
end
|
230
230
|
|
231
231
|
public
|
232
|
+
|
232
233
|
class << self
|
233
234
|
|
234
235
|
# Return the name of the primary key. Defaults to "id".
|
@@ -299,6 +300,16 @@ module BigRecord
|
|
299
300
|
end
|
300
301
|
end
|
301
302
|
|
303
|
+
# Returns all records for the model by invoking find(:all)
|
304
|
+
def all
|
305
|
+
find(:all)
|
306
|
+
end
|
307
|
+
|
308
|
+
# Returns the first record for the model by invoke find(:first)
|
309
|
+
def first
|
310
|
+
find(:first)
|
311
|
+
end
|
312
|
+
|
302
313
|
# Returns true if the given +id+ represents the primary key of a record in the database, false otherwise.
|
303
314
|
def exists?(id)
|
304
315
|
!find(id).nil?
|
@@ -387,10 +398,16 @@ module BigRecord
|
|
387
398
|
connection.truncate_table(table_name)
|
388
399
|
end
|
389
400
|
|
401
|
+
# Returns the inflected table name as it's called in your database.
|
390
402
|
def table_name
|
391
403
|
(superclass == BigRecord::Base) ? @table_name : superclass.table_name
|
392
404
|
end
|
393
405
|
|
406
|
+
# If you want to avoid the table name inflection, you can define the name
|
407
|
+
# explicitly with this method.
|
408
|
+
#
|
409
|
+
# @example
|
410
|
+
# set_table_name :table_xyz
|
394
411
|
def set_table_name(name)
|
395
412
|
@table_name = name.to_s
|
396
413
|
end
|
@@ -519,6 +536,7 @@ module BigRecord
|
|
519
536
|
end
|
520
537
|
|
521
538
|
protected
|
539
|
+
|
522
540
|
def invalidate_views
|
523
541
|
@views = nil
|
524
542
|
@view_names = nil
|
@@ -614,16 +632,6 @@ module BigRecord
|
|
614
632
|
end
|
615
633
|
end
|
616
634
|
|
617
|
-
def find_all_by_id(ids, options={})
|
618
|
-
ids.inject([]) do |result, id|
|
619
|
-
begin
|
620
|
-
result << find_one(id, options)
|
621
|
-
rescue BigRecord::RecordNotFound => e
|
622
|
-
end
|
623
|
-
result
|
624
|
-
end
|
625
|
-
end
|
626
|
-
|
627
635
|
# Add the missing cells to the raw record and set them to nil. We know that it's
|
628
636
|
# nil because else we would have received those cells. That way, when the value of
|
629
637
|
# one of these cells will be requested by the client we won't try to lazy load it.
|