Ruby知识积累2

4 篇文章 0 订阅
  • Block:
    •   Proc.new
          my_proc = Proc.new { puts "tweet" }
          my_proc.call
        lambda
          my_proc = lambda { puts "tweet" }
          my_proc.call
        ->
          my_proc = -> { puts "tweet" }
          my_proc.call
        Parameter:
          e.g.
            class Tweet
              def post(success, error)
                if authenticate?(@user, @password)
                  success.call
                else
                  error.call
                end
              end
            end
      
      
            tweet = Tweet.new('Ruby Bits!')
            success = -> { puts "Sent!" }
            error = -> { raise 'Auth Error' }
            tweet.post(success, error)
          e.g.
            tweets = ["First tweet", "Second tweet"]
            printer = lambda { |tweet| puts tweet }
            tweets.each(&printer) # &操作符将lambda转换为block
        block_given?
          e.g.
            class Timeline
              attr_accessor :tweets
              def print
                if block_given?
                  tweets.each { |tweet| puts yield tweet }
                else
                  puts tweets.join(', ')
                end
              end
            end
      
      
            timeline = Timeline.new
            timeline.tweets = ["One", "Two"]
            timeline.print
            timeline.print { |tweet|
              "tweet: #{tweet}"
            }
          e.g.
            class Tweet
              def initialize
                yield self if block_given?
              end
            end
            Tweet.new do |tweet|
              tweet.status = "Set in initialize!"
              tweet.created_at = Time.now
            end
        closure(闭包):
          def tweet_as(user)
            lambda { |tweet| puts "#{user}: #{tweet}" }
          end
          gregg_tweet = tweet_as("andy")
          greeg_tweet.call("Mind blowing!")
      
      
        Symbol#to_proc
          tweets.map { |e| tweet.user  }
          tweets.map(&:user)
  • Struct:
    •   e.g.
          类:
            class Tweet
              attr_accessor :user, :status
      
      
              def initialize(user, status)
                @user, @status = user, status
              end
      
      
              def to_s
                "#{user}: #{status}"
              end
            end
          结构体:
            Tweet = Struct.new(:user, :status) do
              def to_s
                "#{user}: #{status}"
              end
            end
  • Alias_method:
    • Bad:
          class Timeline
            def initialize(tweets = [])
              @tweets = tweets
            end
      
      
            def tweets
              @tweets
            end
      
      
            def contents
              @tweets
            end
          end
        Good:
          class Timeline
            def initialize(tweets = [])
              @tweets = tweets
            end
      
      
            attr_reader :tweets
            alias_method :contents, :tweets
          end
  • Define_method:
    • e.g.
          native:
            class Tweet
              def draft
                @status = :draft
              end
      
      
              def posted
                @status = :posted
              end
      
      
              def deleted
                @status = :deleted
              end
            end
          change:
            class Tweet
              status = [:draft, :posted, :deleted]
              status.each do |status|
                define_method status do
                  @status = status
                end
              end
            end
  • Send:(常用于访问protected和private方法)
    • e.g.
          class Timeline
            def initialize(tweets)
              @tweets = tweets
            end
      
      
            def contents
              @tweets
            end
      
      
            private
              def direct_message
                #...
              end
          end
          tweets = ['Compiling!', 'Bundling...']
          timeline = Timeline.new(tweets)
          timeline.contents
          timeline.send(:contents)
          timeline.send("contents")
          timeline.send(:direct_message)
          timeline.public_send("direct_message")   # only can access public methods
  • Method:
    • e.g.
          class Timeline
            def initialize(tweets)
              @tweets = tweets
            end
      
      
            def contents
              @tweets
            end
      
      
            def show_tweet(index)
              puts @tweets[index]
            end
          end
          tweets = ['Compiling!', 'Bundling...']
          timeline = Timeline.new(tweets)
          content_method = timeline.method(:contents)
          content_method.call
          show_tweet = timeline.method(:show_tweet)
          show_tweet.call(0)
          (0..1).each(&show_tweet)      #相当于show_tweet(0)和show_tweet(1)
  • Self:
    • e.g.
          puts "Outside the class: #{self}"    # main
          class Tweet
            puts "Inside the class: #{self}"   # Tweet
            def self.find(keyword)
              # ...
            end
          end
  • Class_eval(在指定类中执行):
    • e.g.
          class Tweet
            attr_accessor :status
            attr_reader :created_at
            def initialize(status)
              @status = status
              @created_at = Time.now
            end
          end
      
      
          Tweet.class_eval do
            attr_accessor :user
          end
          tweet = Tweet.new("Learning class_eval")
          tweet.user = "doit"
  • Create a log_method:
    •   log_method以类名和方法名作为参数,调用class_eval来执行类中的代码。使用alias_method来保存原先的方法,使用define_method来重定义方法,对该方法的调用过程进行记录,使用send来调用原先的方法。
        class MethodLogger
          def log_method(klass, method_name)
            klass.class_eval do
              alias_method "#{method_name}_original", method_name
              define_method method_name do |*args, &block|
                puts "#{Time.now}: Called #{method_name}"
                send "#{method_name}_original", *args, &block
              end
            end
          end
        end
        e.g.
          class Tweet
            def say_hi
              puts "hi"
            end
          end
          logger = MethodLogger.new
          logger.log_method(Tweet, :say_hi)
          Tweet.new.say_hi
  • Instance_eval:
    •  e.g.
          class Tweet
            attr_accessor :user, :status
          end
          tweet = Tweet.new
          tweet.instance_eval do
            self.status = "Changing the tweet's status"
          end
        Good:
          class Tweet
            attr_accessor :user, :status
            def initialize
              yield self if block_given?
            end
          end
          Tweet.new do |tweet|
            tweet.status = "I was set in the initialize block!"
            tweet.user = "Gregg"
          end
        Better:
          class Tweet
            attr_accessor :user, :status
            def initialize(&block)
              instance_eval(&block) if block_given?
            end
          end
  • Method_missing:
    • 当无法找到方法时调用
        e.g.
          class Tweet
            def method_missing(method_name, *args)
              logger.warn "You tried to call #{method_name} with these arguments: #{args}"
              super   # ruby's default method handling raise a NoMethodError
            end
          end
        e.g.(对一些方法进行委托)
          class Tweet
            DELEGATED_METHODS = [:username, :avatar]
      
      
            def initialize(user)
              @user = user
            end
      
      
            def method_missing(method_name, *args)
              if DELEGATED_METHODS.include?(method_name)
                @user.send(method_name, *args)
              else
                super
              end
            end
          end
        e.g.(将未知方法,全部委托到user)
          require 'delegate'
          class Tweet < SimpleDelegator
            def initialize(user)
              super(user)
            end
          end
        e.g.
          class Tweet
            def initialize(text)
              @text = text
            end
      
      
            def to_s
              @text
            end
      
      
            def method_missing(method_name, *args)
              match = method_name.to_s.match(/^hash_(\w+)/)
              if match
                @text << " #" + match[1]
              else
                super
              end
            end
          end
        e.g.(define_method)
          class Tweet
            def initialize(text)
              @text = text
            end
      
      
            def to_s
              @text
            end
      
      
            def method_missing(method_name, *args)
              match = method_name.to_s.match(/^hash_(\w+)/)
              if match
                self.class.class_eval do
                  define_method(method_name) do
                    @text << " #" + match[1]
                  end
                end
                send(method_name)
              else
                super
              end
            end
          end
  • Response_to?:
    • e.g.
          class Tweet
            ...
            def respond_to?(method_name)
              method_name =~ /^hash_\w+/ ||super
            end
          end
      
      
          tweet = Tweet.new
          tweet.respond_to?(:to_s)
          tweet.respond_to?(:hash_ruby)
          tweet.method(:hash_ruby)  # NameError:undefined method
  • Response_to_missing?:(Ruby 1.9.3)
    •   e.g.
          class Tweet
            ...
            def respond_to_missing?(method_name)
              method_name =~ /^hash_\w+/ ||super
            end
          end
      
      
          tweet = Tweet.new
          tweet.method(:hash_ruby)  # return a Method object
  • Implement a simple DSL:
    • DSL:领域专用语言
        e.g.
          class Tweet
            def initialize(user)
              @user = user
              @tweets = []
              @annotations = {}
            end
      
      
            def submit_to_twitter
              tweet_text = @tweet.join(' ')
              if tweet_text.length <= 140
                puts "#{@user}: #{tweet_text}"
                puts @annotations.inspect unless @annotations.empty?
              else
                raise "your tweet is too long."
              end
            end
            def text(str)
              @tweet << str
              self
            end
            def mention(*users)
              users.each do |user|
                @tweet << "@" + user
              end
              self
            end
            def hashtag(str)
              @tweet << "#" + str
              self
            end
            def link(str)
              @tweet << str
            end
      
      
            def method_missing(method, *args)
              @annotations[method] = args.join(', ')
            end
          end
      
      
          def tweet_as(user, text=nil,&block)
            tweet = Tweet.new(user)
            tweet.text(text) if text
            tweet.instance_eval(&block) if block_given?
            tweet.submit_to_twitter
          end
      
      
          tweet_as 'marken' do
            mention 'china','usa'
            text('I made a DSL!').hashtag('hooray').hashtag('ruby')
            link 'http://www.somewhere.com'
          end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值