Created
October 4, 2011 03:09
-
-
Save mvaled/1260817 to your computer and use it in GitHub Desktop.
Ejemplo de módulos en Ruby. Ver post: http://manuelonsoftware.wordpress.com/?p=225
This file contains 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
#!/usr/bin/env ruby | |
# -*- encoding: utf-8 -*- | |
# Mostly stealed from ActiveSupport | |
class Module | |
# Encapsulates the common pattern of: | |
# | |
# alias_method :foo_without_feature, :foo | |
# alias_method :foo, :foo_with_feature | |
# | |
# With this, you simply do: | |
# | |
# alias_method_chain :foo, :feature | |
# | |
# And both aliases are set up for you. | |
# | |
# Query and bang methods (foo?, foo!) keep the same punctuation: | |
# | |
# alias_method_chain :foo?, :feature | |
# | |
# is equivalent to | |
# | |
# alias_method :foo_without_feature?, :foo? | |
# alias_method :foo?, :foo_with_feature? | |
# | |
# so you can safely chain foo, foo?, and foo! with the same feature. | |
def alias_method_chain(target, feature) | |
# Strip out punctuation on predicates or bang methods since | |
# e.g. target?_without_feature is not a valid method name. | |
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1 | |
yield(aliased_target, punctuation) if block_given? | |
with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}" | |
alias_method without_method, target | |
alias_method target, with_method | |
case | |
when public_method_defined?(without_method) | |
public target | |
when protected_method_defined?(without_method) | |
protected target | |
when private_method_defined?(without_method) | |
private target | |
end | |
end | |
# Allows you to make aliases for attributes, which includes | |
# getter, setter, and query methods. | |
# | |
# Example: | |
# | |
# class Content < ActiveRecord::Base | |
# # has a title attribute | |
# end | |
# | |
# class Email < Content | |
# alias_attribute :subject, :title | |
# end | |
# | |
# e = Email.find(1) | |
# e.title # => "Superstars" | |
# e.subject # => "Superstars" | |
# e.subject? # => true | |
# e.subject = "Megastars" | |
# e.title # => "Megastars" | |
def alias_attribute(new_name, old_name) | |
module_eval <<-STR, __FILE__, __LINE__ + 1 | |
def #{new_name}; self.#{old_name}; end # def subject; self.title; end | |
def #{new_name}?; self.#{old_name}?; end # def subject?; self.title?; end | |
def #{new_name}=(v); self.#{old_name} = v; end # def subject=(v); self.title = v; end | |
STR | |
end | |
end |
This file contains 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
#!/usr/bin/env ruby | |
# -*- encoding: utf-8 -*- | |
# switchable.rb | |
# | |
# Copyright 2011 Manuel Vazquez Acosta <manu@pavla> | |
# | |
# This program is free software; you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation; either version 2 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program; if not, write to the Free Software | |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
# MA 02110-1301, USA. | |
# | |
# | |
require './ext/module.rb' # File from this gist | |
require 'rubygems' | |
require 'highline/import' | |
module Switchable | |
def initialize(*args) | |
super(*args) | |
@switchable_status ||= false | |
end | |
def on(*args, &block) | |
@switchable_status = true | |
end | |
def off(*args, &block) | |
@switchable_status = false | |
end | |
def is_on? | |
@switchable_status == true | |
end | |
def switch(*args, &block) | |
if is_on? | |
off(*args, &block) | |
else | |
on(*args, &block) | |
end | |
end | |
end | |
module RequireSecret | |
def initialize(*args) | |
super(*args) | |
@secret ||= nil | |
@secret = yield(:initialize_password) if block_given? | |
end | |
def set_secret(old_secret=nil, new_secret=nil, &block) | |
old_secret ||= yield(:current_password, @secret) if block_given? | |
if old_secret == @secret | |
if block_given? | |
@secret = new_secret || yield(:new_password, old_secret) | |
else | |
@secret = new_secret || @secret | |
end | |
end | |
end | |
def on_with_secret(*args, &block) | |
secret = yield(:ask_for_password, @secret) if block_given? | |
if secret == @secret | |
on_without_secret(*args, &block) | |
else | |
raise "Invalid Password" | |
end | |
end | |
def self.included(base) | |
raise "This works only on Switchable objects" unless base.include? Switchable | |
base.class_eval do | |
alias_method_chain :on, :secret # Magic, now the method on will ask for the password | |
end | |
end | |
end | |
module ActAsSwitch | |
def initialize | |
super | |
@target = yield(:connect_to_switachable) if block_given? | |
end | |
def switch_with_acts_as_switch &block | |
@target.switch &block | |
switch_without_acts_as_switch(&block) if respond_to? :switch_without_acts_as_switch | |
end | |
def self.included(base) | |
base.class_eval do | |
if base.include? Switchable | |
alias_method_chain :switch, :acts_as_switch | |
else | |
alias_method :switch, :switch_with_acts_as_switch | |
end | |
end | |
end | |
end | |
module Interactive | |
def self.prompt(what, echo=nil) | |
result = ask("You are require to type something to #{what}: ") { |console| console.echo = echo if echo } | |
end | |
ASK_THE_USER = Proc.new { |what| | |
prompt what | |
} | |
ASK_A_SECRET = Proc.new { |what| | |
prompt(what, '.') | |
} | |
ASK_THE_USER_TO_MATCH_SOMETHING = Proc.new do |what, match| | |
answer = nil | |
until answer == match | |
answer = prompt(what, '.') | |
puts "Your answer does not match the required #{what}" unless answer == match | |
end | |
answer | |
end | |
ASK_THE_USER_TO_NOT_MATCH_SOMETHING = Proc.new do |what, mismatch| | |
answer = nil | |
begin | |
answer = prompt(what, '.') | |
puts "Your answer is required not to match #{mismatch}" if answer == mismatch | |
end while answer == mismatch | |
answer | |
end | |
PRINT = Proc.new do |message| | |
puts message | |
end | |
end | |
class Door | |
include Switchable | |
end | |
class SecretDoor | |
include Switchable | |
include RequireSecret | |
def initialize &block | |
if block_given? | |
super | |
else | |
super &Interactive::ASK_A_SECRET | |
end | |
end | |
# A door opens and closes | |
alias_method :open, :on | |
alias_method :close, :off | |
end | |
class Lever | |
include Switchable | |
include ActAsSwitch | |
end | |
normal_door = Door.new | |
secret_door = SecretDoor.new | |
lever1 = Lever.new { normal_door } | |
lever2 = Lever.new { secret_door } | |
lever1.switch &Interactive::ASK_THE_USER_TO_MATCH_SOMETHING | |
if normal_door.is_on? | |
puts "Normal Door is open" | |
else | |
puts "Normal Door is closed" | |
end | |
lever1.switch &Interactive::ASK_THE_USER_TO_MATCH_SOMETHING | |
if normal_door.is_on? | |
puts "Normal Door is open" | |
else | |
puts "Normal Door is closed" | |
end | |
lever2.switch &Interactive::ASK_THE_USER_TO_MATCH_SOMETHING | |
if secret_door.is_on? | |
puts "Secret Door is open" | |
else | |
puts "Secret Door is closed" | |
end | |
lever2.switch &Interactive::ASK_THE_USER_TO_MATCH_SOMETHING | |
if secret_door.is_on? | |
puts "Secret Door is open" | |
else | |
puts "Secret Door is closed" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment