• Ruby 模仿:|> at 2017年08月12日

    想玩魔法的话其实call也不用的,也不用method_missing,在执行block之前做个宏替换:

    require 'ruby_parser'
    require 'ruby2ruby'
    require 'method_source'
    
    class Object
      class Proxy < BasicObject
        def call value
          @_ = value
        end
    
        def _
          @_
        end
    
        def initialize target
          @_ = target
        end
      end
    
      def pipe &block
        source = block.source
        block_body = RubyParser.new.process(source).to_a[3]
        head, *sequences = block_body
        sequences.map!{|x| [:call, nil, :call, x]}
        ast = Sexp.from_array([:block, *sequences])
        Proxy.new(self).instance_eval Ruby2Ruby.new.process(ast)
      end
    end
    
    #==========业务代码分割线=========
    
    class ServiceA
      def initialize(n); @n = n; end
    
      def do_something
        p @n
        @n + 1
      end
    end
    
    class ServiceB
      def initialize(n); @n = n; end
    
      def do_something_else
        p @n
      end
    end
    
    some_data = 1
    some_data.pipe do
      ServiceA.new(_).do_something  # => print 1
      ServiceB.new(_).do_something_else  # => print 2
    end
    
  • Ruby 模仿:|> at 2017年08月12日

    可以的,_就是上一行的结果,call的作用就是赋值给_https://ruby-china.org/topics/31848

  • Ruby 模仿:|> at 2017年08月12日

    其实ruby完全可以定义一些运算符,甚至超算符...

    some_data
    >> ServiceOne.do_something
    >> ServiceOne.do_something_else
    

    用这套配组合子可以玩的很开心……

    但是要ruby way的话,我想应该是这样子:

    some_data.pipe do
      call ServiceOne.new(_).do_something
      call ServiceTwo.new(_).do_something_else
    end
    

    因为管道本质上是要把占位符拿出来,这样也许不算太优雅,但是也许有些地方能用到,另外个人觉得binding.pry其实比puts要方便.....

    抄送 @luikore ;-)

  • cool,那个class 和def 是用宏做的吗?

  • 物理机 ubuntu 无桌面环境 i3wm

  • MainCombinePackageItem.joins('INNER JOIN packages main_package ON main_package.id = main_combine_package_items.main_package_id')
                          .joins('INNER JOIN packages combined_package ON combined_package.id = main_combine_package_items.combined_package_id')
                          .where('main_package.state NOT IN ? or combined_package.state NOT IN ?', [9, 10], [9, 10])
                          .where(warehouse_id: 1)
    

    像楼上说的not in如果用不到索引的话,可以改成in,一共有哪些状态是知道的

  • rails在joins和eager_load同一个表的时候会加上别名的:

    MainCombinedPackageItem.joins(:main_package, :combined_package)
    
    SELECT "main_combined_package_items".* FROM "main_combined_package_items" INNER JOIN "packages" ON "packages"."id" = "main_combined_package_items"."main_package_id" INNER JOIN "packages" "combined_packages_main_combined_package_items" ON "combined_packages_main_combined_package_items"."id" = "main_combined_package_items"."combined_package_id"
    

    第二个packages表加了combined_packages_main_combined_package_items的别名,可以直接在where用,但是我觉得这样不好,干脆直接写sql或者用把sql拆成手写的joins() where()

  • 惊了可还行,怕不是真实猛男(滑稽

    不过ruby用的不是引用计数,是mark and sweep: http://blog.jobbole.com/60900/

  • 只要记住ruby里传递的永远是引用就好了,包括数字传的也是引用,不提供代码块,只提供一个对象引用的话,这个对象不一定是可复制的(虽然数组可以),所以Array.new肯定不会帮你复制

  • 嗯,我看看