Last active
December 20, 2018 02:14
-
-
Save hanachin/0972004fa4d7251a32c32c816b1233e8 to your computer and use it in GitHub Desktop.
定数の名前書き換えloadするimport_as gemの紹介 ref: https://qiita.com/hanachin_/items/c3c513b1215de18b62f3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ImportAs | |
class DSL | |
def initialize(&block) | |
@as = block | |
end | |
end | |
def import(&block) | |
DSL.new(&block) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ImportAs | |
class DSL | |
def from(path) | |
Tempfile.open(["import_as", ".rb"]) do |tf| | |
new_source = rewrite(File.read(path)) | |
tf.write(new_source) | |
tf.flush | |
tf.close | |
load tf.path | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ImportAs | |
class ConstRewriter | |
def initialize(const_hash) | |
@rewriter = Class.new(Ripper::Filter) { | |
private | |
define_method(:on_const) do |t, f| | |
f << const_hash.fetch(t.to_sym, t).to_s | |
end | |
def on_default(_, t, f) | |
f << t | |
end | |
} | |
end | |
def rewrite(ruby) | |
@rewriter.new(ruby).parse('') | |
end | |
end | |
class DSL | |
private | |
def rewrite(rb) | |
ConstRewriter.new(const_hash).rewrite(rb) | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ImportAs | |
class DSL | |
private | |
using Module.new { | |
refine(Symbol) do | |
def const_id? | |
id = self | |
Module.new.module_eval { const_set(id, true) rescue false } | |
end | |
end | |
refine(RubyVM::AbstractSyntaxTree::Node) do | |
def array? | |
type == "NODE_ARRAY" | |
end | |
def const? | |
type == "NODE_CONST" | |
end | |
def fcall? | |
type == "NODE_FCALL" | |
end | |
def scope? | |
type == "NODE_SCOPE" | |
end | |
def const_pair | |
original_const_id, args = children | |
raise Error unless original_const_id.const_id? | |
raise Error unless args.array? | |
head, *rest = args.children | |
raise Error unless rest.size == 1 && rest[0].nil? | |
raise Error unless head.fcall? | |
as, args2 = head.children | |
raise Error unless as == :as | |
head2, *rest2 = args2.children | |
raise Error unless rest.size == 1 && rest[0].nil? | |
raise Error unless head2.const? | |
raise Error unless head2.children.size == 1 | |
new_const_id = head2.children[0] | |
raise Error unless new_const_id.const_id? | |
[original_const_id, new_const_id] | |
end | |
end | |
} | |
def const_hash | |
root = RubyVM::AbstractSyntaxTree.of(@as) | |
raise Error unless root.scope? | |
_tbl, _args, body = root.children | |
raise Error unless body.fcall? | |
[body.const_pair].to_h | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class LordVoldemort | |
def name | |
"Voldemort" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "import_as/core_ext" | |
import { LordVoldemort as YouKnowWho }.from File.expand_path("./lord_voldemort.rb", __dir__) | |
puts YouKnowWho.new.name | |
# Voldemort | |
puts LordVoldemort.new.name | |
# Traceback (most recent call last): | |
# main.rb:8:in `<main>': uninitialized constant LordVoldemort (NameError) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment