class BigRecord::Base

Constants

VALID_FIND_OPTIONS

Attributes

modified_attributes[RW]

Public Class Methods

base_class() click to toggle source

@return [Class] The base class which inherits BigRecord::Base directly.

# File lib/big_record/base.rb, line 413
def base_class
  (superclass == BigRecord::Base) ? self : superclass.base_class
end
clear_active_connections!() click to toggle source

Clears the cache which maps classes to connections.

# File lib/big_record/connection_adapters/abstract/connection_specification.rb, line 84
def clear_active_connections!
  clear_cache!(@@active_connections) do |name, conn|
    conn.disconnect!
  end
end
clear_reloadable_connections!() click to toggle source

Clears the cache which maps classes

# File lib/big_record/connection_adapters/abstract/connection_specification.rb, line 91
def clear_reloadable_connections!
  @@active_connections.each do |name, conn|
    if conn.requires_reloading?
      conn.disconnect!
      @@active_connections.delete(name)
    end
  end
end
columns_to_find(options={}) click to toggle source

Return the list of fully qualified column names, i.e. [“family:qualifier”].

Returns the column names based on the options argument in order of :columns,then :view, i.e. disregards :view if :columns is defined.

@option options [Array<String, Symbol>] :columns List of fully qualified column names or column aliases. @option options [String, Symbol] :view The name of the view as defined with {view}.

# File lib/big_record/base.rb, line 484
def columns_to_find(options={})
  c =
    if options[:columns]
      column_list = []
      options[:columns].each do |column_name|
        # If the column name provided is a full name, i.e. includes column family and qualifier,
        # then add it to the list.
        if column_name.to_s =~ /:/
          column_list << column_name

        # Otherwise, it's probably an alias and we need to check that.
        else
          columns.select{|column| column_list << column.name if column.alias == column_name.to_s}
        end
      end
      column_list
    elsif options[:view]
      raise ArgumentError, "Unknown view: #{options[:view]}" unless views_hash[options[:view]]
      if options[:view] == :all
        ["#{default_family}:"]
      else
        views_hash[options[:view]].column_names
      end
    elsif views_hash[:default]
      views_hash[:default].column_names
    else
      ["#{default_family}:"]
    end
  c += [options[:include]] if options[:include]
  c.flatten.reject{|x| x == "id"}
end
connected?() click to toggle source

Returns true if a connection that's accessible to this class have already been opened.

# File lib/big_record/connection_adapters/abstract/connection_specification.rb, line 239
def self.connected?
  active_connections[active_connection_name] ? true : false
end
connection() click to toggle source

Returns the connection currently associated with the class. This can also be used to “borrow” the connection to do database work unrelated to any of the specific Active Records.

# File lib/big_record/connection_adapters/abstract/connection_specification.rb, line 73
def connection
  if @active_connection_name && (conn = active_connections[@active_connection_name])
    conn
  else
    # retrieve_connection sets the cache key.
    conn = retrieve_connection
    active_connections[@active_connection_name] = conn
  end
end
create(attrs = nil) click to toggle source

Creates an object, instantly saves it as a record (if the validation permits it), and returns it. If the save fails under validations, the unsaved object is still returned.

# File lib/big_record/base.rb, line 310
def create(attrs = nil)
  if attrs.is_a?(Array)
    attrs.collect { |attr| create(attr) }
  else
    object = new(attrs)
    object.save
    object
  end
end
default_column_prefix() click to toggle source
# File lib/big_record/base.rb, line 468
def default_column_prefix
  "#{default_family}:"
end
default_columns() click to toggle source

Default columns to create with the model, such as primary key.

# File lib/big_record/base.rb, line 464
def default_columns
  {primary_key => ConnectionAdapters::Column.new(primary_key, 'string')}
end
default_family() click to toggle source

Get the default column family used to store attributes that have no column family set explicitly.

Defaults to “attribute”

# File lib/big_record/base.rb, line 400
def default_family
  @default_family ||= "attribute"
end
default_views() click to toggle source

Return the hash of default views which consist of all columns and the :default named views.

