diff options
Diffstat (limited to 'activerecord/lib/active_record')
4 files changed, 57 insertions, 19 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 44e407a561..5b9c9770df 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -522,7 +522,11 @@ module ActiveRecord end def copy_table(from, to, options = {}) #:nodoc: - options = options.merge(:id => (!columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s)) + from_primary_key = primary_key(from) + options[:primary_key] = from_primary_key if from_primary_key != 'id' + unless options[:primary_key] + options[:id] = columns(from).detect{|c| c.name == 'id'}.present? && from_primary_key == 'id' + end create_table(to, options) do |definition| @definition = definition columns(from).each do |column| @@ -536,7 +540,7 @@ module ActiveRecord :precision => column.precision, :scale => column.scale, :null => column.null) end - @definition.primary_key(primary_key(from)) if primary_key(from) + @definition.primary_key(from_primary_key) if from_primary_key yield @definition if block_given? end diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index ed555e4bf6..07b5047d28 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -127,10 +127,16 @@ module ActiveRecord object.is_a?(self) end + # Returns an instance of +Arel::Table+ loaded with the curent table name. + # + # class Post < ActiveRecord::Base + # scope :published_and_commented, published.and(self.arel_table[:comments_count].gt(0)) + # end def arel_table @arel_table ||= Arel::Table.new(table_name, arel_engine) end + # Returns the Arel engine. def arel_engine @arel_engine ||= connection_handler.retrieve_connection_pool(self) ? self : active_record_super.arel_engine end @@ -204,7 +210,7 @@ module ActiveRecord self end - + ## # :method: clone # Identical to Ruby's clone method. This is a "shallow" copy. Be warned that your attributes are not copied. @@ -219,9 +225,9 @@ module ActiveRecord # # user.object_id == new_user.object_id # => false # user.name.object_id == new_user.name.object_id # => true - # + # # user.name.object_id == user.dup.name.object_id # => false - + ## # :method: dup # Duped objects have no id assigned and are treated as new records. Note @@ -230,7 +236,7 @@ module ActiveRecord # specific and is therefore left to the application to implement according # to its need. # The dup method does not preserve the timestamps (created|updated)_(at|on). - + ## def initialize_dup(other) # :nodoc: cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 3ce9995031..aa2f325f74 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -108,15 +108,36 @@ module ActiveRecord 0 end - # This method is designed to perform select by a single column as direct SQL query - # Returns <tt>Array</tt> with values of the specified column name - # The values has same data type as column. + # Use <tt>pluck</tt> as a shortcut to select a single attribute without + # loading a bunch of records just to grab one attribute you want. + # + # Person.pluck(:name) + # + # instead of + # + # Person.all.map(&:name) + # + # Pluck returns an <tt>Array</tt> of attribute values type-casted to match + # the plucked column name, if it can be deduced. Plucking a SQL fragment + # returns String values by default. # # Examples: # - # Person.pluck(:id) # SELECT people.id FROM people - # Person.uniq.pluck(:role) # SELECT DISTINCT role FROM people - # Person.where(:age => 21).limit(5).pluck(:id) # SELECT people.id FROM people WHERE people.age = 21 LIMIT 5 + # Person.pluck(:id) + # # SELECT people.id FROM people + # # => [1, 2, 3] + # + # Person.uniq.pluck(:role) + # # SELECT DISTINCT role FROM people + # # => ['admin', 'member', 'guest'] + # + # Person.where(:age => 21).limit(5).pluck(:id) + # # SELECT people.id FROM people WHERE people.age = 21 LIMIT 5 + # # => [2, 3] + # + # Person.pluck('DATEDIFF(updated_at, created_at)') + # # SELECT DATEDIFF(updated_at, created_at) FROM people + # # => ['0', '27761', '173'] # def pluck(column_name) key = column_name.to_s.split('.', 2).last @@ -130,7 +151,8 @@ module ActiveRecord column = types[key] result.map do |attributes| - value = klass.initialize_attributes(attributes)[key] + raise ArgumentError, "Pluck expects to select just one attribute: #{attributes.inspect}" unless attributes.one? + value = klass.initialize_attributes(attributes).first[1] if column column.type_cast value else diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb index 1c7b839e5e..ce2ea85ef9 100644 --- a/activerecord/lib/active_record/store.rb +++ b/activerecord/lib/active_record/store.rb @@ -10,15 +10,21 @@ module ActiveRecord # Make sure that you declare the database column used for the serialized store as a text, so there's # plenty of room. # + # You can set custom coder to encode/decode your serialized attributes to/from different formats. + # JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+. + # + # String keys should be used for direct access to virtual attributes because of most of the coders do not + # distinguish symbols and strings as keys. + # # Examples: # # class User < ActiveRecord::Base - # store :settings, accessors: [ :color, :homepage ] + # store :settings, accessors: [ :color, :homepage ], coder: JSON # end # # u = User.new(color: 'black', homepage: '37signals.com') - # u.color # Accessor stored attribute - # u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor + # u.color # Accessor stored attribute + # u.settings['country'] = 'Denmark' # Any attribute, even if not specified with an accessor # # # Add additional accessors to an existing store through store_accessor # class SuperUser < User @@ -29,7 +35,7 @@ module ActiveRecord module ClassMethods def store(store_attribute, options = {}) - serialize store_attribute, Hash + serialize store_attribute, options.fetch(:coder, Hash) store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors end @@ -37,13 +43,13 @@ module ActiveRecord keys.flatten.each do |key| define_method("#{key}=") do |value| send("#{store_attribute}=", {}) unless send(store_attribute).is_a?(Hash) - send(store_attribute)[key] = value + send(store_attribute)[key.to_s] = value send("#{store_attribute}_will_change!") end define_method(key) do send("#{store_attribute}=", {}) unless send(store_attribute).is_a?(Hash) - send(store_attribute)[key] + send(store_attribute)[key.to_s] end end end |