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,148 @@
|
|
|
1
|
+
module BigRecord
|
|
2
|
+
module EmbeddedAssociations
|
|
3
|
+
class AssociationProxy #:nodoc:
|
|
4
|
+
instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_)/ }
|
|
5
|
+
|
|
6
|
+
# def initialize(owner, reflection)
|
|
7
|
+
# @owner, @reflection = owner, reflection
|
|
8
|
+
# Array(reflection.options[:extend]).each { |ext| proxy_extend(ext) }
|
|
9
|
+
# reset
|
|
10
|
+
# end
|
|
11
|
+
|
|
12
|
+
def find(id)
|
|
13
|
+
@target.select{|s| s.id == id}.first
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Remove +records+ from this association. Does not destroy +records+.
|
|
17
|
+
def delete(*records)
|
|
18
|
+
records = flatten_deeper(records)
|
|
19
|
+
#records.each { |record| raise_on_type_mismatch(record) }
|
|
20
|
+
records.reject! { |record| @target.delete(record)}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def proxy_owner
|
|
24
|
+
@owner
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def proxy_reflection
|
|
28
|
+
@reflection
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def proxy_target
|
|
32
|
+
@target
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def respond_to?(symbol, include_priv = false)
|
|
36
|
+
proxy_respond_to?(symbol, include_priv) || (load_target && @target.respond_to?(symbol, include_priv))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Explicitly proxy === because the instance method removal above
|
|
40
|
+
# doesn't catch it.
|
|
41
|
+
def ===(other)
|
|
42
|
+
load_target
|
|
43
|
+
other === @target
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def aliased_table_name
|
|
47
|
+
@reflection.klass.table_name
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def reset
|
|
51
|
+
@loaded = false
|
|
52
|
+
@target = nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def reload
|
|
56
|
+
reset
|
|
57
|
+
load_target
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def loaded?
|
|
61
|
+
@loaded
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def loaded
|
|
65
|
+
@loaded = true
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def target
|
|
69
|
+
@target
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def target=(target)
|
|
73
|
+
@target = target
|
|
74
|
+
loaded
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
protected
|
|
78
|
+
def dependent?
|
|
79
|
+
@reflection.options[:dependent] || false
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def quoted_record_ids(records)
|
|
83
|
+
records.map { |record| record.quoted_id }.join(',')
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def extract_options_from_args!(args)
|
|
87
|
+
@owner.send(:extract_options_from_args!, args)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def set_belongs_to_association_for(record)
|
|
91
|
+
if @reflection.options[:as]
|
|
92
|
+
record["#{@reflection.options[:as]}_id"] = @owner.id unless @owner.new_record?
|
|
93
|
+
record["#{@reflection.options[:as]}_type"] = @owner.class.base_class.name.to_s
|
|
94
|
+
else
|
|
95
|
+
record[@reflection.primary_key_name] = @owner.id unless @owner.new_record?
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def merge_options_from_reflection!(options)
|
|
100
|
+
options.reverse_merge!(
|
|
101
|
+
:group => @reflection.options[:group],
|
|
102
|
+
:limit => @reflection.options[:limit],
|
|
103
|
+
:offset => @reflection.options[:offset],
|
|
104
|
+
:joins => @reflection.options[:joins],
|
|
105
|
+
:include => @reflection.options[:include],
|
|
106
|
+
:select => @reflection.options[:select]
|
|
107
|
+
)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
def method_missing(method, *args, &block)
|
|
112
|
+
if load_target
|
|
113
|
+
@target.send(method, *args, &block)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def load_target
|
|
118
|
+
return nil unless defined?(@loaded)
|
|
119
|
+
|
|
120
|
+
if !loaded? and (!@owner.new_record? || foreign_key_present)
|
|
121
|
+
@target = find_target
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
@loaded = true
|
|
125
|
+
@target
|
|
126
|
+
rescue BigRecord::RecordNotFound
|
|
127
|
+
reset
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Can be overwritten by associations that might have the foreign key available for an association without
|
|
131
|
+
# having the object itself (and still being a new record). Currently, only belongs_to present this scenario.
|
|
132
|
+
def foreign_key_present
|
|
133
|
+
false
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def raise_on_type_mismatch(record)
|
|
137
|
+
unless record.is_a?(@reflection.klass)
|
|
138
|
+
raise BigRecord::AssociationTypeMismatch, "#{@reflection.class_name} expected, got #{record.class}"
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Array#flatten has problems with recursive arrays. Going one level deeper solves the majority of the problems.
|
|
143
|
+
def flatten_deeper(array)
|
|
144
|
+
array.collect { |element| element.respond_to?(:flatten) ? element.flatten : element }.flatten
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Replace the anonymous classes
|
|
2
|
+
module BigRecord
|
|
3
|
+
module FamilySpanColumns
|
|
4
|
+
|
|
5
|
+
def self.included(base) #:nodoc:
|
|
6
|
+
super
|
|
7
|
+
base.alias_method_chain :column_for_attribute, :family_span_columns
|
|
8
|
+
base.alias_method_chain :attributes_from_column_definition, :family_span_columns
|
|
9
|
+
|
|
10
|
+
base.extend(ClassMethods)
|
|
11
|
+
base.class_eval do
|
|
12
|
+
class << self
|
|
13
|
+
alias_method_chain :alias_attribute, :family_span_columns
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module ClassMethods
|
|
19
|
+
|
|
20
|
+
# Returns the list of columns that are not spanned on a whole family
|
|
21
|
+
def simple_columns
|
|
22
|
+
columns.select{|c|!c.family?}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Returns the list of columns that are spanned on a whole family
|
|
26
|
+
def family_columns
|
|
27
|
+
columns.select{|c|c.family?}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Define aliases to the fully qualified attributes
|
|
31
|
+
def alias_attribute_with_family_span_columns(alias_name, fully_qualified_name)
|
|
32
|
+
# when it's a single column everything's normal but when it's a
|
|
33
|
+
# column family then this actually add accessors for the whole family
|
|
34
|
+
alias_attribute_without_family_span_columns(alias_name, fully_qualified_name)
|
|
35
|
+
|
|
36
|
+
# fully_qualified_name ends with ':' => consider it a family span column
|
|
37
|
+
if fully_qualified_name.ends_with?(":")
|
|
38
|
+
# add the accessors for the individual columns
|
|
39
|
+
self.class_eval <<-EOF
|
|
40
|
+
def #{alias_name}(column_key=nil)
|
|
41
|
+
if column_key
|
|
42
|
+
read_attribute("#{fully_qualified_name}\#{column_key}")
|
|
43
|
+
else
|
|
44
|
+
read_family_attributes("#{fully_qualified_name}")
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
def set_#{alias_name}(column_key, value)
|
|
48
|
+
write_attribute("#{fully_qualified_name}\#{column_key}", value)
|
|
49
|
+
end
|
|
50
|
+
EOF
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Returns the list of columns that are not spanned on a whole family
|
|
56
|
+
def simple_columns
|
|
57
|
+
columns.select{|c|!c.family?}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Returns the column object for the named attribute.
|
|
61
|
+
def column_for_attribute_with_family_span_columns(name)
|
|
62
|
+
name = name.to_s
|
|
63
|
+
|
|
64
|
+
# ignore methods '=' and '?' (e.g. 'normalized_srf_ief:231=')
|
|
65
|
+
return if name =~ /=|\?$/
|
|
66
|
+
|
|
67
|
+
column = self.columns_hash[name]
|
|
68
|
+
unless column
|
|
69
|
+
family = BigRecord::ConnectionAdapters::Column.extract_family(name)
|
|
70
|
+
column = self.columns_hash[family] if family
|
|
71
|
+
end
|
|
72
|
+
column
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Initializes the attributes array with keys matching the columns from the linked table and
|
|
76
|
+
# the values matching the corresponding default value of that column, so
|
|
77
|
+
# that a new instance, or one populated from a passed-in Hash, still has all the attributes
|
|
78
|
+
# that instances loaded from the database would.
|
|
79
|
+
def attributes_from_column_definition_with_family_span_columns
|
|
80
|
+
self.simple_columns.inject({}) do |attributes, column|
|
|
81
|
+
unless column.name == self.class.primary_key or column.family?
|
|
82
|
+
attributes[column.name] = column.default
|
|
83
|
+
end
|
|
84
|
+
attributes
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
end
|
|
89
|
+
end
|