# File lib/big_record/base.rb, line 473
def default_views
  {:all=>ConnectionAdapters::View.new('all', nil, self), :default=>ConnectionAdapters::View.new('default', nil, self)}
end
delete(id) click to toggle source

Deletes the record with the given id without instantiating an object first. If an array of ids is provided, all of them are deleted.

# File lib/big_record/base.rb, line 345
def delete(id)
  if id.is_a?(Array)
    id.each { |a| connection.delete(table_name, a) }
  else
    connection.delete(table_name, id)
  end
end
delete_all(conditions = nil) click to toggle source

Deletes all the records that match the condition without instantiating the objects first (and hence not calling the destroy method). Example:

Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')"

@todo take into consideration the conditions

# File lib/big_record/base.rb, line 378
def delete_all(conditions = nil)
  connection.get_consecutive_rows(table_name, nil, nil, ["#{default_family}:"]).each do |row|
    connection.delete(table_name, row["id"])
  end
end
destroy(id) click to toggle source

Destroys the record with the given id by instantiating the object and calling destroy (all the callbacks are the triggered). If an array of ids is provided, all of them are destroyed.

# File lib/big_record/base.rb, line 355
def destroy(id)
  id.is_a?(Array) ? id.each { |a| destroy(a) } : find(id).destroy
end
destroy_all(conditions = nil) click to toggle source

Destroys the objects for all the records that match the condition by instantiating each object and calling the destroy method. Example:

Person.destroy_all "last_login < '2004-04-04'"
# File lib/big_record/base.rb, line 369
def destroy_all(conditions = nil)
  find(:all, :conditions => conditions).each { |object| object.destroy }
end
establish_connection(spec = nil) click to toggle source

Establishes the connection to the database. Accepts a hash as input where the :adapter key must be specified with the name of a database adapter (in lower-case) example for regular databases (MySQL, Postgresql, etc):

ActiveRecord::Base.establish_connection(
  :adapter  => "mysql",
  :host     => "localhost",
  :username => "myuser",
  :password => "mypass",
  :database => "somedatabase"
)

Example for SQLite database:

ActiveRecord::Base.establish_connection(
  :adapter => "sqlite",
  :database  => "path/to/dbfile"
)

Also accepts keys as strings (for parsing from yaml for example):

ActiveRecord::Base.establish_connection(
  "adapter" => "sqlite",
  "database"  => "path/to/dbfile"
)

The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError may be returned on an error.

# File lib/big_record/connection_adapters/abstract/connection_specification.rb, line 191
def self.establish_connection(spec = nil)
  case spec
    when nil
      raise AdapterNotSpecified unless defined? RAILS_ENV
      establish_connection(RAILS_ENV)
    when ConnectionSpecification
      clear_active_connection_name
      @active_connection_name = name
      @@defined_connections[name] = spec
    when Symbol, String
      if configuration = configurations[spec.to_s]
        establish_connection(configuration)
      else
        raise AdapterNotSpecified, "#{spec} database is not configured"
      end
    else
      spec = spec.symbolize_keys
      unless spec.key?(:adapter) then raise AdapterNotSpecified, "database configuration does not specify adapter" end
      adapter_method = "#{spec[:adapter]}_connection"
      unless respond_to?(adapter_method) then raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter" end
      remove_connection
      establish_connection(ConnectionSpecification.new(spec, adapter_method))
  end
end
exists?(id) click to toggle source

Returns true if the given id represents the primary key of a record in the database, false otherwise.

# File lib/big_record/base.rb, line 302
def exists?(id)
  !find(id).nil?
rescue BigRecord::BigRecordError
  false
end
families() click to toggle source

Return the list of families for this class

# File lib/big_record/base.rb, line 239
def families
  columns.collect(&:family).uniq
end
find(*args) click to toggle source
# File lib/big_record/base.rb, line 283
def find(*args)
  options = extract_options_from_args!(args)
  validate_find_options(options)

  # set a default view
  if options[:view]
    options[:view] = options[:view].to_sym
  else
    options[:view] = :default
  end

  case args.first
    when :first then find_every(options.merge({:limit => 1})).first
    when :all   then find_every(options)
    else             find_from_ids(args, options)
  end
end
hbase_connection(config) click to toggle source

Establishes a connection to the database that's used by all Active Record objects.

# File lib/big_record/connection_adapters/hbase_adapter.rb, line 7
def self.hbase_connection(config)
  begin
    require 'big_record_driver'
  rescue LoadError => e
    puts "[BigRecord] bigrecord-driver is needed for HbaseAdapter. Install it with: gem install bigrecord-driver"
    raise e
  end

  config = config.symbolize_keys

  zookeeper_host          = config[:zookeeper_host]
  zookeeper_client_port   = config[:zookeeper_client_port]
  drb_host                = config[:drb_host]
  drb_port                = config[:drb_port]

  hbase = BigRecord::Driver::Client.new(config)

  ConnectionAdapters::HbaseAdapter.new(hbase, logger, [zookeeper_host, zookeeper_client_port], config)
end
new(attrs = nil) click to toggle source

New objects can be instantiated as either empty (pass no construction parameter) or pre-set with attributes but not yet saved (pass a hash with key names matching the associated table column names). In both instances, valid attribute keys are determined by the column names of the associated table – hence you can't have attributes that aren't part of the table columns.

Calls superclass method
# File lib/big_record/base.rb, line 18
def initialize(attrs = nil)
  @new_record = true
  super
  attrs.keys.each{ |k| set_loaded(k) } if attrs
end
primary_key() click to toggle source

Return the name of the primary key. Defaults to “id”.

# File lib/big_record/base.rb, line 234
def primary_key
  @primary_key ||= "id"
end
remove_connection(klass=self) click to toggle source

Remove the connection for this class. This will close the active connection and the defined connection (if they exist). The result can be used as argument for ::establish_connection, for easy re-establishing of the connection.

# File lib/big_record/connection_adapters/abstract/connection_specification.rb, line 247
def self.remove_connection(klass=self)
  spec = @@defined_connections[klass.name]
  konn = active_connections[klass.name]
  @@defined_connections.delete_if { |key, value| value == spec }
  active_connections.delete_if { |key, value| value == konn }
  konn.disconnect! if konn
  spec.config if spec
end
scan(options={}, &code) click to toggle source

HBase scanner utility – scans the table and executes code on each record

@example

Entity.scan(:batch_size => 200) {|e|puts "#{e.name} is a child!" if e.parent}

@option options [Integer] :batch_size - number of records to retrieve from database with each scan iteration. @option options [Block] :code - the code to execute (see example above for syntax)

# File lib/big_record/base.rb, line 251
def scan(options={}, &code)
  options = options.dup
  limit = options.delete(:batch_size) || 100

  items_processed = 0

  # add an extra record for defining the next offset without duplicating records
  limit += 1
  last_row_id = nil

  while true
    items = find(:all, options.merge({:limit => limit}))

    # set the new offset as the extra record
    unless items.empty?
      items.delete_at(0) if items[0].id == last_row_id

      break if items.empty?

      last_row_id = items.last.id
      options[:offset] = last_row_id
      items_processed += items.size

      items.each do |item|
        code.call(item)
      end
    else
      break
    end
  end
end
set_default_family(name) click to toggle source

Set the default column family used to store attributes that have no column family set explicitly.

@example

set_default_family :attr  # instead of using :attribute as the default.
# File lib/big_record/base.rb, line 408
def set_default_family(name)
  @default_family = name.to_s
end
set_table_name(name) click to toggle source
# File lib/big_record/base.rb, line 393
def set_table_name(name)
  @table_name = name.to_s
end
table_name() click to toggle source
# File lib/big_record/base.rb, line 389
def table_name
  @table_name || superclass.table_name
end
truncate() click to toggle source

Truncate the table for this model

# File lib/big_record/base.rb, line 385
def truncate
  connection.truncate_table(table_name)
end
update(id, attributes) click to toggle source

Finds the record from the passed id, instantly saves it with the passed attributes (if the validation permits it), and returns it. If the save fails under validations, the unsaved object is still returned.

The arguments may also be given as arrays in which case the update method is called for each pair of id and attributes and an array of objects is returned.

@example of updating one record:

Person.update(15, {:user_name => 'Samuel', :group => 'expert'})

@example of updating multiple records:

people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy"} }
Person.update(people.keys, people.values)
# File lib/big_record/base.rb, line 332
def update(id, attributes)
  if id.is_a?(Array)
    idx = -1
    id.collect { |a| idx += 1; update(a, attributes[idx]) }
  else
    object = find(id)
    object.update_attributes(attributes)
    object
  end
end
update_all(updates, conditions = nil) click to toggle source

Updates all records with the SET-part of an SQL update statement in updates and returns an integer with the number of rows updated. A subset of the records can be selected by specifying conditions. Example:

Billing.update_all "category = 'authorized', approved = 1", "author = 'David'"
# File lib/big_record/base.rb, line 362
def update_all(updates, conditions = nil)
  raise NotImplemented, "update_all"
end
view(name, *columns) click to toggle source

Macro for defining a named view to a list of columns.

@param [String, Symbol] name Give it an arbitrary name. @param [Array<String, Symbol>] columns List of columns to associate to this view. Can use column aliases or fully qualified names.

@example

view :front_page, :name, :title, :description
view :summary, ["attribute:name", "attribute:title"]
# File lib/big_record/base.rb, line 425
def view(name, *columns)
  name = name.to_sym
  @views_hash ||= default_views

  # The other variables that are cached and depend on @views_hash need to be reloaded
  invalidate_views

  @views_hash[name] = ConnectionAdapters::View.new(name, columns.flatten, self)
end
view_names() click to toggle source

Get a list of view names defined by {view}.

# File lib/big_record/base.rb, line 441
def view_names
  @view_names ||= views_hash.keys
end
views() click to toggle source

Get a list of all the views defined by the {view} macro for the model.

# File lib/big_record/base.rb, line 436
def views
  @views ||= views_hash.values
end
views_hash() click to toggle source

Get the full hash of views consisting of the name as keys, and the {ConnectionAdapters::View} views.

# File lib/big_record/base.rb, line 446
def views_hash
  unless @all_views_hash
    # add default hbase columns
    @all_views_hash =
      if self == BigRecord::Base # stop at Base
         @views_hash = default_views
      else
        if @views_hash
          superclass.views_hash.merge(default_views).merge(@views_hash)
        else
          superclass.views_hash.merge(default_views)
        end
      end
  end
  @all_views_hash
end

Protected Class Methods

add_missing_cells(raw_record, requested_columns) click to toggle source

Add the missing cells to the raw record and set them to nil. We know that it's nil because else we would have received those cells. That way, when the value of one of these cells will be requested by the client we won't try to lazy load it.

# File lib/big_record/base.rb, line 625
def add_missing_cells(raw_record, requested_columns)
  requested_columns.each do |k, v|
    # don't do it for column families (e.g. attribute:)
    unless k =~ /:$/
      raw_record[k] = nil unless raw_record.has_key?(k)
    end
  end
end
alias_attribute(alias_name, fully_qualified_name) click to toggle source

Define aliases to the fully qualified attributes

# File lib/big_record/base.rb, line 635
def alias_attribute(alias_name, fully_qualified_name)
  self.class_eval <<-EOF
    def #{alias_name}(options={})
      read_attribute("#{fully_qualified_name}", options)
    end
    def #{alias_name}=(value)
      write_attribute("#{fully_qualified_name}", value)
    end
  EOF
end
find_all_by_id(ids, options={}) click to toggle source
# File lib/big_record/base.rb, line 612
def find_all_by_id(ids, options={})
  ids.inject([]) do |result, id|
    begin
      result << find_one(id, options)
    rescue BigRecord::RecordNotFound => e
    end
    result
  end
