advantage of tap method in ruby

后端 未结 19 1092
天命终不由人
天命终不由人 2020-12-22 16:50

I was just reading a blog article and noticed that the author used tap in a snippet something like:

user = User.new.tap do |u|
  u.username = \         


        
19条回答
  •  不知归路
    2020-12-22 17:45

    It results in less-cluttered code as the scope of variable is limited only to the part where it is really needed. Also, the indentation within the block makes the code more readable by keeping relevant code together.

    Description of tap says:

    Yields self to the block, and then returns self. The primary purpose of this method is to “tap into” a method chain, in order to perform operations on intermediate results within the chain.

    If we search rails source code for tap usage, we can find some interesting usages. Below are few items (not exhaustive list) that will give us few ideas on how to use them:

    1. Append an element to an array based on certain conditions

      %w(
      annotations
      ...
      routes
      tmp
      ).tap { |arr|
        arr << 'statistics' if Rake.application.current_scope.empty?
      }.each do |task|
        ...
      end
      
    2. Initializing an array and returning it

      [].tap do |msg|
        msg << "EXPLAIN for: #{sql}"
        ...
        msg << connection.explain(sql, bind)
      end.join("\n")
      
    3. As syntactic sugar to make code more readable - One can say, in below example, use of variables hash and server makes the intent of code clearer.

      def select(*args, &block)
          dup.tap { |hash| hash.select!(*args, &block) }
      end
      
    4. Initialize/invoke methods on newly created objects.

      Rails::Server.new.tap do |server|
         require APP_PATH
         Dir.chdir(Rails.application.root)
         server.start
      end
      

      Below is an example from test file

      @pirate = Pirate.new.tap do |pirate|
        pirate.catchphrase = "Don't call me!"
        pirate.birds_attributes = [{:name => 'Bird1'},{:name => 'Bird2'}]
        pirate.save!
      end
      
    5. To act on the result of a yield call without having to use a temporary variable.

      yield.tap do |rendered_partial|
        collection_cache.write(key, rendered_partial, cache_options)
      end
      

提交回复
热议问题