root/trunk/config/active_record_patch.rb

Revision 707, 4.5 kB (checked in by jarmo, 1 year ago)
  • Adds the Customer type
Line 
1 # Patch to ActiveRecord::Base, which makes abstract models sub-classes
2 # using single table inheritance function correctly.
3 # Prevents ActiveRecord::Base#add_conditions!() from adding type conditions to
4 # database queries when a sub-class of an abstract model is using single table inheritance.
5 # Attribute abstract_class has to be set true in every abstract model.
6 #
7 # P.S.
8 # If one still wants to support abstract models without abstract_class set true, one can use:
9 #    def self.descends_from_active_record?
10 #      base_class == self || !column_names.include?(inheritance_column)
11 #    end
12 # Although I can't see why anyone would want to do this.
13 module ActiveRecord
14   class Base
15     class << self
16       def descends_from_active_record?
17         base_class == self
18       end
19     end
20   end
21 end
22
23 # Patch to ActiveRecord::ConnectionAdapters.
24 # Fixes quoting of binary (blob) values on SQLite.
25 # Previous implementation freguently caused data corruption.
26 module ActiveRecord
27   module ConnectionAdapters
28     class SQLiteColumn
29       class << self
30         def string_to_binary(value)
31           value.gsub('%', '%25').gsub("\0", '%00')
32         end
33
34         def binary_to_string(value)
35           value.gsub('%00', "\0").gsub('%25', '%')
36         end
37       end
38     end
39   end
40 end
41
42 # Patch to ActiveRecord::ConnectionAdapters::SqliteAdapter#add_column
43 # Fixed a bug that made add_column to raise an error when called
44 # inside a transaction. The error was caused by the execution of
45 # 'VACUUM', which can't be called when there is an active transaction.
46 # This may break sqlite versions piror to 3.1.3.
47 module ActiveRecord
48   module ConnectionAdapters
49     # For some reason this is required for this to work.
50     class SQLite3Adapter
51       def add_column(table_name, column_name, type, options = {})
52         super(table_name, column_name, type, options)
53       end
54     end
55
56     # Overwrite add_column so that it only executes 'VACUUM' if there are
57     # no active transactions.
58     class SQLiteAdapter
59       def add_column(table_name, column_name, type, options = {}) #:nodoc:
60         super(table_name, column_name, type, options)
61         # See last paragraph on http://www.sqlite.org/lang_altertable.html
62         # and http://www.sqlite.org/lang_vacuum.html
63         execute "VACUUM" unless @connection.transaction_active?
64       end
65     end
66   end
67 end
68
69 # Patch to ActiveRecord::ConnectionAdapaters::PostgreSQLAdapter#quote
70 # Binary strings are quoted using the escape string syntax (E'...')
71 module ActiveRecord
72   module ConnectionAdapters
73     class PostgreSQLAdapter
74       alias_method :quote_old, :quote
75
76       def quote(value, column = nil)
77         result = quote_old(value, column)
78         if value.kind_of?(String) and result.match(/^'/) and column and column.type == :binary
79           result = 'E' + result
80         end
81         return result
82       end
83     end
84   end
85 end
86
87 # Patch to ActiveRecord::Validations::ClassMethods#validates_uniqueness_of.
88 # Makes the uniqueness validation work correctly with Single Table Inheritance.
89 # See the Rails Trac: http://dev.rubyonrails.org/ticket/3833
90 module ActiveRecord
91   module Validations
92     module ClassMethods
93       def validates_uniqueness_of(*attr_names)
94         configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken], :case_sensitive => true }
95         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
96
97         validates_each(attr_names,configuration) do |record, attr_name, value|
98           if value.nil? || (configuration[:case_sensitive] || !columns_hash[attr_name.to_s].text?)
99             condition_sql = "#{record.class.table_name}.#{attr_name} #{attribute_condition(value)}"
100             condition_params = [value]
101           else
102             condition_sql = "LOWER(#{record.class.table_name}.#{attr_name}) #{attribute_condition(value)}"
103             condition_params = [value.downcase]
104           end
105           if scope = configuration[:scope]
106             Array(scope).map do |scope_item|
107               scope_value = record.send(scope_item)
108               condition_sql << " AND #{record.class.table_name}.#{scope_item} #{attribute_condition(scope_value)}"
109               condition_params << scope_value
110             end
111           end
112           unless record.new_record?
113             condition_sql << " AND #{record.class.table_name}.#{record.class.primary_key} <> ?"
114             condition_params << record.send(:id)
115           end
116           if self.find(:first, :conditions => [condition_sql, *condition_params])
117             record.errors.add(attr_name, configuration[:message])
118           end
119         end
120       end
121     end
122   end
123 end
Note: See TracBrowser for help on using the browser.

© 2004-2007 Norfello Oy All Rights Reserved