• 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

  • 我推荐过云梯给很多朋友,超过10个了吧,和宽带提供商有很大关系,比如我温州的2个朋友和你情况类似,效果很差,而大部分人情况和我类似,非常稳定。

    上网高峰期(晚上9点~11点),下行速度一般在5M以下,延迟150ms+,非高峰期,超过10M,看youtube 720P无压力

    证明不是托,我来随手贴个图:

  • 我现在用的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 就是||表达式右边的第二种情况呀