Skip to content

Instantly share code, notes, and snippets.

@kwstannard
Last active October 3, 2015 01:54
Show Gist options
  • Save kwstannard/ab9be39465754ec41a85 to your computer and use it in GitHub Desktop.
Save kwstannard/ab9be39465754ec41a85 to your computer and use it in GitHub Desktop.
### In file version
klass = Class.new do
def hi
puts 'hello'
end
end
name = __FILE__.slice(/\w*.rb$/).slice(/\w*/).camelcase
Object.const_set(name, klass)
### Extracted version
class Dryer
def self.dry_class(file_name, &blk)
klass = Class.new &blk
name = __FILE__.slice(/\w*.rb$/).slice(/\w*/).camelcase
Object.const_set(name, klass)
end
end
Dryer.dry_class(__FILE__) do
def herp
puts 'hello'
end
end
### with inheritance
class Dryer
def self.dry_class(file_name, super_class, &blk)
klass = Class.new(super_class, &blk)
name = __FILE__.slice(/\w*.rb$/).slice(/\w*/).camelcase
Object.const_set(name, klass)
end
end
Dryer.dry_class(__FILE__, ActiveRecord::Base) do
def herp
puts 'hello'
end
end
@kwstannard
Copy link
Author

latest crazy rails version:

class Dryer < Struct.new(:file_path, :super_class, :blk)
  def self.dry_class(file_path, super_class=Object, &blk)
    new(file_path, super_class, blk).dry_class
  end

  def dry_class
    constant_names.each.with_index.inject(Object) do |const, (next_const, index)|

      if const.const_defined?(next_const)
        const.const_get(next_const)
      else
        if constant_names.length == index + 1

          # this is needed to set the class name so that activerecord
          # works properly
          klass = const.const_set(next_const, Class.new(super_class))

          # here we eval the class block to define methods and everything
          klass.class_eval &blk
        else
          const.const_get(next_const)
        end
      end
    end
  end

  def constant_names
    get_name.split('/').map(&:camelcase)
  end

  def get_name
    file_path.gsub(most_likely_path, '').gsub(".rb", '')
  end

  def most_likely_path
    self.class.all_autoload_paths.map{|p| file_path[/^#{p}/] || ""}.sort.last + '/'
  end

  def self.all_autoload_paths
    config = Rails.configuration
    config.autoload_paths + config.eager_load_paths + config.autoload_once_paths
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment