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
461 def delete_unused_associations_files
462   _delete_unused_associations_file(@unused_associations_coverage_file)
463   _delete_unused_associations_file(@unused_associations_file)
464 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
445 def unused_association_options(opts=OPTS)
446   unused_associations_data = opts[:unused_associations_data] || Sequel.parse_json(File.binread(@unused_associations_file))
447 
448   unused_association_methods = []
449   unused_associations_data.each do |sc, associations|
450     associations.each do |assoc, unused|
451       unless unused == 'unused'
452         unused_association_methods << [sc, assoc, set_unused_options_for_association({}, unused)]
453       end
454     end
455   end
456   unused_association_methods
457 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
418 def unused_associations(opts=OPTS)
419   unused_associations_data = opts[:unused_associations_data] || Sequel.parse_json(File.binread(@unused_associations_file))
420 
421   unused_associations = []
422   unused_associations_data.each do |sc, associations|
423     associations.each do |assoc, unused|
424       if unused == 'unused'
425         unused_associations << [sc, assoc]
426       end
427     end
428   end
429   unused_associations
430 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 
351   ([self] + descendants).each do |sc|
352     next unless cov_data = coverage_data[sc.name]
353     reflection_data = cov_data[''] || []
354 
355     sc.association_reflections.each do |assoc, ref|
356       # Only report associations for the class they are defined in
357       next unless ref[:model] == sc
358 
359       # Do not report associations using methods_module option, because this plugin only
360       # looks in the class's overridable_methods_module
361       next if ref[:methods_module]
362 
363       info = {}
364       if reflection_data.include?(assoc.to_s)
365         info[:used] = [:reflection]
366       end
367 
368       _update_association_coverage_info(info, cov_data, ref.dataset_method, :dataset_method)
369       _update_association_coverage_info(info, cov_data, ref.association_method, :association_method)
370 
371       unless ref[:orig_opts][:read_only]
372         if ref.returns_array?
373           _update_association_coverage_info(info, cov_data, ref[:add_method], :adder)
374           _update_association_coverage_info(info, cov_data, ref[:remove_method], :remover)
375           _update_association_coverage_info(info, cov_data, ref[:remove_all_method], :clearer)
376         else
377           _update_association_coverage_info(info, cov_data, ref[:setter_method], :setter)
378         end
379       end
380 
381       next if info.keys == [:missing]
382 
383       if !info[:used]
384         (unused_associations_data[sc.name] ||= {})[assoc.to_s] = 'unused'
385       elsif unused = info[:unused]
386         if unused.include?(:setter) || [:adder, :remover, :clearer].all?{|k| unused.include?(k)}
387           [:setter, :adder, :remover, :clearer].each do |k|
388             unused.delete(k)
389           end
390           unused << :read_only
391         end
392         (unused_associations_data[sc.name] ||= {})[assoc.to_s] = unused.map(&:to_s)
393       end
394     end
395   end
396 
397   if @unused_associations_file
398     File.binwrite(@unused_associations_file, Sequel.object_to_json(unused_associations_data))
399   end
400   unless options[:keep_coverage]
401     _delete_unused_associations_file(@unused_associations_coverage_file)
402   end
403 
404   unused_associations_data
405 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
469 def _delete_unused_associations_file(file)
470   if file && File.file?(file)
471     File.unlink(file)
472   end
473 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
477 def _update_association_coverage_info(info, coverage_data, meth, key)
478   type = case coverage_data[meth.to_s]
479   when 0
480     :unused
481   when Integer
482     :used
483   else
484     # Missing here means there is no coverage information for the
485     # the method, which indicates the expected method was never
486     # defined.  In that case, it can be ignored.
487     :missing
488   end
489 
490   (info[type] ||= []) << key
491 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
510 def def_association(opts)
511   if !opts[:is_used] && @unused_associations_data && (data = @unused_associations_data[name]) && (unused = data[opts[:name].to_s])
512     set_unused_options_for_association(opts, unused)
513   end
514   
515   super
516 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
496 def set_unused_options_for_association(opts, unused)
497   opts[:read_only] = true if unused.include?('read_only')
498   opts[:no_dataset_method] = true if unused.include?('dataset_method')
499   opts[:no_association_method] = true if unused.include?('association_method')
500   opts[:adder] = nil if unused.include?('adder')
501   opts[:remover] = nil if unused.include?('remover')
502   opts[:clearer] = nil if unused.include?('clearer')
503   opts
504 end