This allows to restrict some method calls and allow to only specific classes.
Last active
March 19, 2019 20:11
-
-
Save ktimothy/d2ffb3b1c529cd8e0e16f9d6302f4c85 to your computer and use it in GitHub Desktop.
Almost dynamic refinement in ruby.
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 Restrictor | |
# used to save chains of const_missing method calls | |
# will allow to use constant instead of string even before constant was defined | |
# e. g. Okay::Allowed instead of 'Okay::Allowed' | |
class MissingChainer | |
def self.create | |
Class.new(self) | |
end | |
def self.const_missing(constant) | |
add_to_chain(constant) | |
self | |
end | |
def self.add_to_chain(c) | |
@chain ||= [] | |
@chain << c.to_s | |
end | |
def self.erase_chain! | |
result = @chain.join('::') rescue nil | |
@chain = [] | |
result | |
end | |
def self.chain | |
@chain.join('::') rescue nil | |
end | |
def self.to_s | |
chain | |
end | |
end | |
def restrict_method(name, *allow_tos) | |
alias_method("__#{name}", name) | |
define_method(name) { :restricted } | |
klass = self | |
allow_tos.each do |allow_to| | |
refined_module = Restrictor[allow_to.to_s] | |
refined_module.instance_exec do | |
refine klass do | |
define_method(name) do | |
send("__#{name}") | |
end | |
end | |
end | |
end | |
end | |
def const_missing(constant) | |
MissingChainer.create.const_missing(constant) | |
end | |
def self.[](model_or_name) | |
Restrictor.dict[model_or_name.to_s] ||= Module.new {} | |
end | |
private | |
def self.dict | |
@@dictionary ||= {} | |
end | |
end | |
class Model | |
extend Restrictor | |
def ololo | |
:allowed | |
end | |
restrict_method :ololo, Checker, Allowed, Okay::Allowed, One::Two::Three::Allowed | |
end | |
class Allowed | |
using Restrictor[self] | |
def try_it | |
Model.new.ololo | |
end | |
end | |
module Okay | |
class Allowed | |
using Restrictor[self] | |
def try_it | |
Model.new.ololo | |
end | |
end | |
end | |
module One | |
module Two | |
module Three | |
class Allowed | |
using Restrictor[self] | |
def try_it | |
Model.new.ololo | |
end | |
end | |
end | |
end | |
end | |
class Checker < One::Two::Three::Allowed | |
using Restrictor[self] | |
def try_it | |
Model.new.ololo | |
end | |
end | |
puts Model.new.ololo | |
puts Allowed.new.try_it | |
puts Okay::Allowed.new.try_it | |
puts One::Two::Three::Allowed.new.try_it | |
puts Checker.new.try_it |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment