aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/scoping
Commit message (Collapse)AuthorAgeFilesLines
* Enable `Layout/EmptyLinesAroundAccessModifier` copRyuta Kamizono2019-06-132-2/+0
| | | | | | | | | | | We sometimes say "✂️ newline after `private`" in a code review (e.g. https://github.com/rails/rails/pull/18546#discussion_r23188776, https://github.com/rails/rails/pull/34832#discussion_r244847195). Now `Layout/EmptyLinesAroundAccessModifier` cop have new enforced style `EnforcedStyle: only_before` (https://github.com/rubocop-hq/rubocop/pull/7059). That cop and enforced style will reduce the our code review cost.
* Association loading isn't to be affected by null relation scopingRyuta Kamizono2019-04-061-1/+1
| | | | | | Follow up of #35868. Closes #19349.
* Merge pull request #35121 from utilum/warning_tried_to_create_proc_without_blockKasper Timm Hansen2019-03-101-2/+2
|\ | | | | Ruby 2.7 warning: creating a Proc without a block
| * Ruby 2.7 warning: creating a Proc without a blockutilum2019-02-131-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | As of [Revision 66772]( https://bugs.ruby-lang.org/projects/ruby-trunk/repository/trunk/revisions/66772) `Proc.new` without giving a block emits `warning: tried to create Proc object without a block`. This commit fixes cases where Rails test suit tickles this warning. See CI logs: https://travis-ci.org/rails/rails/jobs/487205819#L1161-L1190 https://travis-ci.org/rails/rails/jobs/487205821#L1154-1159 https://travis-ci.org/rails/rails/jobs/487205821#L1160-L1169 https://travis-ci.org/rails/rails/jobs/487205821#L1189 https://travis-ci.org/rails/rails/jobs/487254404#L1307-L1416 https://travis-ci.org/rails/rails/jobs/487254405#L1174-L1191
* | Allow returning nil for `default_scope`Ryuta Kamizono2019-02-281-5/+4
| |
* | Deprecate using class level querying methods if the receiver scope regarded ↵Ryuta Kamizono2019-02-151-1/+9
|/ | | | | | | | | | as leaked This deprecates using class level querying methods if the receiver scope regarded as leaked, since #32380 and #35186 may cause that silently leaking information when people upgrade the app. We need deprecation first before making those.
* Refactor around scopingRyuta Kamizono2019-02-072-10/+2
| | | | | | Don't use `false` as special value to skip to find inherited scope, we could use `skip_inherited_scope = true`, and move `_scoping` back on Relation.
* Chaining named scope is no longer leaking to class level querying methodsRyuta Kamizono2019-02-061-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Active Record uses `scoping` to delegate to named scopes from relations for propagating the chaining source scope. It was needed to restore the source scope in named scopes, but it was caused undesired behavior that pollute all class level querying methods. Example: ```ruby class Topic < ActiveRecord::Base scope :toplevel, -> { where(parent_id: nil) } scope :children, -> { where.not(parent_id: nil) } scope :has_children, -> { where(id: Topic.children.select(:parent_id)) } end # Works as expected. Topic.toplevel.where(id: Topic.children.select(:parent_id)) # Doesn't work due to leaking `toplevel` to `Topic.children`. Topic.toplevel.has_children ``` Since #29301, the receiver in named scopes has changed from the model class to the chaining source scope, so the polluting class level querying methods is no longer required for that purpose. Fixes #14003.
* Module#{define_method,alias_method,undef_method,remove_method} become public ↵Ryuta Kamizono2018-12-211-2/+2
| | | | | | since Ruby 2.5 https://bugs.ruby-lang.org/issues/14133
* Generate delegation methods to named scope in the definition timeRyuta Kamizono2018-10-091-0/+2
| | | | | | | | | | | | | | | | | | | The delegation methods to named scope are defined when `method_missing` is invoked on the relation. Since #29301, the receiver in the named scope is changed to the relation like others (e.g. `default_scope`, etc) for consistency. Most named scopes would be delegated from relation by `method_missing`, since we don't allow scopes to be defined which conflict with instance methods on `Relation` (#31179). But if a named scope is defined with the same name as any method on the `superclass` (e.g. `Kernel.open`), the `method_missing` on the relation is not invoked. To address the issue, make the delegation methods to named scope is generated in the definition time. Fixes #34098.
* Don't expose `current_scope` for internal useRyuta Kamizono2018-09-111-8/+6
|
* Move `scoping` handling into klass level from relationRyuta Kamizono2018-09-111-1/+8
| | | | | I'd like to use this `scoping` handling on klass level to address unwanted internal scoping issues.
* Remove redundant `all.scoping`Ryuta Kamizono2018-09-111-4/+2
| | | | | `scoping` stashes the reciever and then returning that as `klass.all`. `all.scoping` has no effect to the public behavior, so it is redundant.
* Bring back private class methods accessibility in named scopeRyuta Kamizono2018-03-271-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The receiver in a scope was changed from `klass` to `relation` itself for all scopes (named scope, default_scope, and association scope) behaves consistently. In addition. Before 5.2, if both an AR model class and a Relation instance have same named methods (e.g. `arel_attribute`, `predicate_builder`, etc), named scope doesn't respect relation instance information. For example: ```ruby class Post < ActiveRecord::Base has_many :comments1, class_name: "RecentComment1" has_many :comments2, class_name: "RecentComment2" end class RecentComment1 < ActiveRecord::Base self.table_name = "comments" default_scope { where(arel_attribute(:created_at).gteq(2.weeks.ago)) } end class RecentComment2 < ActiveRecord::Base self.table_name = "comments" default_scope { recent_updated } scope :recent_updated, -> { where(arel_attribute(:updated_at).gteq(2.weeks.ago)) } end ``` If eager loading `Post.eager_load(:comments1, :comments2).to_a`, `:comments1` (default_scope) respects aliased table name, but `:comments2` (using named scope) may not work correctly since named scope doesn't respect relation instance information. See also 801ccab. But this is a breaking change between releases without deprecation. I decided to bring back private class methods accessibility in named scope. Fixes #31740. Fixes #32331.
* Prevent scope named same as a ActiveRecord::Relation instance method.Chen Kinnrot2017-11-281-0/+6
| | | | | | | | | Due to inconsistent behavior when chaining scopes and one scope named after a Relation method Validation code added in 2 places: - scope, to prevent problematic scope names. - enum, cause it tries to auto define scope.
* Prevent extra `spawn` to make `klass.all` faster (#29009)Ryuta Kamizono2017-11-201-2/+2
| | | | | | | | | | | | | | | | | | | | These extra `spawn` are called via `klass.all` and `klass.all` is called everywhere in the internal. Avoiding the extra `spawn` makes` klass.all` 30% faster for STI classes. https://gist.github.com/kamipo/684d03817a8115848cec8e8b079560b7 ``` Warming up -------------------------------------- fast relation 4.410k i/100ms slow relation 3.334k i/100ms Calculating ------------------------------------- fast relation 47.373k (± 5.2%) i/s - 238.140k in 5.041836s slow relation 35.757k (±15.9%) i/s - 176.702k in 5.104625s Comparison: fast relation: 47373.2 i/s slow relation: 35756.7 i/s - 1.32x slower ```
* `scoping` should respect current class and STI constraint (#29199)Ryuta Kamizono2017-11-061-1/+7
| | | | | | | | A relation includes `klass`, so it can not be used as it is if current class is different from `current_scope.klass`. It should be created new relation by current class to respect the klass and STI constraint. Fixes #17603. Fixes #23576.
* Through scope should not be affected by scopingRyuta Kamizono2017-08-151-0/+10
| | | | | | Follow up of #29834. Fixes #30266.
* Use frozen-string-literal in ActiveRecordKir Shatrov2017-07-192-0/+4
|
* Revert "Merge pull request #29540 from kirs/rubocop-frozen-string"Matthew Draper2017-07-022-2/+0
| | | | | This reverts commit 3420a14590c0e6915d8b6c242887f74adb4120f9, reversing changes made to afb66a5a598ce4ac74ad84b125a5abf046dcf5aa.
* Enforce frozen string in RubocopKir Shatrov2017-07-012-0/+2
|
* Merge pull request #29301 from kamipo/receiver_in_scope_should_be_relationRafael França2017-06-281-1/+1
|\ | | | | The receiver in a scope should be a `relation`
| * The receiver in a scope should be a `relation`Ryuta Kamizono2017-06-011-1/+1
| | | | | | | | | | | | | | Currently the receiver in a scope is `klass`, not `relation`. I think it is a strange because the receiver in `default_scope` and a scope on association is `relation`. I fixed to the receiver is to be a `relation` properly for consistency.
* | Move constructing polymorphic type to `join_scope` in `Reflection`Ryuta Kamizono2017-06-271-2/+1
| |
* | Fix `default_scoped` with defined `default_scope` on STI modelRyuta Kamizono2017-05-311-1/+5
|/ | | | | | | This regression is caused by d1249c1. If STI model is defined `default_scope`, `base_rel` is not respected. I fixed to merge `base_rel` in that case.
* Merge pull request #29098 from kamipo/fix_association_with_extension_issuesMatthew Draper2017-05-301-4/+7
|\ | | | | | | Fix association with extension issues
| * Extract `default_extensions` to avoid `klass.all`Ryuta Kamizono2017-05-301-0/+8
| | | | | | | | | | As @matthewd's suggestion, if `klass` has no default scope, it will more faster.
| * Refactor `default_scoped` to avoid creating extra relation and mergingRyuta Kamizono2017-05-281-7/+2
| |
* | Add option for class_attribute default (#29270)David Heinemeier Hansson2017-05-291-5/+2
| | | | | | | | | | | | | | | | | | | | | | | | * Allow a default value to be declared for class_attribute * Convert to using class_attribute default rather than explicit setter * Removed instance_accessor option by mistake * False is a valid default value * Documentation
* | Enable extending even if scope returns nilRyuta Kamizono2017-05-241-6/+6
|/
* Fix Rubocop violations and fix documentation visibilityRafael Mendonça França2016-12-281-6/+6
| | | | | | Some methods were added to public API in 5b14129d8d4ad302b4e11df6bd5c7891b75f393c and they should be not part of the public API.
* Privatize unneededly protected methods in Active RecordAkira Matsuda2016-12-242-8/+8
|
* Add missing `+` around a some literals.bogdanvlviv2016-10-271-1/+1
| | | | | | Mainly around `nil` [ci skip]
* Fix broken comments indentation caused by rubocop auto-correct [ci skip]Ryuta Kamizono2016-09-141-44/+44
| | | | | | All indentation was normalized by rubocop auto-correct at 80e66cc4d90bf8c15d1a5f6e3152e90147f00772. But comments was still kept absolute position. This commit aligns comments with method definitions for consistency.
* Merge pull request #26037 from monmonmon/masterRafael França2016-08-171-1/+1
|\ | | | | Check if the logger is not nil before using it
| * Check if the logger exists before trying to use itmonmon2016-08-031-1/+1
| |
* | code gardening: removes redundant selfsXavier Noria2016-08-081-2/+2
| | | | | | | | | | | | | | | | | | A few have been left for aesthetic reasons, but have made a pass and removed most of them. Note that if the method `foo` returns an array, `foo << 1` is a regular push, nothing to do with assignments, so no self required.
* | normalizes indentation and whitespace across the projectXavier Noria2016-08-061-42/+42
| |
* | applies new string literal convention in activerecord/libXavier Noria2016-08-061-4/+4
|/ | | | | The current code base is not uniform. After some discussion, we have chosen to go with double quotes by default.
* Execute default_scope defined by abstract class within the scope of subclassMehmet Emin İNAÇ2016-03-081-1/+2
|
* Revert "Remove valid_scope_name? check - use ruby"Akira Matsuda2016-01-281-0/+10
| | | | | | | | | | | | | This reverts commit f6db31ec16e42ee7713029f7120f0b011d1ddc6c. Reason: Scope names can very easily conflict, particularly when sharing Concerns within the team, or using multiple gems that extend AR models. It is true that Ruby has the ability to detect this with the -w option, but the reality is that we are depending on too many gems that do not care about Ruby warnings, therefore it might not be a realistic solution to turn this switch on in our real-world apps.
* Merge branch '5-0-beta-sec'Aaron Patterson2016-01-251-1/+1
|\ | | | | | | | | | | | | | | | | | | | | * 5-0-beta-sec: bumping version fix version update task to deal with .beta1.1 Eliminate instance level writers for class accessors allow :file to be outside rails root, but anything else must be inside the rails view directory Don't short-circuit reject_if proc stop caching mime types globally use secure string comparisons for basic auth username / password
| * Eliminate instance level writers for class accessorsAaron Patterson2016-01-221-1/+1
| | | | | | | | | | | | | | | | | | Instance level writers can have an impact on how the Active Model / Record objects are saved. Specifically, they can be used to bypass validations. This is a problem if mass assignment protection is disabled and specific attributes are passed to the constructor. CVE-2016-0753
* | Skip the STI condition when evaluating a default scopeMatthew Draper2016-01-121-2/+2
|/ | | | | | | | | | | | | Given a default_scope on a parent of the current class, where that parent is not the base class, the parent's STI condition would become attached to the evaluated default scope, and then override the child's own STI condition. Instead, we can treat the STI condition as though it is a default scope, and skip it in this situation: the scope will be merged into the base relation, which already contains the correct STI condition. Fixes #22426.
* Do not omit parentheses [ci skip]Ryuta Kamizono2015-10-251-1/+1
|
* applies new doc guidelines to Active Record.Yves Senn2015-10-142-16/+18
| | | | | | | | | | | | | | | | | | | The focus of this change is to make the API more accessible. References to method and classes should be linked to make it easy to navigate around. This patch makes exzessiv use of `rdoc-ref:` to provide more readable docs. This makes it possible to document `ActiveRecord::Base#save` even though the method is within a separate module `ActiveRecord::Persistence`. The goal here is to bring the API closer to the actual code that you would write. This commit only deals with Active Record. The other gems will be updated accordingly but in different commits. The pass through Active Record is not completely finished yet. A follow up commit will change the spots I haven't yet had the time to update. /cc @fxn
* Modify the scope method documentationTommaso Visconti2015-10-081-3/+8
| | | | | | | | | | | Adds a paragraph to the documentation of the `ActiveRecord::Scoping::Named.scope` method, explaining that the method is intended to return an ActiveRecord::Relation object to be composable with other scopes. In the case that in the case that `nil` or `false` are returned, the method returns an `all` relation instead. This unexpected behaviour is mentioned in #19249 #14256 #21465 and #21882 and wasn't documented at all. This commit adds this documentation.
* Merge pull request #21522 from tgxworld/scope_perfRafael Mendonça França2015-09-071-1/+8
|\ | | | | PERF: Scope performance.
| * Cache check if `default_scope` has been overridden.Guo Xiang Tan2015-09-071-1/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Benchmark Script: ``` begin require 'bundler/inline' rescue LoadError => e $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' raise e end gemfile(true) do source 'https://rubygems.org' # gem 'rails', github: 'rails/rails', ref: 'f1f0a3f8d99aef8aacfa81ceac3880dcac03ca06' gem 'rails', path: '~/rails' gem 'arel', github: 'rails/arel', branch: 'master' gem 'rack', github: 'rack/rack', branch: 'master' gem 'sass' gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: 'master' gem 'sprockets', github: 'rails/sprockets', branch: 'master' gem 'pg' gem 'benchmark-ips' end require 'active_record' require 'benchmark/ips' ActiveRecord::Base.establish_connection('postgres://postgres@localhost:5432/rubybench') ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do create_table :users, force: true do |t| t.string :name, :email t.timestamps null: false end end class User < ActiveRecord::Base; end attributes = { name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", email: "foobar@email.com", } 1000.times { User.create!(attributes) } Benchmark.ips(5, 3) do |x| x.report('where with hash') { User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") } x.report('where with string') { User.where("users.name = ?", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") } x.compare! end key = if RUBY_VERSION < '2.2' :total_allocated_object else :total_allocated_objects end before = GC.stat[key] User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") after = GC.stat[key] puts "Total Allocated Object: #{after - before}" ``` Stackprof output truncated. ``` TOTAL (pct) SAMPLES (pct) FRAME 52 (10.6%) 10 (2.0%) ActiveRecord::Scoping::Default::ClassMethods#build_default_scope ``` Before: ``` Calculating ------------------------------------- where with hash 2.789k i/100ms where with string 4.407k i/100ms ------------------------------------------------- where with hash 29.170k (± 1.9%) i/s - 147.817k where with string 46.954k (± 2.7%) i/s - 237.978k Comparison: where with string: 46954.3 i/s where with hash: 29169.9 i/s - 1.61x slower Total Allocated Object: 85 Calculating ------------------------------------- all 16.773k i/100ms ------------------------------------------------- all 186.102k (± 3.6%) i/s - 939.288k ``` After: ``` Calculating ------------------------------------- where with hash 3.014k i/100ms where with string 4.623k i/100ms ------------------------------------------------- where with hash 31.524k (± 1.3%) i/s - 159.742k where with string 49.948k (± 2.3%) i/s - 249.642k Comparison: where with string: 49948.3 i/s where with hash: 31524.3 i/s - 1.58x slower Total Allocated Object: 84 Calculating ------------------------------------- all 20.139k i/100ms ------------------------------------------------- all 227.860k (± 2.5%) i/s - 1.148M ```
* | PERF: Don't create a Relation when it is not needed.Guo Xiang Tan2015-09-071-1/+2
|/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Benchmark script used: ``` begin require 'bundler/inline' rescue LoadError => e $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' raise e end gemfile(true) do source 'https://rubygems.org' gem 'rails', path: '~/rails' # master against ref "f1f0a3f8d99aef8aacfa81ceac3880dcac03ca06" gem 'arel', github: 'rails/arel', branch: 'master' gem 'rack', github: 'rack/rack', branch: 'master' gem 'sass' gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: 'master' gem 'sprockets', github: 'rails/sprockets', branch: 'master' gem 'pg' gem 'benchmark-ips' end require 'active_record' require 'benchmark/ips' ActiveRecord::Base.establish_connection('postgres://postgres@localhost:5432/rubybench') ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do create_table :users, force: true do |t| t.string :name, :email t.timestamps null: false end end class User < ActiveRecord::Base; end attributes = { name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", email: "foobar@email.com", } 1000.times { User.create!(attributes) } Benchmark.ips(5, 3) do |x| x.report('all') { User.all } end key = if RUBY_VERSION < '2.2' :total_allocated_object else :total_allocated_objects end before = GC.stat[key] User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") after = GC.stat[key] puts "Total Allocated Object: #{after - before}" ``` Before: ``` Calculating ------------------------------------- all 17.569k i/100ms ------------------------------------------------- all 190.854k (± 3.3%) i/s - 966.295k Total Allocated Object: 85 ``` After: ``` Calculating ------------------------------------- all 22.237k i/100ms ------------------------------------------------- all 262.715k (± 5.5%) i/s - 1.312M Total Allocated Object: 80 ```