Class: Mongoose::Table
Overview
Table class
Class Method Summary collapse
-
.add_column(col_name, col_def, col_class = Column) ⇒ Object
—————————————————————————– Table.add_column —————————————————————————–.
-
.add_indexed_column(col_name, col_def) ⇒ Object
—————————————————————————– Table.add_indexed —————————————————————————–.
-
.apply_options_to_result(result, options) ⇒ Object
—————————————————————————– Table.apply_options_to_result —————————————————————————–.
-
.belongs_to(kind) ⇒ Object
—————————————————————————– Table.belongs_to —————————————————————————–.
-
.close ⇒ Object
—————————————————————————– Table.close —————————————————————————–.
-
.column_names ⇒ Object
—————————————————————————– Table.column_names —————————————————————————–.
-
.columns ⇒ Object
—————————————————————————– Table.columns —————————————————————————–.
-
.content_columns ⇒ Object
—————————————————————————– Table.content_columns —————————————————————————–.
-
.create(options = {}) ⇒ Object
—————————————————————————– Table.create —————————————————————————–.
-
.db ⇒ Object
—————————————————————————– Table.db —————————————————————————–.
-
.db=(db) ⇒ Object
—————————————————————————– Table.db= —————————————————————————–.
-
.delete(id) ⇒ Object
—————————————————————————– Table.delete —————————————————————————–.
-
.delete_all(&block) ⇒ Object
—————————————————————————– Table.delete_all —————————————————————————–.
-
.deleted_recs_counter ⇒ Object
—————————————————————————– Table.deleted_recs_counter —————————————————————————–.
-
.destroy(id) ⇒ Object
—————————————————————————– Table.destroy —————————————————————————–.
-
.destroy_all(&block) ⇒ Object
—————————————————————————– Table.destroy_all —————————————————————————–.
-
.exists?(id) ⇒ Boolean
—————————————————————————– Table.exists? —————————————————————————–.
-
.export(filename = 1) ⇒ Object
—————————————————————————– Table.export —————————————————————————–.
-
.find(*args, &block) ⇒ Object
—————————————————————————– Table.find —————————————————————————–.
-
.find_every(options, &block) ⇒ Object
—————————————————————————– Table.find_every —————————————————————————–.
-
.find_from_block(&block) ⇒ Object
—————————————————————————– Table.find_from_block —————————————————————————–.
-
.find_from_ids(args, options) ⇒ Object
—————————————————————————– Table.find_from_ids —————————————————————————–.
-
.get_all_recs ⇒ Object
—————————————————————————– Table.get_all_recs —————————————————————————–.
-
.get_rec(id) ⇒ Object
—————————————————————————– Table.get_rec —————————————————————————–.
-
.has_many(kind) ⇒ Object
—————————————————————————– Table.has_many —————————————————————————–.
-
.has_one(kind) ⇒ Object
—————————————————————————– Table.has_one —————————————————————————–.
-
.import(filename = 0) ⇒ Object
—————————————————————————– Table.import —————————————————————————–.
-
.init_column(col_name, col_def, col_class) ⇒ Object
—————————————————————————– Table.init_column —————————————————————————–.
-
.init_table ⇒ Object
—————————————————————————– Table.init_table —————————————————————————–.
-
.last_id_used ⇒ Object
—————————————————————————– Table.last_id_used —————————————————————————–.
-
.path ⇒ Object
—————————————————————————– Table.path —————————————————————————–.
-
.plural_form(pluralized) ⇒ Object
—————————————————————————– Table.plural_form —————————————————————————–.
-
.query ⇒ Object
—————————————————————————– Table.query —————————————————————————–.
-
.read_header ⇒ Object
—————————————————————————– Table.read_header —————————————————————————–.
-
.sort_result(result, *order) ⇒ Object
—————————————————————————– Table.sort_result —————————————————————————–.
-
.table_name ⇒ Object
—————————————————————————– Table.table_name —————————————————————————–.
-
.validates_presence_of(*col_names) ⇒ Object
—————————————————————————– Table.validates_presence_of —————————————————————————–.
-
.with_table(access = 'r') ⇒ Object
—————————————————————————– Table.with_table —————————————————————————–.
-
.write_header(header) ⇒ Object
—————————————————————————– Table.write_header —————————————————————————–.
Instance Method Summary collapse
-
#delete ⇒ Object
—————————————————————————– delete —————————————————————————–.
-
#destroy ⇒ Object
—————————————————————————– destroy —————————————————————————–.
-
#initialize(values = nil) ⇒ Table
constructor
—————————————————————————– initialize —————————————————————————–.
-
#save ⇒ Object
—————————————————————————– save —————————————————————————–.
-
#update_attributes(values) ⇒ Object
—————————————————————————– update_attributes —————————————————————————–.
Constructor Details
#initialize(values = nil) ⇒ Table
initialize
577 578 579 580 581 582 583 |
# File 'lib/mongoose/table.rb', line 577 def initialize(values=nil) unless values.nil? values.each do |k,v| send("#{k}=", v) if self.class.column_names.include? k end end end |
Class Method Details
.add_column(col_name, col_def, col_class = Column) ⇒ Object
Table.add_column
232 233 234 235 236 237 238 239 240 241 |
# File 'lib/mongoose/table.rb', line 232 def self.add_column(col_name, col_def, col_class=Column) self.init_column(col_name, col_def, col_class) tbl_header = self.read_header tbl_header[:columns] << { :name => col_name, :data_type => col_def, :class => col_class.to_s } self.write_header(tbl_header) end |
.add_indexed_column(col_name, col_def) ⇒ Object
Table.add_indexed
246 247 248 |
# File 'lib/mongoose/table.rb', line 246 def self.add_indexed_column(col_name, col_def) self.add_column(col_name, col_def, SkipListIndexColumn) end |
.apply_options_to_result(result, options) ⇒ Object
Table.apply_options_to_result
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 |
# File 'lib/mongoose/table.rb', line 404 def self.(result, ) return result if result.empty? result = self.sort_result(result, *[:order]) if .has_key?( :order) result = result[[:offset]-1..-1] if .has_key?(:offset) if .has_key?(:limit) if [:limit] == 1 result = result.first else result = result[0...[:limit]] end end return result end |
.belongs_to(kind) ⇒ Object
Table.belongs_to
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/mongoose/table.rb', line 114 def self.belongs_to(kind) table_name = kind.to_sym class_name = Util.us_case_to_class_case(table_name) define_method(kind) do klass = Object.const_get(class_name.to_s) klass.find(send("#{kind}_id".to_sym)) end define_method("#{kind}=".to_sym) do |other| other.save send("#{kind}_id=".to_sym, other.id.to_i) save end end |
.close ⇒ Object
Table.close
208 209 210 |
# File 'lib/mongoose/table.rb', line 208 def self.close self.columns.each { |c| c.close } end |
.column_names ⇒ Object
Table.column_names
53 54 55 |
# File 'lib/mongoose/table.rb', line 53 def self.column_names self.db.tables[self][:columns].collect { |c| c.name } end |
.columns ⇒ Object
Table.columns
38 39 40 |
# File 'lib/mongoose/table.rb', line 38 def self.columns self.db.tables[self][:columns] end |
.content_columns ⇒ Object
Table.content_columns
45 46 47 48 |
# File 'lib/mongoose/table.rb', line 45 def self.content_columns self.db.tables[self][:columns] = self.columns.reject { |c| c.name == :id || c.name =~ /(_id|_count)$/ } end |
.create(options = {}) ⇒ Object
Table.create
253 254 255 256 257 258 259 260 |
# File 'lib/mongoose/table.rb', line 253 def self.create(={}) rec = new .each do |k,v| rec.send("#{k}=", v) if self.column_names.include? k end rec.save rec end |
.db=(db) ⇒ Object
Table.db=
17 18 19 |
# File 'lib/mongoose/table.rb', line 17 def self.db=(db) @@db = db end |
.delete(id) ⇒ Object
Table.delete
570 571 572 |
# File 'lib/mongoose/table.rb', line 570 def self.delete(id) self.find(id).delete end |
.delete_all(&block) ⇒ Object
Table.delete_all
563 564 565 |
# File 'lib/mongoose/table.rb', line 563 def self.delete_all(&block) self.find(:all, &block).each { |r| p r.delete } end |
.deleted_recs_counter ⇒ Object
Table.deleted_recs_counter
140 141 142 |
# File 'lib/mongoose/table.rb', line 140 def self.deleted_recs_counter self.class.read_header[:deleted_recs_counter] end |
.destroy(id) ⇒ Object
Table.destroy
556 557 558 |
# File 'lib/mongoose/table.rb', line 556 def self.destroy(id) self.find(id).destroy end |
.destroy_all(&block) ⇒ Object
Table.destroy_all
549 550 551 |
# File 'lib/mongoose/table.rb', line 549 def self.destroy_all(&block) self.find(:all, &block).each { |r| p r.destroy } end |
.exists?(id) ⇒ Boolean
Table.exists?
538 539 540 541 542 543 544 |
# File 'lib/mongoose/table.rb', line 538 def self.exists?(id) if self.id[id] true else false end end |
.export(filename = 1) ⇒ Object
Table.export
499 500 501 502 503 504 505 506 507 508 509 510 511 512 |
# File 'lib/mongoose/table.rb', line 499 def self.export(filename=1) if filename.is_a?(Integer) out_file = IO.open(1, 'w') else out_file = File.open(filename, 'w') end CSV::Writer.generate(out_file) do |out| self.find.each do |rec| out << self.column_names.collect {|n| rec.send(n)} end end out_file.close end |
.find(*args, &block) ⇒ Object
Table.find
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/mongoose/table.rb', line 265 def self.find(*args, &block) = {} if args.size == 0 args = [:all] elsif args.first.is_a?(Hash) = args.first args = [:all] elsif args.first.is_a?(Integer) if args.last.is_a?(Hash) = args.last args = args[0...-1] end elsif args.first == :first = args.last if args.last.is_a?(Hash) [:limit] = 1 args = [:all] elsif args.first == :all = args.last if args.last.is_a?(Hash) end case args.first when :all then self.find_every(, &block) else self.find_from_ids(args, ) end end |
.find_every(options, &block) ⇒ Object
Table.find_every
307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/mongoose/table.rb', line 307 def self.find_every(, &block) # If no block was supplied, just grab all the keys from the id column's # index. if block result = self.find_from_block(&block) else result = self.id.keys end return nil if result.nil? return self.( result.collect { |k| self.get_rec(k) }, ) end |
.find_from_block(&block) ⇒ Object
Table.find_from_block
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
# File 'lib/mongoose/table.rb', line 324 def self.find_from_block(&block) result = [] or_result = [] query = Query.new query.find(&block) subquery_no = nil subquery_type = nil # Step through the query block... query.predicates.each do |pred| # Retain the previous subquery_no and subquery_type. This will help # determine if I am still in an #any block or just finished an #any block. previous_subquery_no = subquery_no previous_subquery_type = subquery_type subquery_no = pred.subquery_no subquery_type = pred.subquery_type # If subquery number has not changed, must be in the middle of an #any # block. Therefore, we are going to do a union of the the comparison's # results to the current or_result. if previous_subquery_no == subquery_no or_result = or_result | send(pred.property_name).send(pred.comparison, *pred.arg) # Otherwise, we are starting either a new :and predicate or a new #any # block. else # Therefore, the first thing we want to check if the previous subquery # was an #any block, and add it's result to the overall result array. if previous_subquery_type == :or # If the previous subquery was an #any block and it was the first # subquery in the main query block, initialize the result array # to the whole subqquery's result. if previous_subquery_no == 1 result = or_result # Otherwise, just do an intersection between the or_result and the # overall result. else result = result & or_result end end # If the subquery type is :and, then we are just going to add it # to the existing result. if subquery_type == :and # If this is the first subquery, then we just make the overall # result equal to the comparison's result if subquery_no == 1 result = send(pred.property_name).send(pred.comparison, *pred.arg) # Otherwise, we are going to do an intersection on the # comparison's result and the overall result. else result = result & send(pred.property_name).send(pred.comparison, *pred.arg) end # If the subquery type is :or, and it the subquery number is not # equal to the previous subquery number, then we know we are # at the first predicate of an #any block and we can initialize the # the subquery's result array to whatever the subquery returns. else or_result = send(pred.property_name).send(pred.comparison, *pred.arg) end end end # Now that we are doing executing the whole query, we need to check if # the last subquery was an #any block, so that we can make sure the # results of this subquery get added into the overall query results. if subquery_type == :or if subquery_no == 1 result = or_result else result = result & or_result end end return result end |
.find_from_ids(args, options) ⇒ Object
Table.find_from_ids
294 295 296 297 298 299 300 301 302 |
# File 'lib/mongoose/table.rb', line 294 def self.find_from_ids(args, ) if args.size == 1 result = self.get_rec(args.first) else result = self.(args.collect { |a| self.get_rec(a) }, ) end return result end |
.get_all_recs ⇒ Object
Table.get_all_recs
215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/mongoose/table.rb', line 215 def self.get_all_recs self.with_table do |fptr| begin while true fpos = fptr.tell rec_arr = Marshal.load(fptr) yield rec_arr[1..-1], fpos unless rec_arr[0] end rescue EOFError end end end |
.get_rec(id) ⇒ Object
Table.get_rec
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'lib/mongoose/table.rb', line 463 def self.get_rec(id) fpos = self.id[id] return nil if fpos.nil? rec_arr = [] self.with_table(File::RDONLY) do |fptr| fptr.seek(fpos) rec_arr = Marshal.load(fptr) end raise IndexCorruptError, "Index references deleted record!", caller \ if rec_arr[0] raise IndexCorruptError, "Index ID does not match table ID!", caller \ unless rec_arr[1] == id rec = self.new(Hash[*self.column_names.zip(rec_arr[1..-1]).flatten]) return rec end |
.has_many(kind) ⇒ Object
Table.has_many
84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/mongoose/table.rb', line 84 def self.has_many(kind) table_name = Util.singularize(kind.to_s).to_sym class_name = Util.us_case_to_class_case(table_name) col = Util.col_name_for_class(self.to_s) define_method(kind.to_sym) do klass = Object.const_get(class_name) parent_id = @id Collection.new(self, klass.find { |r| r.send(col) == parent_id }) end end |
.has_one(kind) ⇒ Object
Table.has_one
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/mongoose/table.rb', line 99 def self.has_one(kind) table_name = kind.to_sym class_name = Util.us_case_to_class_case(table_name) col = Util.col_name_for_class(self.to_s) define_method(kind.to_sym) do klass = Object.const_get(class_name) parent_id = @id klass.find(:first) { |r| r.send(col) == parent_id } end end |
.import(filename = 0) ⇒ Object
Table.import
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 |
# File 'lib/mongoose/table.rb', line 517 def self.import(filename=0) if filename.is_a?(Integer) in_file = IO.open(1, 'r') else in_file = File.open(filename, 'r') end CSV::Reader.parse(in_file) do |row| rec = new self.columns.zip(row) do |col, value| rec.send("#{col.name}=", col.convert_to_native(value)) unless \ value.nil? end rec.save end in_file.close end |
.init_column(col_name, col_def, col_class) ⇒ Object
Table.init_column
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/mongoose/table.rb', line 175 def self.init_column(col_name, col_def, col_class) col = col_class.create(self, col_name, col_def) self.columns << col (class << self; self; end).class_eval do define_method(col_name) do self.columns.detect { |c| c.name == col_name.to_sym } end define_method("find_by_#{col_name}".to_sym) do |other| if col_name == :id self.find(other) else self.find(:first) { |tbl| tbl.send(col_name) == other } end end define_method("find_all_by_#{col_name}".to_sym) do |other, *args| self.find(*args) { |tbl| tbl.send(col_name) == other } end end self.class_eval do attr_accessor col_name end col.init_index if col.indexed? end |
.init_table ⇒ Object
Table.init_table
163 164 165 166 167 168 169 170 |
# File 'lib/mongoose/table.rb', line 163 def self.init_table tbl_header = self.read_header self.read_header[:columns].each do |c| self.init_column(c[:name], c[:data_type], Object.full_const_get(c[:class]) ) end end |
.last_id_used ⇒ Object
Table.last_id_used
133 134 135 |
# File 'lib/mongoose/table.rb', line 133 def self.last_id_used self.class.read_header[:last_id_used] end |
.path ⇒ Object
Table.path
60 61 62 |
# File 'lib/mongoose/table.rb', line 60 def self.path self.db.path end |
.plural_form(pluralized) ⇒ Object
Table.plural_form
67 68 69 70 |
# File 'lib/mongoose/table.rb', line 67 def self.plural_form(pluralized) Util::SINGULAR_TO_PLURAL[Util.class_case_to_us_case(self.to_s)] = pluralized Util::PLURAL_TO_SINGULAR[pluralized] = Util.class_case_to_us_case(self.to_s) end |
.query ⇒ Object
Table.query
24 25 26 |
# File 'lib/mongoose/table.rb', line 24 def self.query self.db.tables[self][:query] end |
.read_header ⇒ Object
Table.read_header
147 148 149 150 |
# File 'lib/mongoose/table.rb', line 147 def self.read_header YAML.load(File.open(File.join(self.path, self.table_name.to_s + TBL_HDR_EXT), 'r')) end |
.sort_result(result, *order) ⇒ Object
Table.sort_result
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 |
# File 'lib/mongoose/table.rb', line 424 def self.sort_result(result, *order) sort_cols_arrs = [] order.each do |sort_col| if sort_col.to_s[0..0] == '-' sort_cols_arrs << [sort_col.to_s[1..-1].to_sym, :desc] elsif sort_col.to_s[0..0] == '+' sort_cols_arrs << [sort_col.to_s[1..-1].to_sym, :asc] else sort_cols_arrs << [sort_col, :asc] end end return result.sort do |a,b| x = [] y = [] sort_cols_arrs.each do |s| if [:integer, :float].include?(send(s.first).data_type) a_value = a.send(s.first) || 0 b_value = b.send(s.first) || 0 else a_value = a.send(s.first) b_value = b.send(s.first) end if s.last == :desc x << b_value y << a_value else x << a_value y << b_value end end x <=> y end end |
.table_name ⇒ Object
Table.table_name
31 32 33 |
# File 'lib/mongoose/table.rb', line 31 def self.table_name self.db.tables[self][:table_name] end |
.validates_presence_of(*col_names) ⇒ Object
Table.validates_presence_of
75 76 77 78 79 |
# File 'lib/mongoose/table.rb', line 75 def self.validates_presence_of(*col_names) define_method(:required?) do |col_name| col_names.include?(col_name) end end |
.with_table(access = 'r') ⇒ Object
Table.with_table
487 488 489 490 491 492 493 494 |
# File 'lib/mongoose/table.rb', line 487 def self.with_table(access='r') begin yield fptr = open(File.join(self.db.path, self.table_name.to_s + TBL_EXT), access) ensure fptr.close end end |
.write_header(header) ⇒ Object
Table.write_header
155 156 157 158 |
# File 'lib/mongoose/table.rb', line 155 def self.write_header(header) File.open(File.join(self.path, self.table_name.to_s + TBL_HDR_EXT), 'w' ) { |f| YAML.dump(header, f) } end |
Instance Method Details
#destroy ⇒ Object
destroy
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 |
# File 'lib/mongoose/table.rb', line 628 def destroy fpos_rec_start = self.class.id[@id] self.class.with_table(File::RDWR) do |fptr| fptr.seek(fpos_rec_start) rec = Marshal.load(fptr) raise IndexCorruptError, "Index ID does not match table ID!", caller \ unless rec[1] == @id # First array position of record is the deleted flag: true means deleted rec[0] = true # Record is not actually deleted; it just has its deleted flag set to # true. write_record(fptr, fpos_rec_start, Marshal.dump(rec)) increment_deleted_recs_counter end # Remove all index recs pointing to this record. self.class.columns.each_with_index do |c,i| if i == 0 c.remove_index_rec(@id) elsif c.indexed? c.remove_index_rec(send(c.name), @id) end end # Don't allow any more changes to this record. freeze end |
#save ⇒ Object
save
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 |
# File 'lib/mongoose/table.rb', line 598 def save self.class.columns.each do |c| # First checks to see if validates_presence_of was set in class def. raise "Value required for #{c.name}!" if respond_to?('required?') and \ required?(c.name) and send(c.name).nil? # Next checks to see if validates_presence_of was set in #add_column. raise "Value required for #{c.name}!" if c.required? and send(c.name).nil? end # Add new record. if @id.nil? @id = append_record(self.class.column_names[1..-1].collect { |c_name| send(c_name) }) # Update existing record. else update_record(@id, self.class.columns[1..-1].collect { |c| send(c.name) }) end return true end |
#update_attributes(values) ⇒ Object
update_attributes
588 589 590 591 592 593 |
# File 'lib/mongoose/table.rb', line 588 def update_attributes(values) values.each do |k,v| send("#{k}=", v) if self.class.column_names.include? k end save end |