Class: BigRecord::Embedded

Inherits:
Model show all
Defined in:
lib/big_record/embedded.rb

Overview

Embedded Records

Since a single column in a column-oriented database is perfectly suited to handle large amounts of data, BigRecord gives you the option to store entire records within a single column of another BigRecord::Base record.

These are known as Embedded records, and they behave similarly to BigRecord::Base objects, except that their data is physically stored within another BigRecord::Base record, and they don’t exist unless associated with one. Furthermore, they don’t possess any find or querying functionality.

So what are the benefits of Embedded records?

  • Cleaner organization of models
  • Avoids the need to create entire tables and associations for models that exist only in the context of another model.
  • Allows more complicated functionality to be encompassed within an embedded record, instead of in a parent model.

All of this has been very abstract so far, therefore examples are in order.

Examples

Let’s say we start off with the following arbitrarily created models:

app/model/book.rb:

  class Book < BigRecord::Base
    column :title,       :string
    column :author,      :string
    column :description, :string
  end

app/model/company.rb:

  class Company < BigRecord::Base
    column :name,        :string
    column :address,     :string
    column :description, :string
  end

Now, let’s say we want the ability to create and associate weblinks with each of these models. This is a trivial modification if all we do is create a new column in each model called "weblink" (or something similar), and have a string that stores a URL.

However, what if we wanted these weblinks to have more metadata attached and more complex functionality added to it? Then our only choice is to create a new model called WebLink (for example), with its own table, set of attributes and methods. Then we have our Book and Company models associate to these newly created WebLink models, giving us something like this:

app/model/web_link.rb:

  class WebLink < BigRecord::Base
    column :name,         :string
    column :url,          :string
    column :description,  :string
    column :submitted_by, :string
    column :book_id,      :string
    column :company_id,   :string

    # Could use a polymorphic association here, of course.
    belongs_to_bigrecord :book, :foreign_key => "attribute:book_id"
    belongs_to_bigrecord :company, :foreign_key => "attribute:company_id"

    # other methods ...
  end

and likewise an association to WebLink from the Book and Company models.

Now notice the problem here? A simple concept like adding a WebLink with some metadata has increased the model logic and created some unnecessary associations. In this situation, a WebLink doesn’t need to exist except when associated to a certain model. Therefore this association should be implicit somehow.

Enter Embedded records. We will now instead define WebLink as follows:

app/model/web_link.rb:

  class WebLink < BigRecord::Embedded
    column :name,         :string
    column :url,          :string
    column :description,  :string
    column :submitted_by, :string

    # other methods ...
  end

And modify our Base records like so:

app/model/book.rb:

  class Book < BigRecord::Base
    column :title,       :string
    column :author,      :string
    column :description, :string
    column :web_link,    'WebLink'
  end

app/model/company.rb:

  class Company < BigRecord::Base
    column :name,        :string
    column :address,     :string
    column :description, :string
    column :web_link,    'WebLink'
  end

Now we can encompass any WebLink specific attributes and methods within the WebLink embedded class, and use them with any other Base model.

To use WebLink now, we treat it as though it were a regular model, except that we don’t execute saves on it. For example:

  >> amazon_link = WebLink.new(:name => "Amazon Link to Book", :url => "http://amazon.com/some/book", :description => "Amazon sells this book for cheap!")
  => #<WebLink created_at: "2009-11-12 17:11:57", name: "Amazon Link to Book", url: "http://amazon.com/some/book", description: "Amazon sells this book for cheap!", submitted_by: nil, id: "2b619a68-e462-475d-8e04-01ba2aace11a">
  >> amazon_link.save
  BigRecord::NotImplemented: BigRecord::NotImplemented
  # => [...]
  >> book = Book.find(:first)
  # => [...]
  >> book.web_link = amazon_link
  >> book.save

Now any subsequent access to that book object we just saved to will have a WebLink record available with it.

Constant Summary

Constants inherited from Model

ID_FIELD_SEPARATOR, ID_WHITE_SPACE_CHAR

Class Method Summary

Instance Method Summary

Methods inherited from Model

#==, ===, #[], #[]=, accessible_attributes, alias_attribute, #all_attributes_loaded=, #all_attributes_loaded?, attr_accessible, attr_create_accessible, attr_protected, attr_readonly, #attribute_for_inspect, #attribute_names, #attribute_present?, #attributes, #attributes=, benchmark, column, #column_for_attribute, column_methods_hash, column_names, columns, columns_hash, content_columns, create_accessible_attributes, default_column_prefix, #deserialize, #destroy, #eql?, #freeze, #frozen?, #has_attribute?, #hash, human_attribute_name, #human_attribute_name, #id=, #inspect, instantiate, #new_record?, #preinitialize, protected_attributes, quote_value, #quoted_id, read_methods, #readonly!, #readonly?, readonly_attributes, #reload, reset_subclasses, #respond_to?, #safe_attributes=, #save, #save!, silence, #to_s, undecorated_table_name, #update_attribute, #update_attributes, #update_attributes!

Constructor Details

- (Embedded) initialize(attrs = nil)

A new instance of Embedded



128
129
130
131
132
133
# File 'lib/big_record/embedded.rb', line 128

def initialize(attrs = nil)
  super
  # Regenerate the id unless it's already there
  # (i.e. we're instantiating an existing property)
  @attributes["id"] ||= generate_id
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class BigRecord::Model

Class Method Details

+ (Object) base_class



165
166
167
# File 'lib/big_record/embedded.rb', line 165

def base_class
  (superclass == BigRecord::Embedded) ? self : superclass.base_class
end

+ (Object) connection

Borrow the default connection of BigRecord



161
162
163
# File 'lib/big_record/embedded.rb', line 161

def connection
  BigRecord::Base.connection
end

+ (Object) default_columns



191
192
193
# File 'lib/big_record/embedded.rb', line 191

def default_columns
  {primary_key => ConnectionAdapters::Column.new(primary_key, 'string')}
end

+ (Object) hide_to_users



178
179
180
# File 'lib/big_record/embedded.rb', line 178

def hide_to_users
  @hide_to_user = true
end

+ (Object) inherited(child)

:nodoc:



186
187
188
189
# File 'lib/big_record/embedded.rb', line 186

def inherited(child) #:nodoc:
  child.set_pretty_name child.name.split("::").last
  super
end

+ (Object) pretty_name

Class attribute that holds the name of the embedded type for dispaly



170
171
172
# File 'lib/big_record/embedded.rb', line 170

def pretty_name
  @pretty_name || self.to_s
end

+ (Object) primary_key



156
157
158
# File 'lib/big_record/embedded.rb', line 156

def primary_key
  "id"
end

+ (Object) set_pretty_name(new_name)



174
175
176
# File 'lib/big_record/embedded.rb', line 174

def set_pretty_name new_name
  @pretty_name = new_name
end

+ (Boolean) show_to_users?

Returns:

  • (Boolean)


182
183
184
# File 'lib/big_record/embedded.rb', line 182

def show_to_users?
  !@hide_to_user
end

+ (Boolean) store_primary_key?

Returns:

  • (Boolean)


152
153
154
# File 'lib/big_record/embedded.rb', line 152

def store_primary_key?
  true
end

Instance Method Details

- (Object) connection



135
136
137
# File 'lib/big_record/embedded.rb', line 135

def connection
  self.class.connection
end

- (Object) id



139
140
141
# File 'lib/big_record/embedded.rb', line 139

def id
  super || (self.id = generate_id)
end