Last Update: 2021-07-01 07:57:50 -0700

New Features

  • An unused_associations plugin has been added, which allows you to determine which associations and association methods are not used. You can use this to avoid defining the unused associations and association methods, which can save memory.

    This plugin is supported on Ruby 2.5+, and uses method coverage to determine if the plugin's methods are called. Because Sequel::Model adds association methods to an anonymous module included in the class, directly using the method coverage data to determine which associations are used is challenging.

    This plugin is mostly designed for reporting. You can have a test suite that runs with method coverage enabled, and use the coverage information to get data on unused associations:

    # Calls Coverage.result
    cov_data = Sequel::Model.update_associations_coverage
    unused_associations_data = Sequel::Model.update_unused_associations_data(coverage_data: cov_data)
    Sequel::Model.unused_associations(unused_associations_data: unused_associations_data)
    # => [["Class1", "assoc1"], ...]

    unused_associations returns an array of two element arrays, where the first element is the class name and the second element is the association name. The returned values will be associations where all of the association methods are not used.

    In addition to determining which associations are not used, you can also use this to determine if you are defining association methods that are not used:

    Sequel::Model.unused_association_options(unused_associations_data: unused_associations_data)
    # => [["Class2", "assoc2", {:read_only=>true}], ...]

    unused_association_options is similar to unused_associations, but returns an array of three element arrays, where the third element is a hash of association options that should be used to avoid defining the unused association methods. It's common in Sequel to define associations and only use them for reading data and not for modifications, and you can use this to easily see which associations are only used for reading data.

    As the determination of whether associations are used is based on method coverage, this will report as unused any associations that are used but where the association methods are not called. These cases are rare, but can happen if you have libraries that use the association reflection metadata without calling the association methods, or use the association only in combination with another plugin such as dataset_associations. You can set the :is_used association option to explicitly mark an association as used, and have this plugin avoid reporting it as unused.

    In addition to just reporting on unused associations, you can also directly use the unused associations metadata to automatically avoid defining unused associations or unused associations methods. You can set a :file option when loading the plugin:

    Sequel::Model.plugin :unused_associations, file: 'unused_associations.json'

    Then run the method coverage testing. This will save the unused associations metadata to the file. Then you can use this metadata automatically by also setting the :modify_associations option:

    Sequel::Model.plugin :unused_associations, file: 'unused_associations.json',
      modify_associations: true

    With the :modify_associations option, unused associations are skipped instead of being defined, and the options returned by unused_association_options are automatically used. Note that using the :modify_associations option is risky unless you have complete coverage and do not have cases where the associations are used without calling methods.

    It is common to have multiple test suites where you need to combine coverage. The plugin supports this by using a :coverage_file option:

    Sequel::Model.plugin :unused_associations, coverage_file: 'unused_associations_coverage.json'

    In this case, you would run update_associations_coverage after each test suite, and update_unused_associations_data only after all test suites have been run.

  • Passing nil as the value of the :setter, :adder, :remover, or :clearer association options will cause the related method to not be defined, instead of using the default value. This allows you to only define the methods you will actually be using.