Skip to content

Instantly share code, notes, and snippets.

@mvaled
Created October 4, 2011 03:09
Show Gist options
  • Save mvaled/1260817 to your computer and use it in GitHub Desktop.
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
#!/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
#!/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