Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@avdi
Last active August 29, 2018 07:43
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avdi/6123055 to your computer and use it in GitHub Desktop.
Save avdi/6123055 to your computer and use it in GitHub Desktop.
Modules for macros. In reference to: http://thepugautomatic.com/2013/07/dsom/
class SomeORM
def self.attributes(*names)
if const_defined?(:DynamicAttributes, false)
mod = const_get(:DynamicAttributes)
else
mod = const_set(:DynamicAttributes, Module.new)
include mod
end
mod.module_eval do
names.each do |name|
define_method(name) do
# Stuff
end
end
end
end
end
@henrik
Copy link

henrik commented Jul 31, 2013

Thanks for the feedback!

I like how this solution uses plain constants to keep down the number of modules (one per class in an inheritance hierarchy), unique-enough names (no need for object ids as it's again one per class), and of course for naming.

@henrik
Copy link

henrik commented Jul 31, 2013

One thing I dislike slightly about this compared to my original solution is that Post::DynamicAttributes perhaps gives less of a clue where the module comes from than SomeORM::DynamicAttributes123. But I suppose "where it comes from" is kind of hard to decide anyway – SomeORM generates it, but you declared the attributes in Post, which is-a SomeORM anyway.

I suppose you could call it Post::SomeORMDynamicAttributes if you want to be very clear.

@avdi
Copy link
Author

avdi commented Jul 31, 2013

I also like to define a custom #to_s on these modules so that when listed with #ancestors you see e.g. DynamicAttributes(attr1, attr2, attr3). I think I showed that in one of the RubyTapas episodes I mentioned on Twitter.

@henrik
Copy link

henrik commented Jul 31, 2013

I checked out episode 28, it's in there. Clever!

@henrik
Copy link

henrik commented Jul 31, 2013

For my own future reference, the above could be achieved with something along the lines of (after line 15):

def mod.to_s
  "DynamicAttributes(#{instance_methods(false).join(', ')})"
end

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