end
find_every(options) click to toggle source
# File lib/big_record/base.rb, line 533
def find_every(options)
  requested_columns = columns_to_find(options)

  raw_records = connection.get_consecutive_rows(table_name, options[:offset],
    options[:limit], requested_columns, options[:stop_row])

  raw_records.collect do |raw_record|
    add_missing_cells(raw_record, requested_columns)
    rec = instantiate(raw_record)
    rec.all_attributes_loaded = true if options[:view] == :all
    rec
  end
end
find_from_ids(ids, options) click to toggle source
# File lib/big_record/base.rb, line 547
def find_from_ids(ids, options)
  expects_array = ids.first.kind_of?(Array)
  return ids.first if expects_array && ids.first.empty?

  ids = ids.flatten.compact.uniq

  case ids.size
    when 0
      raise RecordNotFound, "Couldn't find #{name} without an ID"
    when 1
      result = find_one(ids.first, options)
      expects_array ? [ result ] : result
    else
      ids.collect do |id|
        find_one(id, options)
      end
  end
end
find_one(id, options) click to toggle source
# File lib/big_record/base.rb, line 566
def find_one(id, options)
  # allow to pass a record (e.g. Entity.find(@entity)) and not only a string (e.g. Entity.find("$-monkey-123"))
  unless id.is_a?(String)
    id = id.id if id and not id.is_a?(String)
  end

  # Allow the client to give us other objects than integers, e.g. Time and String
  if options[:timestamp] && options[:timestamp].kind_of?(Time)
    options[:timestamp] = options[:timestamp].to_bigrecord_timestamp
  end

  requested_columns = columns_to_find(options)

  # TODO: this is a hack... it should be done in a single call but currently hbase doesn't allow that
  raw_record =
  if options[:versions] and options[:versions] > 1
    timestamps = connection.get(table_name, id, "#{default_family}:updated_at", options)
    timestamps.collect{|timestamp| connection.get_columns(table_name, id, requested_columns, :timestamp => timestamp.to_bigrecord_timestamp)}
  else
    connection.get_columns(table_name, id, requested_columns, options)
  end

  # Instantiate the raw record (or records, if multiple versions were asked)
  if raw_record
    if raw_record.is_a?(Array)
      unless raw_record.empty?
        raw_record.collect do |r|
          add_missing_cells(r, requested_columns)
          rec = instantiate(r)
          rec.all_attributes_loaded = true if options[:view] == :all
          rec
        end
      else
        raise RecordNotFound, "Couldn't find #{name} with ID=#{id}"
      end
    else
      add_missing_cells(raw_record, requested_columns)
      rec = instantiate(raw_record)
      rec.all_attributes_loaded = true if options[:view] == :all
      rec
    end
  else
    raise RecordNotFound, "Couldn't find #{name} with ID=#{id}"
  end
end
invalidate_views() click to toggle source
# File lib/big_record/base.rb, line 517
def invalidate_views
  @views = nil
  @view_names = nil
end

Private Class Methods

clear_all_cached_connections!() click to toggle source
# File lib/big_record/connection_adapters/abstract/connection_specification.rb, line 144
def clear_all_cached_connections!
  if @@allow_concurrency
    @@active_connections.each_value do |connection_hash_for_thread|
      connection_hash_for_thread.each_value {|conn| conn.disconnect! }
      connection_hash_for_thread.clear
    end
  else
    @@active_connections.each_value {|conn| conn.disconnect! }
  end
  @@active_connections.clear
end
clear_cache!(cache, thread_id = nil, &block) click to toggle source
# File lib/big_record/connection_adapters/abstract/connection_specification.rb, line 114
def clear_cache!(cache, thread_id = nil, &block)
  if cache
    if @@allow_concurrency
      thread_id ||= Thread.current.object_id
      thread_cache, cache = cache, cache[thread_id]
      return unless cache
    end

    cache.each(&block) if block_given?
    cache.clear
  end
ensure
  if thread_cache && @@allow_concurrency
    thread_cache.delete(thread_id)
  end
end
remove_stale_cached_threads!(cache, &block) click to toggle source

Remove stale threads from the cache.

