Reputation: 7540
I'm using https://github.com/kenn/active_flag and https://github.com/chanzuckerberg/sorbet-rails
This is what its rbi looks like:
module ActiveFlag
extend ActiveSupport::Concern
end
class ActiveFlag::Definition
def column; end
def human(key, options = nil); end
def humans; end
def initialize(column, keys, klass); end
def keys; end
def maps; end
def pairs; end
def set_all!(key); end
def to_array(integer); end
def to_i(arg); end
def to_value(instance, integer); end
def unset_all!(key); end
end
class ActiveFlag::Railtie < Rails::Railtie
end
class ActiveFlag::Value < Set
def method_missing(symbol, *args, &block); end
def raw; end
def set!(key, options = nil); end
def set(key); end
def set?(key); end
def to_human; end
def to_s; end
def unset!(key, options = nil); end
def unset(key); end
def unset?(key); end
def with(instance, definition); end
end
module ActiveFlag::ClassMethods
def flag(column, keys); end
end
class ActiveRecord::Base
extend ActiveFlag::ClassMethods
end
The last bit (extending AR::Base) I added, the rest srb rbi gems
generated automatically.
To actually use Active Flag, I then do this in my model:
flag :visible_to, [:employee, :manager, :admin]
visible_to
is an integer column. Sorbet Rails has already typed it as such:
sig { returns(Integer) }
def visible_to; end
sig { params(value: Integer).void }
def visible_to=(value); end
sig { returns(T::Boolean) }
def visible_to?; end
I could change this definition, but it's an autogenerated file and I assume the changes will get lost. So the next thing I tried was adding a sig directly above where the method gets used:
sig { returns(ActiveFlag::Value) }
def visible_to; end
flag :visible_to, [:employee, :manager, :admin]
The problem here is that Sorbet fails because the method I've "defined" doesn't return anything. Which I know is fine, because it'll get overriden when flag
is called (it uses define_method
internally), but I don't know how to communicate this to Sorbet.
Returning value that does not conform to method result type https://srb.help/7005
54 | def visible_to; end
^^^^^^^^^^^^^^^^^^^
Expected ActiveFlag::Value
Method visible_to has return type ActiveFlag::Value
54 | def visible_to; end
^^^^^^^^^^^^^^
Got NilClass originating from:
54 | def visible_to; e
So my question is. What's the best way to tell Sorbet that this method will return an ActiveFlag::Value
once it gets defined, ideally without making a manual change to an autogenerated file?
btw. I tried to see how types for enum
in Rails are handled... it doesn't look like that's been done on sorbet-typed
yet. Possibly for the same reason.
Upvotes: 1
Views: 2483
Reputation: 377
You could implement a custom plugin for sorbet-rails
to generate methods added by active_flag
and remove the sigs generated wrongly. Here is the documentation for it:
Upvotes: 0
Reputation: 36
When you want to override a generated rbi
file you can create a second rbi
file for the same class in your workspace and move the methods in there. Sorbet will handle merging multiple definitions files for you. We keep these files in a separate sorbet/custom
directory next to the generated files; others keep the rbi
files next to the rb
files in their application directory.
As to enums, Sorbet does not natively support enum literal types so that's likely why.
Upvotes: 2