require_relative 'concerns/sync_mapping' module CanvasSync module Record extend ActiveSupport::Concern include CanvasSync::Concerns::SyncMapping def self.registered_features @canvas_sync_features ||= {} end def self.define_feature(modul, feature_ident = nil, models: nil, default: false, &blk) feature_ident = modul.name.demodulize.underscore if feature_ident.nil? if models == nil pmod = _get_module_parent(modul) models = pmod.name.demodulize if pmod && _get_module_parent(pmod) == CanvasSync::Concerns end @canvas_sync_features ||= {} @canvas_sync_features[feature_ident] = { name: feature_ident, module: modul, default: default, models: Array.wrap(models).map(&:to_s), setup: blk || ->{ include modul }, } end def self._get_module_parent(modul) modul.respond_to?(:parent) ? modul.parent : modul.module_parent end class_methods do def applicable_canvas_sync_features @applicable_canvas_sync_features ||= begin relev_feats = {} CanvasSync::Record.registered_features.each do |k, cfg| next if cfg[:models].present? && !cfg[:models].include?(self.name.demodulize) relev_feats[k] = cfg end relev_feats end end def canvas_sync_feature(feature, config = nil) feat = applicable_canvas_sync_features[feature] if !feat raise "Unkown feature :#{feature} for model #{self}" end setup = feat[:setup] if setup.arity != 0 instance_exec(config, &setup) elsif config.present? raise ArgumentError, "Feature #{feature} does not accept configuration" else instance_exec(&setup) end end def canvas_sync_features(*args, skip: [], **kwargs) features = {} include_defaults = args.length == 0 || args.include?(:defaults) if include_defaults applicable_canvas_sync_features.each do |key, cfg| next if skip.include?(key) case cfg[:default] when true features[key] = {} when Proc features[key] = {} if instance_exec(&cfg[:default]) end end end args.each do |a| next if a == :defaults features[a] ||= {} end kwargs.each do |key, opts| if opts == false features.delete(key) elsif opts == true features[key] ||= {} else features[key] = opts end end features.each do |key, opts| canvas_sync_feature(key, opts) end end end included do define_model_callbacks :sync_import col_names = column_names rescue [] if col_names.include?("canvas_sync_batch_id") belongs_to :canvas_sync_batch, foreign_key: :canvas_sync_batch_id, class_name: "CanvasSync::SyncBatch", optional: true end end end end