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.
Files changed (104) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +44 -0
  3. data/Rakefile +17 -0
  4. data/VERSION +1 -0
  5. data/doc/bigrecord_specs.rdoc +36 -0
  6. data/doc/getting_started.rdoc +157 -0
  7. data/examples/bigrecord.yml +25 -0
  8. data/generators/bigrecord/bigrecord_generator.rb +17 -0
  9. data/generators/bigrecord/templates/bigrecord.rake +47 -0
  10. data/generators/bigrecord_migration/bigrecord_migration_generator.rb +13 -0
  11. data/generators/bigrecord_migration/templates/migration.rb +9 -0
  12. data/generators/bigrecord_model/bigrecord_model_generator.rb +28 -0
  13. data/generators/bigrecord_model/templates/migration.rb +13 -0
  14. data/generators/bigrecord_model/templates/model.rb +7 -0
  15. data/generators/bigrecord_model/templates/model_spec.rb +12 -0
  16. data/init.rb +9 -0
  17. data/install.rb +22 -0
  18. data/lib/big_record/abstract_base.rb +1088 -0
  19. data/lib/big_record/action_view_extensions.rb +266 -0
  20. data/lib/big_record/ar_associations/association_collection.rb +194 -0
  21. data/lib/big_record/ar_associations/association_proxy.rb +158 -0
  22. data/lib/big_record/ar_associations/belongs_to_association.rb +57 -0
  23. data/lib/big_record/ar_associations/belongs_to_many_association.rb +57 -0
  24. data/lib/big_record/ar_associations/has_and_belongs_to_many_association.rb +164 -0
  25. data/lib/big_record/ar_associations/has_many_association.rb +191 -0
  26. data/lib/big_record/ar_associations/has_one_association.rb +80 -0
  27. data/lib/big_record/ar_associations.rb +1608 -0
  28. data/lib/big_record/ar_reflection.rb +223 -0
  29. data/lib/big_record/attribute_methods.rb +75 -0
  30. data/lib/big_record/base.rb +618 -0
  31. data/lib/big_record/br_associations/association_collection.rb +194 -0
  32. data/lib/big_record/br_associations/association_proxy.rb +153 -0
  33. data/lib/big_record/br_associations/belongs_to_association.rb +52 -0
  34. data/lib/big_record/br_associations/belongs_to_many_association.rb +293 -0
  35. data/lib/big_record/br_associations/cached_item_proxy.rb +194 -0
  36. data/lib/big_record/br_associations/cached_item_proxy_factory.rb +62 -0
  37. data/lib/big_record/br_associations/has_and_belongs_to_many_association.rb +168 -0
  38. data/lib/big_record/br_associations/has_one_association.rb +80 -0
  39. data/lib/big_record/br_associations.rb +978 -0
  40. data/lib/big_record/br_reflection.rb +151 -0
  41. data/lib/big_record/callbacks.rb +367 -0
  42. data/lib/big_record/connection_adapters/abstract/connection_specification.rb +279 -0
  43. data/lib/big_record/connection_adapters/abstract/database_statements.rb +175 -0
  44. data/lib/big_record/connection_adapters/abstract/quoting.rb +58 -0
  45. data/lib/big_record/connection_adapters/abstract_adapter.rb +190 -0
  46. data/lib/big_record/connection_adapters/column.rb +491 -0
  47. data/lib/big_record/connection_adapters/hbase_adapter.rb +432 -0
  48. data/lib/big_record/connection_adapters/view.rb +27 -0
  49. data/lib/big_record/connection_adapters.rb +10 -0
  50. data/lib/big_record/deletion.rb +73 -0
  51. data/lib/big_record/dynamic_schema.rb +92 -0
  52. data/lib/big_record/embedded.rb +71 -0
  53. data/lib/big_record/embedded_associations/association_proxy.rb +148 -0
  54. data/lib/big_record/family_span_columns.rb +89 -0
  55. data/lib/big_record/fixtures.rb +1025 -0
  56. data/lib/big_record/migration.rb +380 -0
  57. data/lib/big_record/routing_ext.rb +65 -0
  58. data/lib/big_record/timestamp.rb +51 -0
  59. data/lib/big_record/validations.rb +830 -0
  60. data/lib/big_record.rb +125 -0
  61. data/lib/bigrecord.rb +1 -0
  62. data/rails/init.rb +9 -0
  63. data/spec/connections/bigrecord.yml +13 -0
  64. data/spec/connections/cassandra/connection.rb +2 -0
  65. data/spec/connections/hbase/connection.rb +2 -0
  66. data/spec/debug.log +281 -0
  67. data/spec/integration/br_associations_spec.rb +80 -0
  68. data/spec/lib/animal.rb +12 -0
  69. data/spec/lib/book.rb +10 -0
  70. data/spec/lib/broken_migrations/duplicate_name/20090706182535_add_animals_table.rb +14 -0
  71. data/spec/lib/broken_migrations/duplicate_name/20090706193019_add_animals_table.rb +9 -0
  72. data/spec/lib/broken_migrations/duplicate_version/20090706190623_add_books_table.rb +9 -0
  73. data/spec/lib/broken_migrations/duplicate_version/20090706190623_add_companies_table.rb +9 -0
  74. data/spec/lib/company.rb +14 -0
  75. data/spec/lib/embedded/web_link.rb +12 -0
  76. data/spec/lib/employee.rb +33 -0
  77. data/spec/lib/migrations/20090706182535_add_animals_table.rb +13 -0
  78. data/spec/lib/migrations/20090706190623_add_books_table.rb +15 -0
  79. data/spec/lib/migrations/20090706193019_add_companies_table.rb +14 -0
  80. data/spec/lib/migrations/20090706194512_add_employees_table.rb +13 -0
  81. data/spec/lib/migrations/20090706195741_add_zoos_table.rb +13 -0
  82. data/spec/lib/novel.rb +5 -0
  83. data/spec/lib/zoo.rb +17 -0
  84. data/spec/spec.opts +4 -0
  85. data/spec/spec_helper.rb +55 -0
  86. data/spec/unit/abstract_base_spec.rb +287 -0
  87. data/spec/unit/adapters/abstract_adapter_spec.rb +56 -0
  88. data/spec/unit/adapters/adapter_shared_spec.rb +51 -0
  89. data/spec/unit/adapters/hbase_adapter_spec.rb +15 -0
  90. data/spec/unit/ar_associations_spec.rb +8 -0
  91. data/spec/unit/base_spec.rb +6 -0
  92. data/spec/unit/br_associations_spec.rb +58 -0
  93. data/spec/unit/embedded_spec.rb +43 -0
  94. data/spec/unit/find_spec.rb +34 -0
  95. data/spec/unit/hash_helper_spec.rb +44 -0
  96. data/spec/unit/migration_spec.rb +144 -0
  97. data/spec/unit/model_spec.rb +315 -0
  98. data/spec/unit/validations_spec.rb +182 -0
  99. data/tasks/bigrecord_tasks.rake +47 -0
  100. data/tasks/data_store.rb +46 -0
  101. data/tasks/gem.rb +22 -0
  102. data/tasks/rdoc.rb +8 -0
  103. data/tasks/spec.rb +34 -0
  104. 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