I see a potential problem in Article.joins(:tags).merge(Tag.unscope(where: 
:deleted_at)):
For example — what happens if you add something in between Tag and unscope? 
Like Article.joins(:tags).merge(Tag.joins(:whatever).unscope(where: 
:deleted_at))

I don't see a way to implement it without explicitly defining a relation to 
affect in the unscope method. 

Why do you think Article.joins(:tags).unscope(where: {tags: :deleted_at}) is 
confusing?
It repeats the structure of a where clause: Article.joins(:tags).where(tags: 
{deleted_at: nil}) and don't break the current behaviour.


We can think about something similar for ordering too:
Article.joins(:tags).unscope(order: :tags)
Article.joins(:tags).unscope(order: {tags: :deleted_at})


And yes, I think once you go to a join(or query) via a string condition, 
you lose the ability to unscope anyway.


On Monday, March 2, 2020 at 5:34:06 PM UTC+1, Geoff Harcourt wrote:
>
> We're using a similar solution, this is what I'd envision:
>
> class Article < ApplicationRecord
>   has_many :articles_tags
>   has_many :tags, through: :articles_tags
>   default_scope { where(deleted_at: nil) }end
> class ArticlesTags < ApplicationRecord
>   belongs_to :article
>   belongs_to :tagend
> class Tag < ApplicationRecord
>   has_many :articles_tags
>   has_many :articles, through: :articles_tags
>   default_scope { where(deleted_at: nil) }end
>
> # This currently doesn't work
> # There might be some confusion over whether this removes the article 
> ownership
> article.joins(:tags).merge(Tag.unscoped)
> # This might be less likely to cause confusion or 
> conflictsarticle.joins(:tags).merge(Tag.unscope(where: :deleted_at))
>
> Currently joins with default scopes are already a very "use with caution" 
> kind of experience. The two cases for us where they are problematic at the 
> moment are anything with a soft-delete (a where criteria that filters 
> records out that we can't remove from the query) or an ordering for a big 
> rollup query where the ordering of one of the joins in the middle is just 
> wasted effort and won't be used at all in the final result.
>
> The place where this becomes really inconvenient is when the default scope 
> falls on a joined relationship that has further joins on it, as once you go 
> to a join via a string condition you lose the ability (I think?) to 
> continue on with AR relationships.
>
> On Sun, Mar 1, 2020 at 10:45 AM Slava Korolev <kor...@gmail.com 
> <javascript:>> wrote:
>
>> Can you provide an example of how you would like to see it with merge 
>> method?
>>
>>
>> My real-life case is more like that(we use Paranoia gem, but I show a 
>> simplified version):
>>
>> class Article < ApplicationRecord
>>   has_many :articles_tags
>>   has_many :tags, through: :articles_tags
>>   default_scope { where(deleted_at: nil) }end
>> class ArticlesTags < ApplicationRecord
>>   belongs_to :article, -> { unscope(where: :deleted_at) } # It intended to 
>> affect only articles; I would like to have it like "unscope(where: { 
>> articles: :deleted_at })"
>>   belongs_to :tag, -> { unscope(where: :deleted_at) } # It intended affect 
>> only tags; I would like to have it like "unscope(where: { tags: :deleted_at 
>> })"end
>> class Tag < ApplicationRecord
>>   has_many :articles_tags
>>   has_many :articles, through: :articles_tags
>>   default_scope { where(deleted_at: nil) }end
>>
>>
>> When I call
>> Article.joins(:tags)
>> It adds the scope from belongs_to :articles (in this case unscope(where: 
>> :deleted_at)) to the where chain and overrides the default scope of tags 
>> (where(deleted_at: nil)) even though it was intended to affect different 
>> tables
>>
>> On Sunday, March 1, 2020 at 1:27:12 PM UTC+1, Geoff Harcourt wrote:
>>>
>>> Maybe the clearer way to apply it would be to allow unscoping via the 
>>> merge method?
>>>
>>> I think the overall idea is worth pursuing in some fashion. We often 
>>> have big queries with lots of joins on aggregate dashboards, and ordering 
>>> on default scopes for joined models adds wasted expense to queries. The 
>>> workarounds are either no default scopes for ordering or joins via SQL 
>>> string, which can be inconvenient for a number of reasons. 
>>>
>>> On Sat, Feb 29, 2020, 5:07 PM Slava Korolev <kor...@gmail.com> wrote:
>>>
>>>> Thank you for your feedback!
>>>>
>>>> I think you might misunderstand what I'm proposing, sorry for that.
>>>> You still can unscope as you did before, but if you want to specify 
>>>> table you want to affect, you can do it.
>>>> In your example, the current implementation also doesn't work:
>>>>
>>>> Article.where("deleted_at IS NULL").unscope(where: :deleted_at) # == 
>>>> SELECT * FROM "articles" WHERE (deleted_at is NULL)
>>>>
>>>> I don't see a way to fix this existing problem.
>>>> But if you don't use custom SQL in your queries you can use both old 
>>>> and new approaches:
>>>>
>>>> Article.where(deleted_at: nil).unscope(where: :deleted_at) # == SELECT 
>>>> * FROM "articles"
>>>> Article.where(deleted_at: nil).unscope(where: { articles: :deleted_at 
>>>> }) # == SELECT * FROM "articles"
>>>>
>>>>
>>>> On Saturday, February 29, 2020 at 4:25:08 PM UTC+1, James Coleman wrote:
>>>>>
>>>>> I think this will likely be confusing in many cases, since it's 
>>>>> trivial to come up with example where it won't be able to work as 
>>>>> expected.
>>>>>
>>>>> For example, suppose that someone does Article.where("deleted_at IS 
>>>>> NULL") in some method (or even harder to find: in a library), then the 
>>>>> result of that has unscope(where: {articles: :deleted_at}) called on it. 
>>>>> In 
>>>>> that case the unscope call will be a no-op, and the result not only 
>>>>> surprising, but likely to cause significant application bugs.
>>>>>
>>>>> As such, I'm -1 on this change.
>>>>>
>>>>> On Sat, Feb 29, 2020 at 1:00 AM Slava Korolev <kor...@gmail.com> 
>>>>> wrote:
>>>>>
>>>>>> I often see a use case when in a query, there are several relations 
>>>>>> with attributes with the same names(for example, in our codebase, there 
>>>>>> are 
>>>>>> several "soft-deletable" entities, and all of them have deleted_at
>>>>>>  attribute).
>>>>>>
>>>>>> Article.where(deleted_at: nil).joins(:comments).where(comments: { 
>>>>>> deleted_at: nil })
>>>>>>
>>>>>> At the moment, it's not possible to unscope deleted_at only for 
>>>>>> articles or only for comments.
>>>>>>
>>>>>> I created a PR that adds support for specifying tables in where 
>>>>>> clauses in unscope method:
>>>>>>
>>>>>> Article.where(deleted_at: nil).joins(:comments).where(comments: { 
>>>>>> deleted_at: nil }).unscope(where: { articles: :deleted_at })
>>>>>>   # == Article.joins(:comments).where(comments: { deleted_at: nil }) 
>>>>>>
>>>>>>
>>>>>> PR: https://github.com/rails/rails/pull/38608
>>>>>>
>>>>>> Happy to get any feedback, thanks!
>>>>>>
>>>>>> -- 
>>>>>> You received this message because you are subscribed to the Google 
>>>>>> Groups "Ruby on Rails: Core" group.
>>>>>> To unsubscribe from this group and stop receiving emails from it, 
>>>>>> send an email to rubyonra...@googlegroups.com.
>>>>>> To view this discussion on the web visit 
>>>>>> https://groups.google.com/d/msgid/rubyonrails-core/e5117870-9340-4d86-b81c-0ae75840d486%40googlegroups.com
>>>>>>  
>>>>>> <https://groups.google.com/d/msgid/rubyonrails-core/e5117870-9340-4d86-b81c-0ae75840d486%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>>> .
>>>>>>
>>>>> -- 
>>>> You received this message because you are subscribed to the Google 
>>>> Groups "Ruby on Rails: Core" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>> an email to rubyonra...@googlegroups.com.
>>>> To view this discussion on the web visit 
>>>> https://groups.google.com/d/msgid/rubyonrails-core/c044aa68-7fac-4eb6-bb35-93c0cd69e9c6%40googlegroups.com
>>>>  
>>>> <https://groups.google.com/d/msgid/rubyonrails-core/c044aa68-7fac-4eb6-bb35-93c0cd69e9c6%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>> .
>>>>
>>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Ruby on Rails: Core" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to rubyonra...@googlegroups.com <javascript:>.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/rubyonrails-core/c311ad8c-9d0a-4b4a-bc6b-03713f7c5b5e%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/rubyonrails-core/c311ad8c-9d0a-4b4a-bc6b-03713f7c5b5e%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to rubyonrails-core+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rubyonrails-core/58ce0c49-b8e2-48ec-ad0b-4ecf4ef8db4d%40googlegroups.com.

Reply via email to