module Sequel::Plugins::UnusedAssociations::ClassMethods

Public Instance Methods

associate(type, assoc_name, opts=OPTS) click to toggle source

If modifying associations, and this association is marked as not used, and the association does not include the specific :is_used option, skip defining the association.

Calls superclass method
    # File lib/sequel/plugins/unused_associations.rb
284 def associate(type, assoc_name, opts=OPTS)
285   if !opts[:is_used] && @unused_associations_data && (data = @unused_associations_data[name]) && data[assoc_name.to_s] == 'unused'
286     return
287   end
288   
289   super
290 end
association_reflection(association) click to toggle source

Record access to association reflections to determine which associations are not used.

Calls superclass method
    # File lib/sequel/plugins/unused_associations.rb
275 def association_reflection(association)
276   uar = used_association_reflections
277   Sequel.synchronize{uar[association] ||= true}
278   super
279 end
delete_unused_associations_files() click to toggle source

Delete the unused associations coverage file and unused associations data file, if either exist.

    # File lib/sequel/plugins/unused_associations.rb
463 def delete_unused_associations_files
464   _delete_unused_associations_file(@unused_associations_coverage_file)
465   _delete_unused_associations_file(@unused_associations_file)
466 end
freeze() click to toggle source

Setup the used_association_reflections storage before freezing

Calls superclass method
    # File lib/sequel/plugins/unused_associations.rb
293 def freeze
294   used_association_reflections
295   super
296 end
unused_association_options(opts=OPTS) click to toggle source

Return an array of unused association options. These are associations some but not all of the association methods are used, according to the coverage information. Each entry in the array is an array of three elements. The first element is the class name string, the second element is the association name string, and the third element is a hash of association options that can be used in the association so it does not define methods that are not used.

Options:

:unused_associations_data

The data to use for determining which associations are unused, which is returned from update_unused_associations_data. If not given, loads the data from the file specified by the :file plugin option.

    # File lib/sequel/plugins/unused_associations.rb
447 def unused_association_options(opts=OPTS)
448   unused_associations_data = opts[:unused_associations_data] || Sequel.parse_json(File.binread(@unused_associations_file))
449 
450   unused_association_methods = []
451   unused_associations_data.each do |sc, associations|
452     associations.each do |assoc, unused|
453       unless unused == 'unused'
454         unused_association_methods << [sc, assoc, set_unused_options_for_association({}, unused)]
455       end
456     end
457   end
458   unused_association_methods
459 end
unused_associations(opts=OPTS) click to toggle source

Return an array of unused associations. These are associations where none of the association methods are used, according to the coverage information. Each entry in the array is an array of two strings, with the first string being the class name and the second string being the association name.

Options:

:unused_associations_data

The data to use for determining which associations are unused, which is returned from update_unused_associations_data. If not given, loads the data from the file specified by the :file plugin option.

    # File lib/sequel/plugins/unused_associations.rb
420 def unused_associations(opts=OPTS)
421   unused_associations_data = opts[:unused_associations_data] || Sequel.parse_json(File.binread(@unused_associations_file))
422 
423   unused_associations = []
424   unused_associations_data.each do |sc, associations|
425     associations.each do |assoc, unused|
426       if unused == 'unused'
427         unused_associations << [sc, assoc]
428       end
429     end
430   end
431   unused_associations
432 end
update_associations_coverage(opts=OPTS) click to toggle source

Parse the coverage result, and return the coverage data for the associations for descendants of this class. If the plugin uses the :coverage_file option, the existing coverage file will be loaded if present, and before the method returns, the coverage file will be updated.

Options:

:coverage_result

The coverage result to use. This defaults to Coverage.result.

    # File lib/sequel/plugins/unused_associations.rb
305 def update_associations_coverage(opts=OPTS)
306   coverage_result = opts[:coverage_result] || Coverage.result
307   module_mapping = {}
308   file = @unused_associations_coverage_file
309 
310   coverage_data = if file && File.file?(file)
311     Sequel.parse_json(File.binread(file))
312   else
313     {}
314   end
315 
316   ([self] + descendants).each do |sc|
317     next if sc.associations.empty? || !sc.name
318     module_mapping[sc.send(:overridable_methods_module)] = sc
319     cov_data = coverage_data[sc.name] ||= {''=>[]}
320     cov_data[''].concat(sc.used_association_reflections.keys.map(&:to_s).sort).uniq!
321   end
322 
323   coverage_result.each do |file, coverage|
324     coverage[:methods].each do |(mod, meth), times|
325       next unless sc = module_mapping[mod]
326       coverage_data[sc.name][meth.to_s] ||= 0
327       coverage_data[sc.name][meth.to_s] += times
328     end
329   end
330 
331   if file
332     File.binwrite(file, Sequel.object_to_json(coverage_data))
333   end
334 
335   coverage_data
336 end
update_unused_associations_data(options=OPTS) click to toggle source

Parse the coverage data returned by update_associations_coverage, and return data on unused associations and unused association methods.

Options:

:coverage_data

The coverage data to use. If not given, it is taken from the file specified by the :coverage_file plugin option.

:keep_coverage

Do not delete the file specified by the :coverage_file plugin option, even if it exists.

    # File lib/sequel/plugins/unused_associations.rb
346 def update_unused_associations_data(options=OPTS)
347   coverage_data = options[:coverage_data] || Sequel.parse_json(File.binread(@unused_associations_coverage_file))
348 
349   unused_associations_data = {}
350   to_many_modification_methods = [:adder, :remover, :clearer]
351   modification_methods = [:setter, :adder, :remover, :clearer]
352 
353   ([self] + descendants).each do |sc|
354     next unless cov_data = coverage_data[sc.name]
355     reflection_data = cov_data[''] || []
356 
357     sc.association_reflections.each do |assoc, ref|
358       # Only report associations for the class they are defined in
359       next unless ref[:model] == sc
360 
361       # Do not report associations using methods_module option, because this plugin only
362       # looks in the class's overridable_methods_module
363       next if ref[:methods_module]
364 
365       info = {}
366       if reflection_data.include?(assoc.to_s)
367         info[:used] = [:reflection]
368       end
369 
370       _update_association_coverage_info(info, cov_data, ref.dataset_method, :dataset_method)
371       _update_association_coverage_info(info, cov_data, ref.association_method, :association_method)
372 
373       unless ref[:orig_opts][:read_only]
374         if ref.returns_array?
375           _update_association_coverage_info(info, cov_data, ref[:add_method], :adder)
376           _update_association_coverage_info(info, cov_data, ref[:remove_method], :remover)
377           _update_association_coverage_info(info, cov_data, ref[:remove_all_method], :clearer)
378         else
379           _update_association_coverage_info(info, cov_data, ref[:setter_method], :setter)
380         end
381       end
382 
383       next if info.keys == [:missing]
384 
385       if !info[:used]
386         (unused_associations_data[sc.name] ||= {})[assoc.to_s] = 'unused'
387       elsif unused = info[:unused]
388         if unused.include?(:setter) || to_many_modification_methods.all?{|k| unused.include?(k)}
389           modification_methods.each do |k|
390             unused.delete(k)
391           end
392           unused << :read_only
393         end
394         (unused_associations_data[sc.name] ||= {})[assoc.to_s] = unused.map(&:to_s)
395       end
396     end
397   end
398 
399   if @unused_associations_file
400     File.binwrite(@unused_associations_file, Sequel.object_to_json(unused_associations_data))
401   end
402   unless options[:keep_coverage]
403     _delete_unused_associations_file(@unused_associations_coverage_file)
404   end
405 
406   unused_associations_data
407 end
used_association_reflections() click to toggle source

Synchronize access to the used association reflections.

    # File lib/sequel/plugins/unused_associations.rb
270 def used_association_reflections
271   Sequel.synchronize{@used_association_reflections ||= {}}
272 end

Private Instance Methods

_delete_unused_associations_file(file) click to toggle source

Delete the given file if it exists.

    # File lib/sequel/plugins/unused_associations.rb
471 def _delete_unused_associations_file(file)
472   if file && File.file?(file)
473     File.unlink(file)
474   end
475 end
_update_association_coverage_info(info, coverage_data, meth, key) click to toggle source

Update the info hash with information on whether the given method was called, according to the coverage information.

    # File lib/sequel/plugins/unused_associations.rb
479 def _update_association_coverage_info(info, coverage_data, meth, key)
480   type = case coverage_data[meth.to_s]
481   when 0
482     :unused
483   when Integer
484     :used
485   else
486     # Missing here means there is no coverage information for the
487     # the method, which indicates the expected method was never
488     # defined.  In that case, it can be ignored.
489     :missing
490   end
491 
492   (info[type] ||= []) << key
493 end
def_association(opts) click to toggle source

If modifying associations, and this association has unused association methods, automatically set the appropriate options so the unused association methods are not defined, unless the association explicitly uses the :is_used options.

Calls superclass method
    # File lib/sequel/plugins/unused_associations.rb
512 def def_association(opts)
513   if !opts[:is_used] && @unused_associations_data && (data = @unused_associations_data[name]) && (unused = data[opts[:name].to_s])
514     set_unused_options_for_association(opts, unused)
515   end
516   
517   super
518 end
set_unused_options_for_association(opts, unused) click to toggle source

Based on the value of the unused, update the opts hash with association options that will prevent unused association methods from being defined.

    # File lib/sequel/plugins/unused_associations.rb
498 def set_unused_options_for_association(opts, unused)
499   opts[:read_only] = true if unused.include?('read_only')
500   opts[:no_dataset_method] = true if unused.include?('dataset_method')
501   opts[:no_association_method] = true if unused.include?('association_method')
502   opts[:adder] = nil if unused.include?('adder')
503   opts[:remover] = nil if unused.include?('remover')
504   opts[:clearer] = nil if unused.include?('clearer')
505   opts
506 end