# File lib/big_record/connection_adapters/abstract/connection_specification.rb, line 132
def remove_stale_cached_threads!(cache, &block)
  stale = Set.new(cache.keys)

  Thread.list.each do |thread|
    stale.delete(thread.object_id) if thread.alive?
  end

  stale.each do |thread_id|
    clear_cache!(cache, thread_id, &block)
  end
end

Public Instance Methods

[](attr_name) click to toggle source

Returns the value of the attribute identified by attr_name after it has been typecast (for example, “2004-12-12” in a data column is cast to a date object, like Date.new(2004, 12, 12)). (Alias for the protected #read_attribute method).

# File lib/big_record/base.rb, line 27
def [](attr_name)
  if attr_name.ends_with?(":")
    read_family_attributes(attr_name)
  else
    read_attribute(attr_name)
  end
end
connection() click to toggle source
# File lib/big_record/base.rb, line 193
def connection
  self.class.connection
end
destroy() click to toggle source

Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can't be persisted).

# File lib/big_record/base.rb, line 162
    def destroy
      unless new_record?
        connection.delete(self.class.table_name, self.id)
      end

      # FIXME: this currently doesn't work because we write the attributes everytime we read them
      # which means that we cannot read the attributes of a deleted record... it's bad
#      freeze
    end
is_loaded?(name) click to toggle source
# File lib/big_record/base.rb, line 137
def is_loaded?(name)
  @loaded_columns ||= []
  @loaded_columns.include?(name)
end
new_record?() click to toggle source

Returns true if this object hasn't been saved yet – that is, a record for the object doesn't exist yet.

# File lib/big_record/base.rb, line 144
def new_record?
  @new_record
end
read_attribute(attr_name, options={}) click to toggle source

Returns the value of the attribute identified by attr_name after it has been typecast (for example, “2004-12-12” in a data column is cast to a date object, like Date.new(2004, 12, 12)).

Calls superclass method
# File lib/big_record/base.rb, line 37
def read_attribute(attr_name, options={})
  attr_name = attr_name.to_s
  column = column_for_attribute(attr_name)
  if column
    # First check if the attribute is already in the attributes hash
    if @attributes.has_key?(attr_name) and options.blank?
      super(attr_name)
    # Elsif the column exist, we try to lazy load it
    elsif !(is_loaded?(attr_name)) and attr_name != self.class.primary_key and !new_record?
      unless self.all_attributes_loaded? and attr_name =~ /\A#{self.class.default_family}:/
        if options.blank?
          # Normal behavior

          # Retrieve the version of the attribute matching the current record version
          options[:timestamp] = self.updated_at.to_bigrecord_timestamp if self.has_attribute?("#{self.class.default_family}:updated_at") and self.updated_at

          # get the content of the cell
          value = connection.get(self.class.table_name, self.id, attr_name, options)

          set_loaded(attr_name)
          write_attribute(attr_name, column.type_cast(value))
        else
          # Special request... don't keep it in the attributes hash
          options[:timestamp] ||= self.updated_at.to_bigrecord_timestamp if self.has_attribute?("#{self.class.default_family}:updated_at") and self.updated_at

          # get the content of the cell
          value = connection.get(self.class.table_name, self.id, attr_name, options)

          if options[:versions] and options[:versions] > 1
            value.collect{ |v| column.type_cast(v) }
          else
            column.type_cast(value)
          end
        end
      else
        write_attribute(attr_name, column.default)
      end
    else
      write_attribute(attr_name, column.default)
    end
  else
    nil
  end
end
read_family_attributes(attr_name) click to toggle source

Read an attribute that defines a column family.

# File lib/big_record/base.rb, line 83
def read_family_attributes(attr_name)
  attr_name = attr_name.to_s
  column = column_for_attribute(attr_name)
  if column
    # First check if the attribute is already in the attributes hash
    if @attributes.has_key?(attr_name)
      if (values = @attributes[attr_name]) and values.is_a?(Hash)
        values.delete(self.class.primary_key)
        casted_values = {}
        values.each{|k,v| casted_values[k] = column.type_cast(v)}
        write_attribute(attr_name, casted_values)
      else
        write_attribute(attr_name, {})
      end

    # Elsif the column exist, we try to lazy load it
    elsif !(is_loaded?(attr_name)) and attr_name != self.class.primary_key and !new_record?
      unless self.all_attributes_loaded? and attr_name =~ /\A#{self.class.default_family}:/
        options = {}
        # Retrieve the version of the attribute matching the current record version
        options[:timestamp] = self.updated_at.to_bigrecord_timestamp if self.has_attribute?("#{self.class.default_family}:updated_at") and self.updated_at

        # get the content of the whole family
        values = connection.get_columns(self.class.table_name, self.id, [attr_name], options)
        if values
          values.delete(self.class.primary_key)
          casted_values = {}
          values.each do |k,v|
            short_name = k.split(":")[1]
            casted_values[short_name] = column.type_cast(v) if short_name
            set_loaded(k)
            write_attribute(k, casted_values[short_name]) if short_name
          end
          write_attribute(attr_name, casted_values)
        else
          set_loaded(attr_name)
          write_attribute(attr_name, {})
        end
      else
        write_attribute(attr_name, column.default)
      end
    else
      write_attribute(attr_name, column.default)
    end
  else
    nil
  end
end
save() click to toggle source
  • No record exists: Creates a new record with values matching those of the object attributes.

  • A record does exist: Updates the record with values matching those of the object attributes.

# File lib/big_record/base.rb, line 150
def save
  create_or_update
end
save!() click to toggle source

Attempts to save the record, but instead of just returning false if it couldn't happen, it raises a RecordNotSaved exception

# File lib/big_record/base.rb, line 156
def save!
  create_or_update || raise(RecordNotSaved)
end
set_loaded(name) click to toggle source
# File lib/big_record/base.rb, line 132
def set_loaded(name)
  @loaded_columns ||= []
  @loaded_columns << name
end
update_attribute(name, value) click to toggle source

Updates a single attribute and saves the record. This is especially useful for boolean flags on existing records. Note: This method is overwritten by the Validation module that'll make sure that updates made with this method doesn't get subjected to validation checks. Hence, attributes can be updated even if the full object isn't valid.

# File lib/big_record/base.rb, line 175
def update_attribute(name, value)
  send(name.to_s + '=', value)
  save
end
update_attributes(attributes) click to toggle source

Updates all the attributes from the passed-in Hash and saves the record. If the object is invalid, the saving will fail and false will be returned.

# File lib/big_record/base.rb, line 182
def update_attributes(attributes)
  self.attributes = attributes
  save
end
update_attributes!(attributes) click to toggle source

Updates an object just like #update_attributes but calls save! instead of save so an exception is raised if the record is invalid.

# File lib/big_record/base.rb, line 188
def update_attributes!(attributes)
  self.attributes = attributes
  save!
end

Protected Instance Methods

create() click to toggle source

Creates a record with values matching those of the instance attributes and returns its id. Generate a UUID as the row key.

# File lib/big_record/base.rb, line 208
def create
  self.id = generate_new_id unless self.id
  @new_record = false
  update_bigrecord
end
create_or_update() click to toggle source

Invoke {#create} if {#new_record} returns true, otherwise it's an {#update}

# File lib/big_record/base.rb, line 200
def create_or_update
  raise ReadOnlyRecord if readonly?
  result = new_record? ? create : update
  result != false
end
update() click to toggle source

Updates the associated record with values matching those of the instance attributes. Returns the number of affected rows.

# File lib/big_record/base.rb, line 216
def update
  update_bigrecord
end
update_bigrecord() click to toggle source

Update this record in hbase. Cannot be directly in the method 'update' because it would trigger callbacks and therefore weird behaviors.

# File lib/big_record/base.rb, line 222
def update_bigrecord
  timestamp = self.respond_to?(:updated_at) ? self.updated_at.to_bigrecord_timestamp : Time.now.to_bigrecord_timestamp

  data = clone_in_persistence_format

  connection.update(self.class.table_name, id, data, timestamp)
end