Skip to content
This repository has been archived by the owner on Jul 5, 2023. It is now read-only.

Wrong sig for group().count #273

Open
ghiculescu opened this issue Feb 19, 2020 · 3 comments
Open

Wrong sig for group().count #273

ghiculescu opened this issue Feb 19, 2020 · 3 comments
Labels
bug Something isn't working

Comments

@ghiculescu
Copy link
Contributor

ghiculescu commented Feb 19, 2020

https://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-count

Person.count returns an Integer

Article.group(:status, :category).count returns a hash of type T::Hash[String, Integer]

Currently there's no sigs for count on an AR::Relation generated, it's left to other places (sorbet rbi generation / sorbet-typed) to define.

However, rbis generated for relations do include Enumerable, which means that by default count is assumed to return Integer. See sorbet.run.

My proposal

I'm not sure if this is a good idea yet, I'd like feedback.

Currently rbis we generate for models include this:

  sig { params(args: T.untyped).returns(Article::ActiveRecord_Relation) }
  def self.group(*args); end

We could change it to this:

  sig { params(args: T.untyped).returns(Article::ActiveRecord_Relation__GROUPED) }
  def self.group(*args); end

And also define this in the same rbi:

class Article::ActiveRecord_Relation__GROUPED < Article::ActiveRecord_Relation
  extend T::Sig
  extend T::Generic
  Elem = type_member(fixed: Article)

  sig { returns(T::Hash[T.any(String, T::Array[String]), Integer]) }
  def count; end
end

I've tested this code statically and it works great. I imagine it might create some runtime problems which is why I want feedback on it before pursuing the idea.

@ghiculescu ghiculescu added the bug Something isn't working label Feb 19, 2020
@hdoan741
Copy link
Contributor

hdoan741 commented Feb 24, 2020

I like this proposal. It's kind of like the case with where_not. I think there might be more variations of methods once the query is grouped, and we can add those to this special module.

There are a few things from the Documentation that I'd like to point out:

  1. You can write code like this and it would still have to return a __GROUPED relation.
Student.group(:first_name).where(site_id: 43).count
  1. From the documentation, I think the method return type will have to be T::Hash[T.untyped, Integer] thought, because it depends on how many attributes you've groupped

If count is used with Relation#group for multiple columns, it returns a Hash whose keys are an array containing the individual values of each column and the value of each key would be the count.

Article.group(:status, :category).count
=> {["draft", "business"]=>10, ["draft", "technology"]=>4,
["published", "business"]=>0, ["published", "technology"]=>2}

  sig { returns(T::Hash[String, Integer]) }
  def count; end

@ghiculescu
Copy link
Contributor Author

ghiculescu commented Feb 24, 2020

  1. True. We could fix this by having ActiveRecord_Relation__GROUPED re-define more methods than just count.
  2. You're correct; will update proposal. I think T.any(String, T::Array[String]) is ideal.

@hdoan741
Copy link
Contributor

hdoan741 commented Feb 24, 2020 via email

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants