diff options
Diffstat (limited to 'activerecord/lib/active_record')
16 files changed, 104 insertions, 76 deletions
diff --git a/activerecord/lib/active_record/association_relation.rb b/activerecord/lib/active_record/association_relation.rb index e2976577f6..20516bba0c 100644 --- a/activerecord/lib/active_record/association_relation.rb +++ b/activerecord/lib/active_record/association_relation.rb @@ -5,6 +5,10 @@ module ActiveRecord @association = association end + def proxy_association + @association + end + private def exec_queries diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 5e5995f566..3490057298 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -172,7 +172,7 @@ module ActiveRecord @association_cache[name] = association end - # Associations are a set of macro-like class methods for tying objects together through + # \Associations are a set of macro-like class methods for tying objects together through # foreign keys. They express relationships like "Project has one Project Manager" # or "Project belongs to a Portfolio". Each macro adds a number of methods to the # class which are specialized according to the collection or association symbol and the @@ -365,11 +365,11 @@ module ActiveRecord # there is some special behavior you should be aware of, mostly involving the saving of # associated objects. # - # You can set the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>, + # You can set the <tt>:autosave</tt> option on a <tt>has_one</tt>, <tt>belongs_to</tt>, # <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association. Setting it # to +true+ will _always_ save the members, whereas setting it to +false+ will - # _never_ save the members. More details about :autosave option is available at - # autosave_association.rb . + # _never_ save the members. More details about <tt>:autosave</tt> option is available at + # AutosaveAssociation. # # === One-to-one associations # @@ -402,7 +402,7 @@ module ActiveRecord # # == Customizing the query # - # Associations are built from <tt>Relation</tt>s, and you can use the <tt>Relation</tt> syntax + # \Associations are built from <tt>Relation</tt>s, and you can use the <tt>Relation</tt> syntax # to customize them. For example, to add a condition: # # class Blog < ActiveRecord::Base @@ -568,6 +568,8 @@ module ActiveRecord # @group.avatars << Avatar.new # this would work if User belonged_to Avatar rather than the other way around # @group.avatars.delete(@group.avatars.last) # so would this # + # == Setting Inverses + # # If you are using a +belongs_to+ on the join model, it is a good idea to set the # <tt>:inverse_of</tt> option on the +belongs_to+, which will mean that the following example # works correctly (where <tt>tags</tt> is a +has_many+ <tt>:through</tt> association): @@ -584,7 +586,26 @@ module ActiveRecord # belongs_to :tag, inverse_of: :taggings # end # - # == Nested Associations + # If you do not set the +:inverse_of+ record, the association will do its + # best to match itself up with the correct inverse. Automatic +:inverse_of+ + # detection only works on +has_many+, +has_one+, and +belongs_to+ associations. + # + # Extra options on the associations, as defined in the + # <tt>AssociationReflection::INVALID_AUTOMATIC_INVERSE_OPTIONS</tt> constant, will + # also prevent the association's inverse from being found automatically. + # + # The automatic guessing of the inverse association uses a heuristic based + # on the name of the class, so it may not work for all associations, + # especially the ones with non-standard names. + # + # You can turn off the automatic detection of inverse associations by setting + # the +:automatic_inverse_of+ option to +false+ like so: + # + # class Taggable < ActiveRecord::Base + # belongs_to :tag, automatic_inverse_of: false + # end + # + # == Nested \Associations # # You can actually specify *any* association with the <tt>:through</tt> option, including an # association which has a <tt>:through</tt> option itself. For example: @@ -627,7 +648,7 @@ module ActiveRecord # add a <tt>Commenter</tt> in the example above, there would be no way to tell how to set up the # intermediate <tt>Post</tt> and <tt>Comment</tt> objects. # - # == Polymorphic Associations + # == Polymorphic \Associations # # Polymorphic associations on models are not restricted on what types of models they # can be associated with. Rather, they specify an interface that a +has_many+ association @@ -789,7 +810,7 @@ module ActiveRecord # For example if all the addressables are either of class Person or Company then a total # of 3 queries will be executed. The list of addressable types to load is determined on # the back of the addresses loaded. This is not supported if Active Record has to fallback - # to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError. + # to the previous implementation of eager loading and will raise <tt>ActiveRecord::EagerLoadPolymorphicError</tt>. # The reason is that the parent model's type is a column value so its corresponding table # name cannot be put in the +FROM+/+JOIN+ clauses of that query. # @@ -1024,7 +1045,7 @@ module ActiveRecord # An empty array is returned if none are found. # [collection<<(object, ...)] # Adds one or more objects to the collection by setting their foreign keys to the collection's primary key. - # Note that this operation instantly fires update sql without waiting for the save or update call on the + # Note that this operation instantly fires update SQL without waiting for the save or update call on the # parent object, unless the parent object is a new record. # [collection.delete(object, ...)] # Removes one or more objects from the collection by setting their foreign keys to +NULL+. @@ -1060,10 +1081,10 @@ module ActiveRecord # [collection.size] # Returns the number of associated objects. # [collection.find(...)] - # Finds an associated object according to the same rules as ActiveRecord::Base.find. + # Finds an associated object according to the same rules as <tt>ActiveRecord::Base.find</tt>. # [collection.exists?(...)] # Checks whether an associated object with the given conditions exists. - # Uses the same rules as ActiveRecord::Base.exists?. + # Uses the same rules as <tt>ActiveRecord::Base.exists?</tt>. # [collection.build(attributes = {}, ...)] # Returns one or more new objects of the collection type that have been instantiated # with +attributes+ and linked to this object through a foreign key, but have not yet @@ -1082,7 +1103,7 @@ module ActiveRecord # # === Example # - # Example: A Firm class declares <tt>has_many :clients</tt>, which will add: + # A <tt>Firm</tt> class declares <tt>has_many :clients</tt>, which will add: # * <tt>Firm#clients</tt> (similar to <tt>Client.where(firm_id: id)</tt>) # * <tt>Firm#clients<<</tt> # * <tt>Firm#clients.delete</tt> @@ -1116,8 +1137,8 @@ module ActiveRecord # Controls what happens to the associated objects when # their owner is destroyed. Note that these are implemented as # callbacks, and Rails executes callbacks in order. Therefore, other - # similar callbacks may affect the :dependent behavior, and the - # :dependent behavior may affect other callbacks. + # similar callbacks may affect the <tt>:dependent</tt> behavior, and the + # <tt>:dependent</tt> behavior may affect other callbacks. # # * <tt>:destroy</tt> causes all the associated objects to also be destroyed. # * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed). @@ -1163,8 +1184,8 @@ module ActiveRecord # If true, always save the associated objects or destroy them if marked for destruction, # when saving the parent object. If false, never save or destroy the associated objects. # By default, only save associated objects that are new records. This option is implemented as a - # before_save callback. Because callbacks are run in the order they are defined, associated objects - # may need to be explicitly saved in any user-defined before_save callbacks. + # +before_save+ callback. Because callbacks are run in the order they are defined, associated objects + # may need to be explicitly saved in any user-defined +before_save+ callbacks. # # Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>. # [:inverse_of] @@ -1189,7 +1210,7 @@ module ActiveRecord # Specifies a one-to-one association with another class. This method should only be used # if the other class contains the foreign key. If the current class contains the foreign key, # then you should use +belongs_to+ instead. See also ActiveRecord::Associations::ClassMethods's overview - # on when to use has_one and when to use belongs_to. + # on when to use +has_one+ and when to use +belongs_to+. # # The following methods for retrieval and query of a single associated object will be added: # @@ -1357,7 +1378,7 @@ module ActiveRecord # class is created and decremented when it's destroyed. This requires that a column # named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class) # is used on the associate class (such as a Post class) - that is the migration for - # <tt>#{table_name}_count</tt> is created on the associate class (such that Post.comments_count will + # <tt>#{table_name}_count</tt> is created on the associate class (such that <tt>Post.comments_count</tt> will # return the count cached, see note below). You can also specify a custom counter # cache column by providing a column name instead of a +true+/+false+ value to this # option (e.g., <tt>counter_cache: :my_custom_counter</tt>.) @@ -1439,7 +1460,7 @@ module ActiveRecord # [collection<<(object, ...)] # Adds one or more objects to the collection by creating associations in the join table # (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method). - # Note that this operation instantly fires update sql without waiting for the save or update call on the + # Note that this operation instantly fires update SQL without waiting for the save or update call on the # parent object, unless the parent object is a new record. # [collection.delete(object, ...)] # Removes one or more objects from the collection by removing their associations from the join table. @@ -1462,10 +1483,10 @@ module ActiveRecord # [collection.find(id)] # Finds an associated object responding to the +id+ and that # meets the condition that it has to be associated with this object. - # Uses the same rules as ActiveRecord::Base.find. + # Uses the same rules as <tt>ActiveRecord::Base.find</tt>. # [collection.exists?(...)] # Checks whether an associated object with the given conditions exists. - # Uses the same rules as ActiveRecord::Base.exists?. + # Uses the same rules as <tt>ActiveRecord::Base.exists?</tt>. # [collection.build(attributes = {})] # Returns a new object of the collection type that has been instantiated # with +attributes+ and linked to this object through the join table, but has not yet been saved. diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 56e57cc36e..71b64de5ea 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -847,9 +847,7 @@ module ActiveRecord # Returns a <tt>Relation</tt> object for the records in this association def scope - @association.scope.tap do |scope| - scope.proxy_association = @association - end + @association.scope end # :nodoc: diff --git a/activerecord/lib/active_record/associations/join_dependency.rb b/activerecord/lib/active_record/associations/join_dependency.rb index 28e081c03c..5b2f2d1902 100644 --- a/activerecord/lib/active_record/associations/join_dependency.rb +++ b/activerecord/lib/active_record/associations/join_dependency.rb @@ -55,6 +55,13 @@ module ActiveRecord join_parts.first end + def join_relation(relation) + join_associations.each do |association| + relation = association.join_relation(relation) + end + relation + end + def columns join_parts.collect { |join_part| table = join_part.aliased_table diff --git a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb index a23baeaced..f596a8b02e 100644 --- a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb +++ b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb @@ -41,8 +41,9 @@ module ActiveRecord # task.read_attribute_before_type_cast('id') # => '1' # task.read_attribute('completed_on') # => Sun, 21 Oct 2012 # task.read_attribute_before_type_cast('completed_on') # => "2012-10-21" + # task.read_attribute_before_type_cast(:completed_on) # => "2012-10-21" def read_attribute_before_type_cast(attr_name) - @attributes[attr_name] + @attributes[attr_name.to_s] end # Returns a hash of attributes before typecasting and deserialization. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 566550cbe2..aabedf15e9 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -65,8 +65,7 @@ module ActiveRecord # Appends a primary key definition to the table definition. # Can be called multiple times, but this is probably not a good idea. def primary_key(name, type = :primary_key, options = {}) - options[:primary_key] = true - column(name, type, options) + column(name, type, options.merge(:primary_key => true)) end # Returns a ColumnDefinition for the column with name +name+. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 9c0c4e3ef0..8ffe150de6 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -706,12 +706,21 @@ module ActiveRecord end # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause. - # Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax. # - # distinct("posts.id", "posts.created_at desc") + # distinct("posts.id", ["posts.created_at desc"]) # def distinct(columns, order_by) - "DISTINCT #{columns}" + ActiveSupport::Deprecation.warn("#distinct is deprecated and shall be removed from future releases.") + "DISTINCT #{columns_for_distinct(columns, order_by)}" + end + + # Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT. + # Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax - they + # require the order columns appear in the SELECT. + # + # columns_for_distinct("posts.id", ["posts.created_at desc"]) + def columns_for_distinct(columns, orders) # :nodoc: + columns end # Adds timestamps (+created_at+ and +updated_at+) columns to the named table. diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index 98916b06a5..a651b6c32e 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -467,22 +467,17 @@ module ActiveRecord end end - # Returns a SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause. - # # PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and # requires that the ORDER BY include the distinct column. - # - # distinct("posts.id", ["posts.created_at desc"]) - # # => "DISTINCT posts.id, posts.created_at AS alias_0" - def distinct(columns, orders) #:nodoc: - order_columns = orders.map{ |s| + def columns_for_distinct(columns, orders) #:nodoc: + order_columns = orders.reject(&:blank?).map{ |s| # Convert Arel node to string s = s.to_sql unless s.is_a?(String) # Remove any ASC/DESC modifiers s.gsub(/\s+(ASC|DESC)\s*(NULLS\s+(FIRST|LAST)\s*)?/i, '') }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" } - [super].concat(order_columns).join(', ') + [super, *order_columns].join(', ') end end end diff --git a/activerecord/lib/active_record/explain_subscriber.rb b/activerecord/lib/active_record/explain_subscriber.rb index a3bc56d600..6a49936644 100644 --- a/activerecord/lib/active_record/explain_subscriber.rb +++ b/activerecord/lib/active_record/explain_subscriber.rb @@ -19,7 +19,7 @@ module ActiveRecord # On the other hand, we want to monitor the performance of our real database # queries, not the performance of the access to the query cache. IGNORED_PAYLOADS = %w(SCHEMA EXPLAIN CACHE) - EXPLAINED_SQLS = /\A\s*(select|update|delete|insert)/i + EXPLAINED_SQLS = /\A\s*(select|update|delete|insert)\b/i def ignore_payload?(payload) payload[:exception] || IGNORED_PAYLOADS.include?(payload[:name]) || payload[:sql] !~ EXPLAINED_SQLS end diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 6c020e1d57..511a1585a7 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -668,6 +668,7 @@ module ActiveRecord copied end + # Determines the version number of the next migration. def next_migration_number(number) if ActiveRecord::Base.timestamped_migrations [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 0ba860a186..1f76adb367 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -8,7 +8,7 @@ module ActiveRecord self.reflections = {} end - # Reflection enables to interrogate Active Record classes and objects + # \Reflection enables to interrogate Active Record classes and objects # about their associations and aggregations. This information can, # for example, be used in a form builder that takes an Active Record object # and creates input fields for all of the attributes depending on their type @@ -100,7 +100,7 @@ module ActiveRecord # Returns the hash of options used for the macro. # # <tt>composed_of :balance, class_name: 'Money'</tt> returns <tt>{ class_name: "Money" }</tt> - # <tt>has_many :clients</tt> returns +{}+ + # <tt>has_many :clients</tt> returns <tt>{}</tt> attr_reader :options attr_reader :active_record @@ -449,8 +449,8 @@ module ActiveRecord # Checks to see if the reflection doesn't have any options that prevent # us from being able to guess the inverse automatically. First, the # +automatic_inverse_of+ option cannot be set to false. Second, we must - # have :has_many, :has_one, :belongs_to associations. Third, we must - # not have options such as :class_name or :polymorphic which prevent us + # have +has_many+, +has_one+, +belongs_to+ associations. Third, we must + # not have options such as +:polymorphic+ or +:foreign_key+ which prevent us # from correctly guessing the inverse association. # # Anything with a scope can additionally ruin our attempt at finding an @@ -493,7 +493,7 @@ module ActiveRecord delegate :foreign_key, :foreign_type, :association_foreign_key, :active_record_primary_key, :type, :to => :source_reflection - # Gets the source of the through reflection. It checks both a singularized + # Returns the source of the through reflection. It checks both a singularized # and pluralized form for <tt>:belongs_to</tt> or <tt>:has_many</tt>. # # class Post < ActiveRecord::Base @@ -507,8 +507,7 @@ module ActiveRecord # end # # tags_reflection = Post.reflect_on_association(:tags) - # - # taggings_reflection = tags_reflection.source_reflection + # tags_reflection.source_reflection # # => <ActiveRecord::Reflection::AssociationReflection: @macro=:belongs_to, @name=:tag, @active_record=Tagging, @plural_name="tags"> # def source_reflection @@ -524,7 +523,8 @@ module ActiveRecord # end # # tags_reflection = Post.reflect_on_association(:tags) - # taggings_reflection = tags_reflection.through_reflection + # tags_reflection.through_reflection + # # => <ActiveRecord::Reflection::AssociationReflection: @macro=:has_many, @name=:taggings, @active_record=Post, @plural_name="taggings"> # def through_reflection @through_reflection ||= active_record.reflect_on_association(options[:through]) diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 913f6f88f2..ae3fa85da9 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -17,7 +17,7 @@ module ActiveRecord include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation attr_reader :table, :klass, :loaded - attr_accessor :default_scoped, :proxy_association + attr_accessor :default_scoped alias :model :klass alias :loaded? :loaded alias :default_scoped? :default_scoped diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 72e9272cd7..ba222aac93 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -160,7 +160,7 @@ module ActiveRecord conditions = conditions.id if Base === conditions return false if !conditions - join_dependency = construct_join_dependency_for_association_find + join_dependency = construct_join_dependency relation = construct_relation_for_association_find(join_dependency) relation = relation.except(:select, :order).select("1 AS one").limit(1) @@ -201,7 +201,7 @@ module ActiveRecord protected def find_with_associations - join_dependency = construct_join_dependency_for_association_find + join_dependency = construct_join_dependency relation = construct_relation_for_association_find(join_dependency) rows = connection.select_all(relation, 'SQL', relation.bind_values.dup) join_dependency.instantiate(rows) @@ -209,45 +209,37 @@ module ActiveRecord [] end - def construct_join_dependency_for_association_find + def construct_join_dependency(joins = []) including = (eager_load_values + includes_values).uniq - ActiveRecord::Associations::JoinDependency.new(@klass, including, []) + ActiveRecord::Associations::JoinDependency.new(@klass, including, joins) end def construct_relation_for_association_calculations - including = (eager_load_values + includes_values).uniq - join_dependency = ActiveRecord::Associations::JoinDependency.new(@klass, including, arel.froms.first) - relation = except(:includes, :eager_load, :preload) - apply_join_dependency(relation, join_dependency) + apply_join_dependency(self, construct_join_dependency(arel.froms.first)) end def construct_relation_for_association_find(join_dependency) - relation = except(:includes, :eager_load, :preload, :select).select(join_dependency.columns) + relation = except(:select).select(join_dependency.columns) apply_join_dependency(relation, join_dependency) end def apply_join_dependency(relation, join_dependency) - join_dependency.join_associations.each do |association| - relation = association.join_relation(relation) - end - - limitable_reflections = using_limitable_reflections?(join_dependency.reflections) + relation = relation.except(:includes, :eager_load, :preload) + relation = join_dependency.join_relation(relation) - if !limitable_reflections && relation.limit_value - limited_id_condition = construct_limited_ids_condition(relation.except(:select)) - relation = relation.where(limited_id_condition) + if using_limitable_reflections?(join_dependency.reflections) + relation + else + relation.where!(construct_limited_ids_condition(relation)) if relation.limit_value + relation.except(:limit, :offset) end - - relation = relation.except(:limit, :offset) unless limitable_reflections - - relation end def construct_limited_ids_condition(relation) - orders = relation.order_values.map { |val| val.presence }.compact - values = @klass.connection.distinct("#{quoted_table_name}.#{primary_key}", orders) + values = @klass.connection.columns_for_distinct( + "#{quoted_table_name}.#{quoted_primary_key}", relation.order_values) - relation = relation.dup.select(values) + relation = relation.except(:select).select(values).distinct! id_rows = @klass.connection.select_all(relation.arel, 'SQL', relation.bind_values) ids_array = id_rows.map {|row| row[primary_key]} diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb index bda7a76330..eea43aff0e 100644 --- a/activerecord/lib/active_record/relation/merger.rb +++ b/activerecord/lib/active_record/relation/merger.rb @@ -94,9 +94,7 @@ module ActiveRecord []) relation.joins! rest - join_dependency.join_associations.each do |association| - @relation = association.join_relation(relation) - end + @relation = join_dependency.join_relation(relation) end end diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 9fcd2d06c5..d020f1ba52 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -340,6 +340,9 @@ module ActiveRecord # User.where(name: "John", active: true).unscope(where: :name) # == User.where(active: true) # + # This method is applied before the default_scope is applied. So the conditions + # specified in default_scope will not be removed. + # # Note that this method is more generalized than ActiveRecord::SpawnMethods#except # because #except will only affect a particular relation's values. It won't wipe # the order, grouping, etc. when that relation is merged. For example: diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index 3259dbbd80..4bfd0167a4 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -43,7 +43,7 @@ module ActiveRecord unless info[:version].blank? initialize_schema_migrations_table - assume_migrated_upto_version(info[:version], migrations_paths) + connection.assume_migrated_upto_version(info[:version], migrations_paths) end end |