thehyve/puppet-i2b2

View on GitHub
lib/puppet_x/thehyve/i2b2_param_mixin.rb

Summary

Maintainability
A
1 hr
Test Coverage
module PuppetX
module Thehyve
module I2b2ParamMixin

  def self.create_param_type(target_class, method_suffix, &block_constant)
    target_class.send(:define_method,
                      "new_#{method_suffix}") do |name, options = {}, &block_specific|

      gen_method = options[:create_property] ? :newproperty : :newparam
      options.delete :create_property

      method(gen_method).call name, options do
        # needs to be class_eval, not instance_eval. self is a class object
        # at this point, and instance_eval would make the default definee
        # (i.e. the target of unqualified definitions) inside the block
        # the singleton class of the self class object, instead of the class
        # itself (hence define_method would need to be called instead of just
        # def foo do ... end in order to override parameter methods)
        class_eval &block_constant

        first_validate = instance_method(:unsafe_validate)
        first_munge    = instance_method(:unsafe_munge)

        class_eval &block_specific if block_given?

        second_validate = instance_method(:unsafe_validate)
        second_munge    = instance_method(:unsafe_munge)

        # allow specific block to remove constant block's munge/validation

        if first_validate and second_validate and first_validate != second_validate
          validate do |value|
            first_validate.bind(self)[value]
            second_validate.bind(self)[value]
          end
        end

        if first_munge and second_munge and first_munge != second_munge
          munge do |value|
            first_value = first_munge.bind(self)[value]
            second_munge.bind(self)[first_value]
          end
        end
      end
    end
  end

  def create_param_type(method_suffix, &block_constant)
    # self will be a class object (this module will be extended, not included),
    # hence we'll be creating a method on the class's singleton class, i.e.
    # a class method on the class extending this module
    I2b2ParamMixin.create_param_type self.singleton_class,
                                     method_suffix, &block_constant
  end

  # creates instance method new_string_valued_hash_param on the module
  create_param_type self, 'string_valued_hash_param' do
    validate do |value|
      fail "'#{name}' must be a hash, got '#{value}'" unless value.instance_of?(Hash)
      value.each_pair do |k, v|
        fail 'cannot have hashes or arrays in hash values, ' \
              "got #{v} (class #{v.class}) for key '#{k}'" if
            v.instance_of? Hash or v.instance_of? Array
      end
    end

    munge do |value|
      value.inject({}) do |memo, (k, v)|
        memo[k.to_sym] = v.to_s.encode('utf-8')
        memo
      end
    end
  end

  def create_system_user_param
    newparam :system_user do
      desc 'If setting the uid is required, the system user to change to.'
    end

    autorequire(:user) do
      [self[:system_user]]
    end
  end

  def create_connect_params_param
    new_string_valued_hash_param :connect_params do
      isrequired

      desc <<-'EOT'
      The connection parameters for the database. Given in hash form.
      EOT

      def value
        super().inject('') do |s, (k, v)|
          s + "#{k}='" + v.to_s.gsub(/['\\]/, '\\\\\0') + "' "
        end
      end
    end
  end
end
end
end