diff --git a/README.textile b/README.textile
index aaecf09..05f76c8 100644
--- a/README.textile
+++ b/README.textile
@@ -21,7 +21,7 @@ h2. What it does
Processing HotelsController#show (for 127.0.0.1 at 2009-03-18 19:29:38) [GET]
Parameters: {"action"=>"show", "id"=>"8699-radisson-hotel-waterfront-cape-town", "controller"=>"hotels"}
- Hotel Load Scrooged (0.3ms) SELECT `hotels`.id FROM `hotels` WHERE (`hotels`.`id` = 8699)
+ Hotel Load Scrooged (0.3ms) SELECT `hotels`.id FROM `hotels` WHERE (`hotels`.`id` = 8699)
Rendering template within layouts/application
Rendering hotels/show
SQL (0.2ms) SELECT `hotels`.location_id,`hotels`.hotel_name,`hotels`.location,`hotels`.from_price,`hotels`.star_rating,`hotels`.apt,`hotels`.latitude,`hotels`.longitude,`hotels`.distance,`hotels`.narrative,`hotels`.telephone,`hotels`.important_notes,`hotels`.nearest_tube,`hotels`.nearest_rail,`hotels`.created_at,`hotels`.updated_at,`hotels`.id FROM `hotels` WHERE `hotels`.id IN ('8699')
@@ -29,7 +29,7 @@ h2. What it does
SQL (0.2ms) SELECT `images`.hotel_id,`images`.title,`images`.url,`images`.width,`images`.height,`images`.thumbnail_url,`images`.thumbnail_width,`images`.thumbnail_height,`images`.has_thumbnail,`images`.created_at,`images`.updated_at,`images`.id FROM `images` WHERE `images`.id IN ('488')
Rendered shared/_header (0.0ms)
Rendered shared/_navigation (0.2ms)
- Image Load Scrooged (0.2ms) SELECT `images`.id FROM `images` WHERE (`images`.hotel_id = 8699)
+ Image Load Scrooged (0.2ms) SELECT `images`.id FROM `images` WHERE (`images`.hotel_id = 8699)
SQL (0.2ms) SELECT `images`.hotel_id,`images`.title,`images`.url,`images`.width,`images`.height,`images`.thumbnail_url,`images`.thumbnail_width,`images`.thumbnail_height,`images`.has_thumbnail,`images`.created_at,`images`.updated_at,`images`.id FROM `images` WHERE `images`.id IN ('488')
Address Columns (306.2ms) SHOW FIELDS FROM `addresses`
Address Load Scrooged (3.6ms) SELECT `addresses`.id FROM `addresses` WHERE (`addresses`.hotel_id = 8699) LIMIT 1
@@ -40,20 +40,20 @@ h2. What it does
Processing HotelsController#show (for 127.0.0.1 at 2009-03-18 19:29:40) [GET]
Parameters: {"action"=>"show", "id"=>"8699-radisson-hotel-waterfront-cape-town", "controller"=>"hotels"}
- Hotel Load Scrooged (0.3ms) SELECT `hotels`.narrative,`hotels`.from_price,`hotels`.star_rating,`hotels`.hotel_name,`hotels`.id FROM `hotels` WHERE (`hotels`.`id` = 8699)
- Address Load Scrooged (0.2ms) SELECT `addresses`.id FROM `addresses` WHERE (`addresses`.hotel_id = 8699)
+ Hotel Load Scrooged (0.3ms) SELECT `hotels`.narrative,`hotels`.from_price,`hotels`.star_rating,`hotels`.hotel_name,`hotels`.id FROM `hotels` WHERE (`hotels`.`id` = 8699)
+ Address Load Scrooged (0.2ms) SELECT `addresses`.id FROM `addresses` WHERE (`addresses`.hotel_id = 8699)
Rendering template within layouts/application
Rendering hotels/show
Image Load Scrooged (0.3ms) SELECT `images`.url,`images`.id,`images`.height,`images`.width FROM `images` WHERE (`images`.hotel_id = 8699) LIMIT 1
Rendered shared/_header (0.1ms)
Rendered shared/_navigation (0.2ms)
- Image Load Scrooged (0.3ms) SELECT `images`.thumbnail_width,`images`.id,`images`.thumbnail_height,`images`.thumbnail_url FROM `images` WHERE (`images`.hotel_id = 8699)
+ Image Load Scrooged (0.3ms) SELECT `images`.thumbnail_width,`images`.id,`images`.thumbnail_height,`images`.thumbnail_url FROM `images` WHERE (`images`.hotel_id = 8699)
Rendered hotels/_show_sidebar (1.0ms)
Rendered shared/_footer (0.1ms)
Completed in 8ms (View: 5, DB: 1) | 200 OK [http://localhost/hotels/8699-radisson-hotel-waterfront-cape-town]
-
+
-
+
h2. Suggested Use
@@ -75,7 +75,7 @@ h4. As a Gem
h2. Stability
-The whole Rails 2.3.2 ActiveRecord test suite passes with scrooge, except for 13 failures related to callsite augmentation (note the SQL reload snippets below). Thoughts on handling or circumventing this much appreciated.
+The whole Rails 2.3.2 ActiveRecord test suite passes with scrooge, except for 13 failures related to callsite augmentation (note the SQL reload snippets below). Thoughts on handling or circumventing this much appreciated.
@@ -87,10 +87,10 @@ test_finding_with_includes_on_belongs_to_association_with_same_include_includes_
/opt/local/lib/ruby/gems/1.8/gems/activesupport-2.3.1/lib/active_support/testing/setup_and_teardown.rb:57:in `run']:
5 instead of 3 queries were executed.
Queries:
-SELECT `posts`.id,`posts`.type FROM `posts` WHERE (`posts`.`id` = 1)
-SELECT `posts`.author_id,`posts`.title,`posts`.body,`posts`.comments_count,`posts`.taggings_count FROM `posts` WHERE (`posts`.`id` = 1)
-SELECT `authors`.name,`authors`.id FROM `authors` WHERE (`authors`.`id` = 1)
-SELECT `authors`.author_address_id,`authors`.author_address_extra_id FROM `authors` WHERE (`authors`.`id` = 1)
+SELECT `posts`.id,`posts`.type FROM `posts` WHERE (`posts`.`id` = 1)
+SELECT `posts`.author_id,`posts`.title,`posts`.body,`posts`.comments_count,`posts`.taggings_count FROM `posts` WHERE (`posts`.`id` = 1)
+SELECT `authors`.name,`authors`.id FROM `authors` WHERE (`authors`.`id` = 1)
+SELECT `authors`.author_address_id,`authors`.author_address_extra_id FROM `authors` WHERE (`authors`.`id` = 1)
SELECT `author_addresses`.id FROM `author_addresses` WHERE (`author_addresses`.`id` = 1) .
<3> expected but was
<5>.
@@ -149,25 +149,25 @@ Ruby allows introspection of the call tree through
Kernel#caller
-
-
+
+
-Scrooge analyzes the last 10 calltree elements that triggered
+Scrooge analyzes the last 10 calltree elements that triggered
ActiveRecord::Base.find_by_sql
-
+
Lets refer to that as a callsite, or signature.
-Thus given SQL such as
+Thus given SQL such as
"SELECT * FROM `images` WHERE (`images`.hotel_id = 11697) LIMIT 1"
-
+
Called from our application helper
@@ -175,17 +175,17 @@ Called from our application helper
["/Users/lourens/projects/superbreak_app/vendor/plugins/scrooge/rails/../lib/scrooge.rb:27:in `find_by_sql'", "/Users/lourens/projects/superbreak_app/vendor/rails/activerecord/lib/active_record/base.rb:1557:in `find_every'", "/Users/lourens/projects/superbreak_app/vendor/rails/activerecord/lib/active_record/base.rb:1514:in `find_initial'", "/Users/lourens/projects/superbreak_app/vendor/rails/activerecord/lib/active_record/base.rb:613:in `find'", "/Users/lourens/projects/superbreak_app/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:60:in `find'", "/Users/lourens/projects/superbreak_app/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb:67:in `first'", "/Users/lourens/projects/superbreak_app/app/helpers/application_helper.rb:60:in `hotel_image'", "/Users/lourens/projects/superbreak_app/app/views/hotels/_hotel.html.erb:4:in `_run_erb_app47views47hotels47_hotel46html46erb_locals_hotel_hotel_counter_object'", "/Users/lourens/projects/superbreak_app/vendor/rails/actionpack/lib/action_view/renderable.rb:36:in `send'", "/Users/lourens/projects/superbreak_app/vendor/rails/actionpack/lib/action_view/renderable.rb:36:in `render'", "/Users/lourens/projects/superbreak_app/vendor/rails/actionpack/lib/action_view/renderable_partial.rb:20:in `render'"]
-
+
We can generate a unique callsite identifier with the following calculation :
(The above calltree << "SELECT * FROM `images` ).hash " # cut off conditions etc.
-
+
-Callsites are tracked on a per model ( table name ) basis.
+Callsites are tracked on a per model ( table name ) basis.
h4. Scope
diff --git a/Rakefile b/Rakefile
index 0b9c79a..8df7270 100644
--- a/Rakefile
+++ b/Rakefile
@@ -9,7 +9,7 @@ task :default => [:test_with_active_record, :test_scrooge]
task :test => :default
Rake::TestTask.new( :test_with_active_record ) { |t|
- t.libs << AR_TEST_SUITE << Scrooge::Test.connection()
+ t.libs << AR_TEST_SUITE << Scrooge::Test.connection()
t.test_files = Scrooge::Test.active_record_test_files()
t.ruby_opts = ["-r #{File.join( File.dirname(__FILE__), 'test', 'setup' )}"]
t.verbose = true
diff --git a/VERSION.yml b/VERSION.yml
index f4406dc..750b78c 100644
--- a/VERSION.yml
+++ b/VERSION.yml
@@ -1,4 +1,4 @@
----
+---
:major: 3
:minor: 0
:patch: 0
diff --git a/lib/callsite.rb b/lib/callsite.rb
index bcbfa14..891ffae 100644
--- a/lib/callsite.rb
+++ b/lib/callsite.rb
@@ -1,28 +1,28 @@
module Scrooge
class Callsite
-
- # Represents a Callsite and is a container for any columns and
+
+ # Represents a Callsite and is a container for any columns and
# associations referenced at the callsite.
#
-
+
Mtx = Mutex.new # mutex should perhaps be per-instance at the expense of a little memory
attr_accessor :klass,
:signature,
:columns,
:associations
-
+
def initialize( klass, signature )
@klass = klass
@signature = signature
end
-
+
# Flag a column as seen
#
def column!( column )
columns && Mtx.synchronize { @columns << column }
end
-
+
# Flag an association as seen
# association should be an AssociationReflection object
#
@@ -31,33 +31,33 @@ def association!(association, record_id)
associations.register(association, record_id)
end
end
-
+
def inspect
"<##{@klass.name} :select => '#{@klass.scrooge_select_sql( columns )}', :include => [#{associations_for_inspect}]>"
end
-
+
# Lazy init default columns
#
def default_columns
@default_columns || Mtx.synchronize { @default_columns = setup_columns }
end
-
+
# Lazy init columns
#
def columns
- @columns || default_columns && Mtx.synchronize { @columns = @default_columns.dup }
+ @columns || default_columns && Mtx.synchronize { @columns = @default_columns.dup }
end
-
+
# Lazy init associations
#
def associations
@associations || Mtx.synchronize { @associations = setup_associations }
end
-
+
def has_associations?
@associations
end
-
+
# Analyze previously collected information
# and reset ready for a new query
#
@@ -66,15 +66,15 @@ def reset
associations.reset
end
end
-
+
def register_result_set(result_set)
if has_associations?
associations.register_result_set(result_set)
end
end
-
+
private
-
+
def associations_for_inspect
if has_associations?
associations.to_preload.map{|a| ":#{a.to_s}" }.join(', ')
@@ -82,36 +82,36 @@ def associations_for_inspect
""
end
end
-
+
# Only register associations that isn't polymorphic or a collection
#
def preloadable_association?( association )
@klass.preloadable_associations.include?( association.to_sym )
end
-
+
# Is the table a container for STI models ?
- #
+ #
def inheritable?
@klass.columns_hash.has_key?( inheritance_column )
end
-
+
# Ensure that at least the primary key and optionally the inheritance
- # column ( for STI ) is set.
+ # column ( for STI ) is set.
#
def setup_columns
if inheritable?
SimpleSet.new([primary_key, inheritance_column])
else
primary_key.blank? ? SimpleSet.new : SimpleSet.new([primary_key])
- end
+ end
end
-
+
# Start with no registered associations
#
def setup_associations
Optimizations::Associations::AssociationSet.new
end
-
+
# Memoize a string representation of the inheritance column
#
def inheritance_column
@@ -119,10 +119,10 @@ def inheritance_column
end
# Memoize a string representation of the primary
- #
+ #
def primary_key
@primary_key ||= @klass.primary_key.to_s
- end
-
+ end
+
end
end
\ No newline at end of file
diff --git a/lib/optimizations/associations/association_set.rb b/lib/optimizations/associations/association_set.rb
index 736cb97..b38e9a5 100644
--- a/lib/optimizations/associations/association_set.rb
+++ b/lib/optimizations/associations/association_set.rb
@@ -1,9 +1,9 @@
module Scrooge
- module Optimizations
+ module Optimizations
module Associations
# Keeps track of how a result set is used to access associations
- # Each callsite where associations are accessed will contain one of
+ # Each callsite where associations are accessed will contain one of
# these objects.
# Each thread will collect data, and we check this data before each
# fetch from the database, adding any associations that are needed
@@ -21,58 +21,58 @@ def initialize
@associations = SimpleSet.new
@as_data_id = :"association_data_#{object_id}"
end
-
+
def register(association, record_id)
assoc_data.register(association, record_id)
end
-
+
def register_result_set(result_set)
assoc_data.register_result_set(result_set)
end
-
+
def reset
Mtx.synchronize do
@associations |= assoc_data.to_preload
end
assoc_data.reset
end
-
+
def to_preload
@associations.to_a
end
-
+
private
-
+
def assoc_data
Thread.current[@as_data_id] ||= AssociationData.new
end
end
-
+
class AssociationData
def initialize
reset
end
-
+
def reset
@associations = {}
@result_set_size = 0
end
-
+
def register(association, record_id)
if @result_set_size > 1
assoc = (@associations[association.name] ||= AssociationIdentity.new(association))
assoc.register(record_id)
end
end
-
+
def register_result_set(result_set)
@result_set_size = result_set.size
end
-
+
def to_preload
@associations.values.select { |association| preload_this_assoc?(association) }.map(&:name)
end
-
+
private
# Calculate the benefit of preloading an association
@@ -81,7 +81,7 @@ def to_preload
# to access the association - more than 25% and we preload
#
# TODO: more rules and analysis for different association types
- #
+ #
def preload_this_assoc?(association)
if @result_set_size <= 1
false
diff --git a/lib/optimizations/associations/macro.rb b/lib/optimizations/associations/macro.rb
index e6ee454..d2b7815 100644
--- a/lib/optimizations/associations/macro.rb
+++ b/lib/optimizations/associations/macro.rb
@@ -1,33 +1,33 @@
module Scrooge
- module Optimizations
+ module Optimizations
module Associations
module Macro
-
+
class << self
-
+
# Inject into ActiveRecord
#
def install!
unless scrooge_installed?
ActiveRecord::Base.send( :extend, SingletonMethods )
- ActiveRecord::Associations::AssociationProxy.send( :include, InstanceMethods )
+ ActiveRecord::Associations::AssociationProxy.send( :include, InstanceMethods )
end
end
-
+
protected
-
+
def scrooge_installed?
ActiveRecord::Associations::AssociationProxy.included_modules.include?( InstanceMethods )
end
-
+
end
-
+
end
-
+
module SingletonMethods
-
+
@@preloadable_associations = {}
-
+
def self.extended( base )
eigen = class << base; self; end
# not used at present
@@ -53,18 +53,18 @@ def scrooge_preloading_exclude
Thread.current[:scrooge_preloading] = false
end
end
-
+
# Let's not preload polymorphic associations or collections
- #
+ #
def preloadable_associations
- @@preloadable_associations[self.name] ||=
+ @@preloadable_associations[self.name] ||=
reflect_on_all_associations.reject{|a| a.options[:polymorphic] || a.macro == :has_many}.map(&:name)
end
end
-
+
module InstanceMethods
-
+
def self.included( base )
base.alias_method_chain :load_target, :scrooge
end
@@ -78,7 +78,7 @@ def load_target_with_scrooge
end
private
-
+
# Register an association with Scrooge
#
def scrooge_seen_association!( association )
@@ -86,13 +86,13 @@ def scrooge_seen_association!( association )
@owner.class.scrooge_callsite(callsite_signature).association!(association, @owner.id)
end
end
-
+
def callsite_signature
@owner.instance_variable_get(:@attributes).callsite_signature
end
-
+
end
-
+
end
end
-end
\ No newline at end of file
+end
\ No newline at end of file
diff --git a/lib/optimizations/columns/attributes_proxy.rb b/lib/optimizations/columns/attributes_proxy.rb
index 29b94ff..e1cf336 100644
--- a/lib/optimizations/columns/attributes_proxy.rb
+++ b/lib/optimizations/columns/attributes_proxy.rb
@@ -4,7 +4,7 @@ module Columns
class UnscroogedAttributes < Hash
# Hash container for attributes when scrooge is not used
- #
+ #
def self.setup(record)
new.replace(record)
@@ -18,7 +18,7 @@ def update(hash)
end
alias_method :merge!, :update
-
+
# Don't try to reload one of these
#
def fully_fetched
@@ -27,9 +27,9 @@ def fully_fetched
end
class ScroogedAttributes < Hash
-
+
# Hash container for attributes with scrooge monitoring of attribute access
- #
+ #
attr_accessor :fully_fetched, :klass, :updateable_result_set
@@ -62,7 +62,7 @@ def []=(attr_name, value)
add_to_scrooge_columns(attr_name)
super
end
-
+
alias_method :store, :[]=
def dup
@@ -88,7 +88,7 @@ def update(hash)
@fully_fetched = true
super(hash.to_hash)
end
-
+
alias_method :merge!, :update
def fetch_remaining
@@ -100,22 +100,22 @@ def fetch_remaining
@fully_fetched = true
end
end
-
+
def callsite_signature
@updateable_result_set.callsite_signature
end
-
+
def scrooge_columns
@scrooge_columns || @updateable_result_set.scrooge_columns
end
-
+
protected
def fetch_remaining!( columns_to_fetch )
@updateable_result_set.updaters_attributes = self # for after_initialize & after_find
@updateable_result_set.reload_columns!(columns_to_fetch)
end
-
+
def augment_callsite!( attr_name )
@klass.scrooge_seen_column!(callsite_signature, attr_name)
end
@@ -138,4 +138,4 @@ def dup_self
end
end
end
-end
+end
diff --git a/lib/optimizations/columns/macro.rb b/lib/optimizations/columns/macro.rb
index 381da06..f4be354 100644
--- a/lib/optimizations/columns/macro.rb
+++ b/lib/optimizations/columns/macro.rb
@@ -1,74 +1,74 @@
module Scrooge
- module Optimizations
+ module Optimizations
module Columns
module Macro
-
+
class << self
-
+
# Inject into ActiveRecord
#
def install!
if scrooge_installable?
ActiveRecord::Base.send( :extend, SingletonMethods )
- ActiveRecord::Base.send( :include, InstanceMethods )
- end
+ ActiveRecord::Base.send( :include, InstanceMethods )
+ end
end
-
+
private
-
+
def scrooge_installable?
!ActiveRecord::Base.included_modules.include?( InstanceMethods )
end
-
+
end
-
+
end
-
+
module SingletonMethods
-
+
ScroogeBlankString = "".freeze
- ScroogeComma = ",".freeze
+ ScroogeComma = ",".freeze
ScroogeRegexSanitize = /(?:LIMIT|WHERE|FROM|GROUP\s*BY|HAVING|ORDER\s*BY|PROCEDURE|FOR\s*UPDATE|INTO\s*OUTFILE).*/i
ScroogeRegexJoin = /(?:left|inner|outer|cross)*\s*(?:straight_join|join)/i
-
+
@@scrooge_select_regexes = {}
-
+
# Augment a given callsite signature with a column / attribute.
#
def scrooge_seen_column!( callsite_signature, attr_name )
scrooge_callsite( callsite_signature ).column!( attr_name )
- end
-
+ end
+
# Generates a SELECT snippet for this Model from a given Set of columns
#
def scrooge_select_sql( set )
set.map{|a| attribute_with_table( a ) }.join( ScroogeComma )
- end
-
+ end
+
# Marshal.load
- #
+ #
def _load(str)
Marshal.load(str)
end
-
- # Efficient reloading - get the hash with missing attributes directly from the
+
+ # Efficient reloading - get the hash with missing attributes directly from the
# underlying connection.
#
def scrooge_reload( p_keys, missing_columns )
sql_keys = p_keys.collect{|pk| "'#{pk}'"}.join(ScroogeComma)
connection.send( :select, "SELECT #{scrooge_select_sql(missing_columns)} FROM #{quoted_table_name} WHERE #{quoted_table_name}.#{primary_key} IN (#{sql_keys})", "#{name} Scrooge Reload" )
end
-
+
# Only scope n-1 rows by default.
- #
+ #
def scope_with_scrooge?( sql )
- sql =~ scrooge_select_regex &&
+ sql =~ scrooge_select_regex &&
columns_hash.has_key?(self.primary_key.to_s) &&
sql !~ ScroogeRegexJoin
end
-
+
private
-
+
# Find through callsites.
#
def find_by_sql_with_scrooge(sql)
@@ -95,7 +95,7 @@ def find_by_sql_with_scrooge(sql)
result_set
end
-
+
def find_by_sql_without_scrooge(sql)
connection.select_all(sanitize_sql(sql), "#{name} Load").collect! do |record|
instantiate( UnscroogedAttributes.setup(record) )
@@ -104,7 +104,7 @@ def find_by_sql_without_scrooge(sql)
# Generate a regex that respects the table name as well to catch
# verbose SQL from JOINS etc.
- #
+ #
def scrooge_select_regex
@@scrooge_select_regexes[self.table_name] ||= Regexp.compile( "SELECT (`?(?:#{table_name})?`?.?\\*) FROM" )
end
@@ -114,11 +114,11 @@ def scrooge_select_regex
def callsite_sql( sql )
sql.gsub(ScroogeRegexSanitize, ScroogeBlankString)
end
-
+
end
-
+
module InstanceMethods
-
+
def self.included( base )
base.alias_method_chain :delete, :scrooge
base.alias_method_chain :destroy, :scrooge
@@ -126,27 +126,27 @@ def self.included( base )
base.alias_method_chain :attributes_from_column_definition, :scrooge
base.alias_method_chain :becomes, :scrooge
end
-
+
# Is this instance being handled by scrooge?
#
def scrooged?
@attributes.is_a?(ScroogedAttributes)
- end
-
+ end
+
# Delete should fully load all the attributes before the @attributes hash is frozen
#
def delete_with_scrooge
scrooge_fetch_remaining
delete_without_scrooge
- end
-
+ end
+
# Destroy should fully load all the attributes before the @attributes hash is frozen
#
def destroy_with_scrooge
scrooge_fetch_remaining
destroy_without_scrooge
- end
-
+ end
+
# Augment callsite info for new model class when using STI
#
def becomes_with_scrooge(klass)
@@ -156,7 +156,7 @@ def becomes_with_scrooge(klass)
end
end
becomes_without_scrooge(klass)
- end
+ end
# Marshal
# force a full load if needed, and remove any possibility for missing attr flagging
@@ -169,7 +169,7 @@ def _dump(depth)
scrooge_dump_unflag_this
str
end
-
+
# Enables us to use Marshal.dump inside our _dump method without an infinite loop
#
def respond_to_with_scrooge?(symbol, include_private=false)
@@ -179,7 +179,7 @@ def respond_to_with_scrooge?(symbol, include_private=false)
respond_to_without_scrooge?(symbol, include_private)
end
end
-
+
# Expose this record's callsite signature
#
def callsite_signature
@@ -213,7 +213,7 @@ def scrooge_dump_flagged?
def scrooge_fetch_remaining
@attributes.fetch_remaining if scrooged?
end
-
+
# Dumped objects should not contain object_ids of old result sets
#
def scrooge_invalidate_updateable_result_set
@@ -221,15 +221,15 @@ def scrooge_invalidate_updateable_result_set
@attributes.updateable_result_set = ResultSets::UpdateableResultSet.new(nil, self, callsite_signature, @attributes.scrooge_columns)
end
end
-
+
# New objects should get an UnscroogedAttributes as their @attributes hash
#
def attributes_from_column_definition_with_scrooge
UnscroogedAttributes.setup(attributes_from_column_definition_without_scrooge)
end
-
+
end
-
+
end
end
end
diff --git a/lib/optimizations/result_sets/updateable_result_set.rb b/lib/optimizations/result_sets/updateable_result_set.rb
index dbf670b..c586b8f 100644
--- a/lib/optimizations/result_sets/updateable_result_set.rb
+++ b/lib/optimizations/result_sets/updateable_result_set.rb
@@ -2,13 +2,13 @@ module Scrooge
module Optimizations
module ResultSets
class UpdateableResultSet
-
+
# Contains a weak referernce to the result set, and can update from DB
#
-
+
attr_accessor :updaters_attributes
attr_reader :callsite_signature, :scrooge_columns
-
+
def initialize(result_set_array, klass, callsite_signature, scrooge_columns)
if result_set_array
@result_set_object_id = result_set_array.object_id
@@ -18,7 +18,7 @@ def initialize(result_set_array, klass, callsite_signature, scrooge_columns)
@callsite_signature = callsite_signature
@scrooge_columns = scrooge_columns
end
-
+
# Called by a ScroogedAttributes hash when it is asked for a column
# that was not fetched from the DB
#
@@ -45,7 +45,7 @@ def result_set_attributes
memo
end.uniq
end
-
+
# The result set is weak referenced by its object_id
# So we check that a unique id matches what we have remembered to make sure
# that we got the right object (object ids are recycled by ruby)
@@ -57,7 +57,7 @@ def result_set
rescue RangeError
nil
end
-
+
# When called from after_find and after_initialize, the object
# being accessed (and causing the reload) is not in the result set yet.
# We make sure that we add its attributes to result_set_attributes so it
@@ -66,7 +66,7 @@ def result_set
def default_attributes
[@updaters_attributes]
end
-
+
# Ids of the items to be reloaded
#
def result_set_ids
@@ -77,7 +77,7 @@ def result_set_ids
memo
end
end
-
+
# Update the result set with attributes provided, as returned by
# the sql server
#
@@ -90,18 +90,18 @@ def update_with(remaining_attributes)
end
end
end
-
+
# Make an efficient data structure to access items when the
# primary key is known
#
def hash_by_primary_key(rows)
rows.inject({}) {|memo, row| memo[row[primary_key_name]] = row; memo}
end
-
+
def primary_key_name
@klass.primary_key
end
-
+
end
end
end
diff --git a/lib/scrooge.rb b/lib/scrooge.rb
index 9876e65..010fdb1 100644
--- a/lib/scrooge.rb
+++ b/lib/scrooge.rb
@@ -25,7 +25,7 @@ class << self
# Determine if a given SQL string is a candidate for callsite <=> columns
# optimization.
- #
+ #
def find_by_sql(sql)
if scope_with_scrooge?(sql)
find_by_sql_with_scrooge(sql)
@@ -33,9 +33,9 @@ def find_by_sql(sql)
find_by_sql_without_scrooge(sql)
end
end
-
+
# Expose known callsites for this model
- #
+ #
def scrooge_callsites
@@scrooge_callsites[table_name] || ScroogeMutex.synchronize { @@scrooge_callsites[table_name] = {} }
end
@@ -49,7 +49,7 @@ def scrooge_callsite( callsite_signature )
end
# Flush all known callsites. Mostly a test helper.
- #
+ #
def scrooge_flush_callsites!
ScroogeMutex.synchronize do
@@scrooge_callsites[table_name] = {}
@@ -64,12 +64,12 @@ def scrooge_unlink_callsite!( callsite_signature )
ScroogeMutex.synchronize do
@@scrooge_callsites.delete(callsite_signature)
end
- end
+ end
# Initialize a callsite
#
def callsite( signature )
- Scrooge::Callsite.new( self, signature )
+ Scrooge::Callsite.new( self, signature )
end
# Link the column to its table
@@ -77,7 +77,7 @@ def callsite( signature )
def attribute_with_table( attr_name )
"#{quoted_table_name}.#{connection.quote_column_name(attr_name.to_s)}"
end
-
+
# Computes a unique signature from a given call stack and supplementary
# context information.
#
diff --git a/lib/simple_set.rb b/lib/simple_set.rb
index 17d5853..56fbd53 100644
--- a/lib/simple_set.rb
+++ b/lib/simple_set.rb
@@ -1,7 +1,7 @@
module Scrooge
class SimpleSet < Hash
-
+
class << self
##
# Creates a new set containing the given objects
@@ -13,7 +13,7 @@ def [](*ary)
new(ary)
end
end
-
+
##
# Create a new SimpleSet containing the unique members of _arr_
#
@@ -25,7 +25,7 @@ def [](*ary)
def initialize(arr = [])
Array(arr).each {|x| self[x] = true}
end
-
+
##
# Add a value to the set, and return it
#
@@ -38,7 +38,7 @@ def <<(value)
self[value] = true
self
end
-
+
##
# Merge _arr_ with receiver, producing the union of receiver & _arr_
#
@@ -54,7 +54,7 @@ def merge(arr)
super(arr.inject({}) {|s,x| s[x] = true; s })
end
alias_method :|, :merge
-
+
##
# Invokes block once for each item in the set. Creates an array
# containing the values returned by the block.
@@ -69,7 +69,7 @@ def collect(&block)
keys.collect(&block)
end
alias_method :map, :collect
-
+
##
# Get a human readable version of the set.
#
@@ -82,10 +82,10 @@ def collect(&block)
def inspect
"#