diff options
Diffstat (limited to 'activerecord/lib')
9 files changed, 51 insertions, 96 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index c2f725445e..c26119287a 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1052,20 +1052,15 @@ module ActiveRecord #:nodoc: # Each dynamic finder using <tt>scoped_by_*</tt> is also defined in the class after it # is first invoked, so that future attempts to use it do not run through method_missing. def method_missing(method_id, *arguments, &block) - if match = DynamicFinderMatch.match(method_id) + if match = (DynamicFinderMatch.match(method_id) || DynamicScopeMatch.match(method_id)) attribute_names = match.attribute_names super unless all_attributes_exists?(attribute_names) - if match.finder? - options = arguments.extract_options! - relation = options.any? ? scoped(options) : scoped - relation.send :find_by_attributes, match, attribute_names, *arguments, &block - elsif match.instantiator? - scoped.send :find_or_instantiator_by_attributes, match, attribute_names, *arguments, &block + if arguments.size < attribute_names.size + method_trace = "#{__FILE__}:#{__LINE__}:in `#{method_id}'" + backtrace = [method_trace] + caller + raise ArgumentError, "wrong number of arguments (#{arguments.size} for #{attribute_names.size})", backtrace end - elsif match = DynamicScopeMatch.match(method_id) - attribute_names = match.attribute_names - super unless all_attributes_exists?(attribute_names) - if match.scope? + if match.respond_to?(:scope?) && match.scope? self.class_eval <<-METHOD, __FILE__, __LINE__ + 1 def self.#{method_id}(*args) # def self.scoped_by_user_name_and_password(*args) attributes = Hash[[:#{attribute_names.join(',:')}].zip(args)] # attributes = Hash[[:user_name, :password].zip(args)] @@ -1074,6 +1069,12 @@ module ActiveRecord #:nodoc: end # end METHOD send(method_id, *arguments) + elsif match.finder? + options = arguments.extract_options! + relation = options.any? ? scoped(options) : scoped + relation.send :find_by_attributes, match, attribute_names, *arguments, &block + elsif match.instantiator? + scoped.send :find_or_instantiator_by_attributes, match, attribute_names, *arguments, &block end else super @@ -1737,7 +1738,7 @@ MSG end # Returns an <tt>#inspect</tt>-like string for the value of the - # attribute +attr_name+. String attributes are elided after 50 + # attribute +attr_name+. String attributes are truncated upto 50 # characters, and Date and Time attributes are returned in the # <tt>:db</tt> format. Other attributes return the value of # <tt>#inspect</tt> without modification. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb index bcd3abc08d..123b3654e6 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb @@ -46,6 +46,12 @@ module ActiveRecord # "database" => "path/to/dbfile" # ) # + # Or a URL: + # + # ActiveRecord::Base.establish_connection( + # "postgres://myuser:mypass@localhost/somedatabase" + # ) + # # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError # may be returned on an error. def self.establish_connection(spec = nil) @@ -58,6 +64,8 @@ module ActiveRecord when Symbol, String if configuration = configurations[spec.to_s] establish_connection(configuration) + elsif spec.is_a?(String) && hash = connection_url_to_hash(spec) + establish_connection(hash) else raise AdapterNotSpecified, "#{spec} database is not configured" end @@ -81,6 +89,24 @@ module ActiveRecord end end + def self.connection_url_to_hash(url) # :nodoc: + config = URI.parse url + adapter = config.scheme + adapter = "postgresql" if adapter == "postgres" + spec = { :adapter => adapter, + :username => config.user, + :password => config.password, + :port => config.port, + :database => config.path.sub(%r{^/},""), + :host => config.host } + spec.reject!{ |_,value| !value } + if config.query + options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys + spec.merge!(options) + end + spec + end + class << self # Returns the connection currently associated with the class. This can # also be used to "borrow" the connection to do database work unrelated diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 724b2e6d9c..e2a0f63393 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -157,6 +157,11 @@ module ActiveRecord end end + def type_cast(value, column) # :nodoc: + return super unless BigDecimal === value + + value.to_f + end # DATABASE STATEMENTS ====================================== diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index c459846264..507f345ef5 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -1,3 +1,5 @@ +require "active_support/core_ext/module/delegation" +require "active_support/core_ext/class/attribute_accessors" require "active_support/core_ext/array/wrap" module ActiveRecord diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 53617059d0..2dbebfcaf8 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -383,7 +383,7 @@ module ActiveRecord attributes_collection = if keys.include?('id') || keys.include?(:id) Array.wrap(attributes_collection) else - attributes_collection.sort_by { |i, _| i.to_i }.map { |_, attributes| attributes } + attributes_collection.values end end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 44e5520230..0ee7e20cf1 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -115,7 +115,8 @@ db_namespace = namespace :db do end end else - $stderr.puts "#{config['database']} already exists" + # Bug with 1.9.2 Calling return within begin still executes else + $stderr.puts "#{config['database']} already exists" unless config['adapter'] =~ /sqlite/ end end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 283115a448..8cef4e5554 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -243,7 +243,7 @@ module ActiveRecord end def construct_limited_ids_condition(relation) - orders = relation.order_values + orders = relation.order_values.map { |val| val.presence }.compact values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders) relation = relation.dup diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb index e3185a9c5a..5ad40d8cd9 100644 --- a/activerecord/lib/active_record/serialization.rb +++ b/activerecord/lib/active_record/serialization.rb @@ -10,46 +10,8 @@ module ActiveRecord #:nodoc: options[:except] = Array.wrap(options[:except]).map { |n| n.to_s } options[:except] |= Array.wrap(self.class.inheritance_column) - hash = super(options) - - serializable_add_includes(options) do |association, records, opts| - hash[association] = records.is_a?(Enumerable) ? - records.map { |r| r.serializable_hash(opts) } : - records.serializable_hash(opts) - end - - hash + super(options) end - - private - # Add associations specified via the <tt>:include</tt> option. - # - # Expects a block that takes as arguments: - # +association+ - name of the association - # +records+ - the association record(s) to be serialized - # +opts+ - options for the association records - def serializable_add_includes(options = {}) - return unless include_associations = options.delete(:include) - - include_has_options = include_associations.is_a?(Hash) - associations = include_has_options ? include_associations.keys : Array.wrap(include_associations) - - associations.each do |association| - records = case self.class.reflect_on_association(association).macro - when :has_many, :has_and_belongs_to_many - send(association).to_a - when :has_one, :belongs_to - send(association) - end - - if records - association_options = include_has_options ? include_associations[association] : {} - yield(association, records, association_options) - end - end - - options[:include] = include_associations - end end end diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb index f8e6cf958c..cbfa1ad609 100644 --- a/activerecord/lib/active_record/serializers/xml_serializer.rb +++ b/activerecord/lib/active_record/serializers/xml_serializer.rb @@ -182,48 +182,6 @@ module ActiveRecord #:nodoc: options[:except] |= Array.wrap(@serializable.class.inheritance_column) end - def add_extra_behavior - add_includes - end - - def add_includes - procs = options.delete(:procs) - @serializable.send(:serializable_add_includes, options) do |association, records, opts| - add_associations(association, records, opts) - end - options[:procs] = procs - end - - # TODO This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well. - def add_associations(association, records, opts) - association_name = association.to_s.singularize - merged_options = options.merge(opts).merge!(:root => association_name, :skip_instruct => true) - - if records.is_a?(Enumerable) - tag = ActiveSupport::XmlMini.rename_key(association.to_s, options) - type = options[:skip_types] ? { } : {:type => "array"} - - if records.empty? - @builder.tag!(tag, type) - else - @builder.tag!(tag, type) do - records.each do |record| - if options[:skip_types] - record_type = {} - else - record_class = (record.class.to_s.underscore == association_name) ? nil : record.class.name - record_type = {:type => record_class} - end - - record.to_xml merged_options.merge(record_type) - end - end - end - elsif record = @serializable.send(association) - record.to_xml(merged_options) - end - end - class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc: def compute_type klass = @serializable.class |