New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
scope in belongs_to is not respected when used in join context #20679
Comments
I found the same problem with This gist follows the bug report template: |
This problem occurs only with "regular" belongs_to, if you create a second "belongs_to" statement like: class Profile
belongs_to :user, -> { unscope(where: :disabled_at) }
belongs_to :user_even_if_deleted, -> { unscope(where: :disabled_at) },
class_name: 'User', foreign_key: :user_id
end and use this new relation on scope it works. I tested with stable 4.2.3 and it still with problems.. This seems to me as a regression @rafaelfranca since it was working on 4.2.2. Anyways, this usage of another belongs_to can be used as a workaround. |
Not true in my case. I've been using
I'm using 4.2.1 so you seem to have a different problem than mine. In my case, the crux of the issue is that there are two places that takes Profile.joins(:user).merge(User.where(id: 1)).to_sql
=> "SELECT `profiles`.* FROM `profiles`
INNER JOIN `users` ON `users`.`id` = `profiles`.`id`
AND `users`.`disabled_at` IS NULL
WHERE `users`.`disabled_at` IS NULL AND `users`.`id` = 1"
Profile.joins(:user).merge(User.unscoped.where(id: 1)).to_sql
=> "SELECT `profiles`.* FROM `profiles`
INNER JOIN `users` ON `users`.`id` = `profiles`.`id`
AND `users`.`disabled_at` IS NULL
WHERE `users`.`id` = 1" So, There should be a way to remove default_scope from the At this moment, I had to resort to class Profile
def self.joins_unscoped(key)
source = arel_table
target = key.to_s.classify.constantize.arel_table
join = source
.join(target, Arel::Nodes::InnerJoin)
.on(source[:id].eq(target[:id])).join_sources
joins(join)
end
end
Profile.joins_unscoped(:user).merge(User.unscoped.where(id: 1)).to_sql
=> "SELECT `profiles`.* FROM `profiles`
INNER JOIN `users` ON `profiles`.`id` = `users`.`id`
WHERE `users`.`id` = 1" |
@everton could you open a new issue for your problem? Thanks |
This issue has been automatically marked as stale because it has not been commented on for at least The resources of the Rails team are limited, and so we are asking for your help. If you can still reproduce this error on the Thank you for all your contributions. |
I've come up with a robust monkey patch that fixes this issue. module ActiveRecordExtension
extend ActiveSupport::Concern
module ClassMethods
def joins_unscoped(name)
reflection = reflections[name.to_s]
source = arel_table
target = reflection.class_name.constantize.arel_table
join = source
.join(target, Arel::Nodes::InnerJoin)
.on(source[reflection.foreign_key].eq(target[:id])).join_sources
joins(join)
end
end
end
ActiveRecord::Base.send(:include, ActiveRecordExtension) Now > Picture.joins_unscoped(:user).to_sql
=> "SELECT `pictures`.* FROM `pictures` INNER JOIN `users` ON `pictures`.`user_id` = `users`.`id`" Related issues #13775 and #18109 but it's not quite the same - when I join, it's highly likely to do Maybe we need a new relation method |
@kenn your PR makes absolute sense. For me when I do:
The join should override the default scope (which is archived: false). The monkey patch works for simple cases, but something like: Will go kaboom, alas. Still waiting for a good solution to this one. Using unscoped with a block is not really feasible and using pure sql joins creates issues with non-unique table names, which then need to be aliased, creating massive headache. |
Unscoping `default_scope` in associations has already supported (rails#17360 for preloading, c9cf8b8 for eager loading). Fixes rails#20679. Closes rails#16531.
In particular, I pass scope argument to
belongs_to
to reverse the effect ofdefault_scope
in the parent model.Here, I'm seeing an inconsistent behavior - the scope is respected when it's called on the child instance, but not when it's called on the relation using
joins
.Here's models:
Now, given User:1 has disabled_at set:
I think this is fairly confusing, and believe that the scope should be respected with the join relation as well.
Thoughts?
The text was updated successfully, but these errors were encountered: