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

Add cursed methods to Rails models #106

Open
connorshea opened this issue Aug 2, 2019 · 8 comments
Open

Add cursed methods to Rails models #106

connorshea opened this issue Aug 2, 2019 · 8 comments
Labels
bug Something isn't working

Comments

@connorshea
Copy link
Contributor

connorshea commented Aug 2, 2019

These are all a mess and I'd prefer not to implement them, but I wanted to at least document them here, since they're taking up a lot of my hidden.rbi.

Is there a way to remove these from hidden.rbi without adding a bunch of useless methods to these classes?

Association Callback Methods

For every attribute on a model that has a relation with any other model, ActiveRecord/ActiveModel will have 12 methods. For example, let's say you add a relation on a Post that assigns a User as an author. Rails would create these methods:

# before add
def before_add_for_author; end
def before_add_for_author?; end
def before_add_for_author=(val); end

# before remove
def before_remove_for_author; end
def before_remove_for_author?; end
def before_remove_for_author=(val); end

# after add
def after_add_for_author; end
def after_add_for_author?; end
def after_add_for_author=(val); end

# after remove
def after_remove_for_author; end
def after_remove_for_author?; end
def after_remove_for_author=(val); end

Defined here: https://github.com/rails/rails/blob/5-2-stable/activerecord/lib/active_record/associations/builder/collection_association.rb#L32

These have barely any usage on GitHub, so I'm honestly not sure why they haven't been deprecated, but they do technically exist.

Dirty Methods

These only found their way into my hidden.rbi with Rails 6, but it seems like they've been there since at least 5.2? I'm not really sure why Sorbet couldn't find them before.

In 6.0 they're defined here: https://github.com/rails/rails/blob/v6.0.0.rc2/activemodel/lib/active_model/dirty.rb#L124-L126

If you declare an attribute name, you get these:

def name_change(*args); end
def name_changed?(*args); end
def name_previous_change(*args); end
def name_previously_changed?(*args); end
def name_was(*args); end
def name_will_change!(*args); end
def restore_name!(*args); end

There are also a few defined here: https://github.com/rails/rails/blob/v6.0.0.rc2/activerecord/lib/active_record/attribute_methods/dirty.rb#L19-L26

def saved_change_to_name?(*args); end
def saved_change_to_name(*args); end
def name_before_last_save(*args); end
def will_save_change_to_name?(*args); end
def name_change_to_be_saved(*args); end
def name_in_database(*args); end

And two here: https://github.com/rails/rails/blob/v6.0.0.rc2/activerecord/lib/active_record/attribute_methods/before_type_cast.rb#L32-L33

def name_before_type_cast(*args); end
def name_came_from_user?(*args); end

So that's 15 methods added per attribute (and this isn't counting the setter, getter, or asker), fun!

@connorshea connorshea added the bug Something isn't working label Aug 2, 2019
@connorshea
Copy link
Contributor Author

@connorshea
Copy link
Contributor Author

And there are also _ids getters and setters:

https://github.com/rails/rails/blob/b343beba03722672b9bb827f8ce29c7c1c216406/activerecord/lib/active_record/associations/builder/collection_association.rb#L55

module Game::GeneratedAssociationMethods
  def game_genre_ids(); end

  def game_genre_ids=(ids); end

  def game_platform_ids(); end

  def game_platform_ids=(ids); end

  def game_publisher_ids(); end

  def game_publisher_ids=(ids); end

  def game_purchase_ids(); end

  def game_purchase_ids=(ids); end
end

@connorshea
Copy link
Contributor Author

And reload_:

module Game::GeneratedAssociationMethods
  def reload_cover_attachment(); end

  def reload_cover_blob(); end

  def reload_pg_search_document(); end

  def reload_series(); end
end

https://github.com/rails/rails/blob/fc35da76e93f8a5d5ace595b4819e19cc0512edd/activerecord/lib/active_record/associations/builder/singular_association.rb#L19

As well as build_/create_:

module Game::GeneratedAssociationMethods
  def build_cover_attachment(*args, &block); end

  def build_pg_search_document(*args, &block); end

  def build_series(*args, &block); end

  def create_cover_attachment(*args, &block); end

  def create_cover_attachment!(*args, &block); end

  def create_pg_search_document(*args, &block); end

  def create_pg_search_document!(*args, &block); end

  def create_series(*args, &block); end

  def create_series!(*args, &block); end
end

https://github.com/rails/rails/blob/fc35da76e93f8a5d5ace595b4819e19cc0512edd/activerecord/lib/active_record/associations/builder/singular_association.rb#L28-L38

@hdoan741
Copy link
Contributor

Since they aren't really used, there is little value to generate them, except to clean up hidden.rbi file. If you'd like to clean these up properly, feel free to contribute a plugin that generate the methods, but we don't add the plugin to the default list.

@connorshea
Copy link
Contributor Author

I've created a working plugin (although everything is essentially untyped): https://github.com/connorshea/VideoGameList/blob/9c9f1d0d1fb2394103fad05b77295007c0a7c2ae/lib/cursed_rbi_plugin.rb

It removed a little over 5k lines out of my 35k line hidden.rbi :)

@manhhung741 do you still want this? :) Should I rename it from 'CursedRbiPlugin'? And how should the user enable its usage?

@hdoan741
Copy link
Contributor

hdoan741 commented Oct 9, 2019 via email

@hdoan741
Copy link
Contributor

hdoan741 commented Oct 9, 2019 via email

@connorshea
Copy link
Contributor Author

Something to do with metaprogramming, probably. Maybe MetaprogrammingGarageSalePlugin? :P

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