• curry 和数学中定义各种符号一样,主要是用来抽取公用部分,简化代码。

    比如高中数学中的累加符号Σ

    对应到 Ruby 代码,我们可以定义一个 sigma lambda

    sigma = -> (f, a, b) { a.upto(b).map{|n| f.(n)}.inject(:+)}
    

    然后用 curry 定义数字累加操作和平方累加操作:

    sum_of_number = sigma.curry.(-> (n) {n})
    sum_of_square = sigma.curry.(-> (n) {n * n})
    
    sum_of_number.(1,10)
    sum_of_square.(1,10)
    

    可以用相同的代码来定义累乘符号∏

    pi = -> (f, a, b) { a.upto(b).map{|n| f.(n)}.inject(:*)}
    

    更进一步,Σ和∏都是范围操作,我们可以用 curry 抽取出来:

    range = -> (x, f, a, b) { x.(a.upto(b).map{|n| f.(n)})}
    sigma = range.curry.(-> (r) {r.inject(:+)})
    pi = range.curry.(-> (r) {r.inject(:*)})
    
    products_of_number = pi.curry.(-> (n) {n})
    
    products_of_number.(1,10)
    
  • 贴一下我之前给一个类似项目做的性能优化,单机目标 500RPS 跑 wrk 本机测试,单机结果 1105RPS, 这是在一台每月 200 元的 2 核 4GB 最低配云主机跑的结果:

      10 threads and 100 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     8.95ms    1.59ms  54.36ms   82.69%
        Req/Sec   224.23    142.93   484.00     79.00%
      11171 requests in 10.10s, 3.05MB read
    Requests/sec:   1105.64
    Transfer/sec:    309.35KB
    

    你要问什么架构?基于 rails-api,redis 存储,都是大路货,没什么高端科技 150 台机器...只能说楼主有钱,请我!每小时仅收费$300,保证赚回你的机器钱

  • 上传大文件和下载一样,可以让 nginx 来负责接收上传的文件,然后 rack 通过 header 从文件系统读取上传完毕的文件:

    https://stackoverflow.com/questions/44371643/nginx-php-failing-with-large-file-uploads-over-6-gb

  • 我现在用的 Intel NUC

  • Ubuntu 17.04 物理机 希望有个命令行就好了

  • 看了一下 README,counter_culture 是通过把更新计数器移到 after_commit 解决的,也算一种绕过去的方法吧

  • 申请删帖 at 2017年06月04日

    他们不但没有做类型检查,反倒是去改变语法

    Javascript 是因为语言本身设计缺陷,所以才需要检查传入的是否是 function,Ruby 已经声明这是一个 blcok,你不可能给这个方法传入第二个参数,完全没必要进行参数类型检查,常见的只是用 block_gvien?检查一下是否有 block:

    class Foo
      def bar(name, &block)
        str = "Hello #{name}"
        yield str if block_given?
      end
    end
    
    foo = Foo.new
    
    # block是可选的:
    foo.bar('world') do |str|
      puts str
    end
    
    foo.bar('ruby')
    

    如果你没有认真学过 Ruby 这门语言,或者只是扫一眼浏览式学习,你根本不知道 yield 做了什么。

    对于没有认真学习又 blahblah 的人,最好的回复是:RTFM

    我去掉了 &b1, &b2, &b3,看看可读性如何,在你看 obj.m1 的时候,你知道 yield 传入了什么吗?看 obj.m2 的时候,或者本来就是从 obj.m2 看起,这时候你肯定会不知道 yield 传入了什么,总的来说:

    yield 本质就是占个位,写 yield 目的就是为了无需知道传入的 block 是做什么,如果要理解 m2 的 yield 传入什么才能读懂整个代码,那说明这里不应该用 block/yield 去实现这种需求,写成这样是你的代码设计有问题。

    但是,ES6 新增了 Promise 和 Generator 已经解决了这些问题,把所有的异步都给我串起来!!!让你们看看什么才叫真正的优雅:

    如果你认真学习过 Ruby,用 block 做 callback 使用也可以写出很优雅的代码,否则就算用 promise 或者 coroutine 也能写出不容易理解的代码,而且你举的代码例子无论从命名和实际用途都不清,如何评价是否优雅?show me the REAL code

    (最后,个人认为 coroutine 最优雅)

  • 量产型炮灰工程师 at 2017年05月22日

    http://threeifbywhiskey.github.io/2014/03/05/non-alphanumeric-ruby-for-fun-and-not-much-else/

    _=$$/$$;__=_-_;@_=_+_;$_=@_+_;$__=@_+$_;$-_=$__*$_;@__=''<<$-_*($__+$_)+@_;$___=''<<$-_*$__-$__<<$-_*($__+@_)<<@__<<@__;@___=''<<$-_*$__-$_*$_<<$-_*($__+$_)-$_<<@__<<@__;(___=->{$.+=_;$><<($.%$-_==__ ?$___+@___:$.%$_==__ ?$___:$.%$__==__ ?@___:$.)<<(''<<$__*@_);$.<($__*@_)**@_?___[]:_})[]
    
  • mysql index 自动选择的问题,常见的坑,可以在查询里面加 FORCE INDEX 来解决

  • 对于这种需求,我推荐 Decorator 模式,有现成的 gem draper 可以用

    https://github.com/drapergem/draper

  • 因为我要想在用户注册之后,加入更多逻辑的话

    比如要加一个 FooBar 的逻辑,你的做法是在 config/initializer/business.rb 加一行:

    Fanli.on(:create_user, [
      SendWelcomeEmail,
      GiveCouponIfXmas,
      GiveInitialCash,
      FooBar,
    ])
    

    而我的做法是在 CreateUser 里面加一行

    [SendWelcomeEmail, GiveCouponIfXmas, GiveInitialCash, FooBar].each
    

    剩下其他代码都是一样的,你可以说你那个是配置,我那个需要修改代码,但是在这个例子里面看不出两者有什么本质区别。

    如果非要改成配置的方式,那么我们改一下代码:

    class CreateUser
      def perform(args)
        user = User.create!(args)
        callbacks(args)
      end
    
      def callbacks(args)
        callbacks_from_config.each do |clazz|
          clazz.(args)
        end
      end
    end
    

    即使抽象一个 Base 出来,看起来和你的例子一模一样了,但是本质上还是意大利面条:

    class Base
      def perform(args)
        _perform(args)
        callbacks(args)
      end
    end
    
    class CreateUser < Base
      def _perform(args)
        user = User.create!(args)
      end
    end
    

    所以从这个例子上我看不出有用 Pub/Sub 的任何优势

  • 代码结构和 README 里面的例子是一模一样的,例子怎么做单元测试,上面的代码也是一样做,单一职责并没有违反,做的事情都在各自代码里面,和例子也是一模一样的

  • 感觉这和直接写意大利面代码没什么区别

    class CreateUser
      def perform(args)
        user = User.create!(args)
    
        [SendWelcomeEmail, GiveCouponIfXmas, GiveInitialCash].each do |clazz|
          clazz.(args)
        end
      end
    end
    
    class SendWelcomeEmail
      def self.call(args)
      end
    end
    
    class GiveCouponIfXmas
      def self.call(args)
      end
    end
    
    class GiveInitialCash
      def self.call(args)
      end
    end
    
  • Map for hash array using &: at 2017年04月30日

    &后面跟的是 Symbol,我们可以给它加个 monkey patch

    class Symbol
      def call(*args, &block)
        ->(caller, *rest) { caller.send(self, *rest, *args, &block) }
      end
    end
    

    然后 call 在 Ruby 里面有.() 的便捷调用,就可以这样写了:

    a = [{aa: '123'}, {aa: '321'}]
    
    a.map &:[].(:aa)
    

    忘记在哪里看到这个技巧的,但是真的很好用

    [%w(hello world), %w(ruby on rails), %w(foo bar)].map(&:inject.(&:+))
    
  • nginx 设置一下,其他域名访问重定向到 ruby-china.org,就可以了,管局只看在浏览器里面输入域名,然后看返回的是什么

  • 在 Java 里面很流行的做法,用 annotation 做 AOP,ruby 有一些 gem 可以让你很方便写,比如 https://github.com/comparaonline/co_aspects

    你需要自己写一个 Aspect:

    module CoAspects
      module Aspects
        class CacheAspect < Aspector::Base
          around method_arg: true do |method, proxy, *args, &block|
            cache_key = [self.class, method].join('.') + ':' + args.join(',')
            Cache.fetch cache_key do
              proxy.call(*args, &block)
            end
          end
        end
      end
    end
    

    用到这个 Aspect 的地方,写一个 annotation(伪)就可以了:

    class Foo
      aspects_annotations!
    
      _cache
      def bar
        'bar'
      end
    end
    
  • 数据库开 slow query log,5.7 还是慢可能和查询语句有关,把 log 到的语句 explain 一下看看

  • 以前项目中用 imagemagick 执行命令行实现:

    convert your.jpg -colors 256 -format %c  -depth 8  histogram:info:-
    
  • #5 楼 @themadeknight

    mysql 有 select into,和 copy 命令类似,能支持各种选项,导出 csv 的例子:

    SELECT * INTO OUTFILE '/tmp/result.csv'
      FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
      LINES TERMINATED BY '\n'
      FROM table;
    
  • Oj.dump 一个 NaN 会出现 PI at 2016年12月01日

    用超过上限的数字来表示 NaN,保证 dump 回来的数据能正常显示 NaN?哈哈哈哈

    https://github.com/ohler55/oj/blob/cecfe196af51e8fc964cd6d9751e50724f1cb8bf/ext/oj/oj.h#L73

    #define INF_VAL     "3.0e14159265358979323846"
    #define NINF_VAL    "-3.0e14159265358979323846"
    #define NAN_VAL     "3.3e14159265358979323846"
    
  • RubyConf China 2016 视频 at 2016年10月29日

    #23 楼 @huacnlee 另外再报告一个 bug,发帖的上传图片按钮,事件好像被绑定了多次,重现: 在本页面,点击任意一个其他链接,然后点击浏览器返回按钮,点击上传图片按钮,会弹出 2 次

  • RubyConf China 2016 视频 at 2016年10月29日

    #23 楼 @huacnlee 报告一个 bug,@ 通知的人错了:

  • 这个 eval 解决 Leetcode 问题的想法好有趣

  • #15 楼 @tianlitao end_a < start_c 就是||表达式右边的第二种情况呀

  • 不写测试代码 at 2016年10月16日

    我一般 CRUD 不写测试代码,只写测试代码测试复杂逻辑和用来重现用户报告的 Bug 然后并修复它

  • 判断时间区段重叠可以通过这样的方式来简化:

    先是判断时间区段不重叠,有 2 种情况

                            |start_a ----- end_a| 
    |start_b ----- end_b|                       
    
    ---------------------------------------------
    
    |start_a ----- end_a|                        
                            |start_b ----- end_b|
    

    得出不重叠的表达式是:

    start_a > end_b || end_a < start_b
    

    那么不重叠就是取反

    !(start_a > end_b || end_a < start_b)
    

    布尔运算等价于

    start_a <= end_b and end_a >= start_b
    

    代码可以简化成:

    plan = Plan.where('start_time <= ? and end_time >= ?', end_at, start_at)
    
  • 是的,Ruby 没有 primitive 类型,proc 也是 Object,method 也是 Object

    1.is_a? Object
    #true
    
    proc = -> {puts 1}
    proc.is_a? Object
    #true
    
    class String
      def -(s)
        self.gsub(s, '')
      end
    end
    "abc".method(:-).is_a? Object
    #true
    
  • @bastengao @lainuo ruby 用的 OpenSSL 可以直接设置 padding,没有必要自己再去实现一次

    cipher.padding = 7
    
  • 看了一下 rfc,是要求有空格的,那就不是 bug 了,是发起方没有遵循 rfc http://www.rfc-base.org/txt/rfc-2183.txt

    disposition := "Content-Disposition" ":"
                   disposition-type
                   *(";" disposition-parm)
    
  • 恭喜你找到了 rack 的 bug,这里的正则表达式用了\s: \sfilename,可以去提个 pull request 了