• https://ruby-china.org/topics/31956 https://ruby-china.org/topics/32024 他写了两篇文章,可以先看一下。 不过,重构首先要技术过关,你自己也觉得 ruby 水平一般,就尽量先别动。能跑的代码总比出问题的代码好。哈哈。

  • 书写规范,如果返回到是布尔,就用问号

  • 吱,好久没参加聚会了。

  • 如果一定要想实现在自己的服务器上登录微信的话,看下面这个。 Python 版 WeixinBot,基于微信 Web 的 API,我们是用 Ruby 重写了发送消息的功能。其他的自己写也能搞定。

  • 哈哈,我想写到退休...

  • 买一本支持一下。

  • 关于 ElasticSearch 的疑惑 at 2016年11月30日

    其实,你可以看一下 Ruby China 的源代码,它就是用的 Elasticsearch,看看它怎么用的 Elasticsearch,在 Model 里做了什么,Gemfile 里用了那几个 gem 就知道了。再看看官方的文档就知道了。

  • 这个好,👍 💪

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

    刚进公司时,负责将代码从 Rails 3 升级到 Rails 4,但是他们之前只写了一小部分。于是我重新补写了所有 Model,Controller 的测试(以前其实我也不写测试,之前的公司太 “敏捷”😂 ) 但写了之后,我有下面几个感觉

    1. 不是所有的地方都需要写测试(不知道对不对)
    2. 写测试的好处是,自己会更加全面的去考虑 “接口” 的设计
    3. 在修改接口时,可以通过测试来保证接口的正确性
    4. 实际上大大加快了开发效率,因为你写的代码总是要测试的,不管是用什么,测试总比人肉快
  • 实际上, if: :password_required?if option 特性,并不是来做ActiveModel 而是来自 ActiveSupport::Callbacks。之前好像有一个帖子专门讨论callback的。

    我把整个定义这个 validate 过程写下来,以Rails 5代码为例,你就能看到在哪里执行 if 了。

    首先是 validates的定义 code

    注意这段代码,validates_with(validator, defaults.merge(_parse_validates_options(options)))

    validates_with的定义在这里 code

    然后有看到了,validate(validator, options)

    validate 的定义在这里 code

    首先看到这里,好激动,看到了if

    if options.key?(:on)
      options = options.dup
      options[:if] = Array(options[:if])
      options[:if].unshift ->(o) {
        !(Array(options[:on]) & Array(o.validation_context)).empty?
      }
    end
    

    同时下面还有一段 set_callback(:validate, *args, &block) 我们的if还在 args 里面

    到这里大概明白,实际上 validate 就是一个 callback

    那么set_callback是什么鬼?

    网上找会看到这段代码

    included do
        extend ActiveModel::Naming
        extend ActiveModel::Callbacks #这个!!这个!!
        extend ActiveModel::Translation
    
    

    然后找到了ActiveModel::Callback定义的地方。code,但是,实际上这里并没有做什么。

    然后又看到了,

    def self.extended(base) #:nodoc:
      base.class_eval do
        include ActiveSupport::Callbacks
      end
    end
    

    终于到了ActiveSupport::Callbacks ,我们找到的是set_callback的定义

    定义在这里code

    其中有这段代码

    mapped = filters.map do |filter|
        Callback.build(self_chain, filter, type, options)
    end
    

    然后要找的就是Callback的定义了

    Callback code

    又一次兴奋的看到了if

    def initialize(name, filter, kind, options, chain_config)
      @chain_config  = chain_config
        @name    = name
      @kind    = kind
    @filter  = filter
        @key     = compute_identifier filter
      @if      = Array(options[:if]) # 这个!!这个!!
      @unless  = Array(options[:unless])
    end
    

    接下来的问题,其实就比较轻松了,这和Callback被执行时的,@if 是如何处理的。

    在当前的页面,还能看到这段代码

    def conditions_lambdas
        @if.map { |c| CallTemplate.build(c, self).make_lambda } +
          @unless.map { |c| CallTemplate.build(c, self).inverted_lambda }
    end
    

    这里,整个 @if Array 转化成了一个由 CallTemplate.build(c, self).make_lambda 组成的Array,里面是什么呢?是lambda

    接着就是要搞这个 conditions_lambdas返回的 Array 去了哪里。

    我们还是在同一个文件里code

    def apply(callback_sequence)
      user_conditions = conditions_lambdas
      user_callback = CallTemplate.build(@filter, self)
    
      case kind
      when :before
        Filters::Before.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config, @filter)
      when :after
        Filters::After.build(callback_sequence, user_callback.make_lambda, user_conditions, chain_config)
      when :around
        callback_sequence.around(user_callback, user_conditions)
      end
    end
    

    这里其实有涉及到了,ActiveSupport::Callbacks的执行逻辑,就不再深入,直接跳到最终执行的地方,还是同一个文件code

    def skip?(arg)
      arg.halted || !@user_conditions.all? { |c| c.call(arg.target, arg.value) }
    end
    

    这里有[email protected]_conditions.all? { |c| c.call(arg.target, arg.value) } 因为这是一个 Array

    查看 Enumerable .all?的定义。code

    all? [{ |obj| block } ] → true or false
    Passes each element of the collection to the given block. The method returns true if the block never returns false or nil. If the block is not given, Ruby adds an implicit block of { |obj| obj } which will cause all? to return true when none of the collection members are false or nil.
    

    所以,if options 实际上是在这里执行的。

  • #4 楼 @miserytan @first_dow@last_dow 是为了存放你的结果,避免重复计算。 when 1 怎么不理解? 这个算法其实你可以自己去实现的。

  • 补充一下,为什么要用上面的算法,是为了过滤你在 Settings.start_of_week中设置 1-7 以外的数字。你也可以用别的算法。

  • 关于 Ruby 的线上视频培训 at 2016年10月10日

    支持

    1. 代码格式有点问题,多复制了一个 end 你理解的是对的 first_wday 返回的是一周的第一天是哪一天 last_wday 返回的是一周的最后一天是哪一天

    2. 为什么开始都是星期日? 因为这段代码 Setting.start_of_week.to_i 返回的是 7, 也就是默认设置的就是星期日是第一天, 如果你希望是星期一是第一天,那么 Settings.start_of_week 应该改成 1

  • select_tagf.select 是不同的。 你看一下这两个函数参数的区别。

    1. select_tag
    2. f.select

    你这里其实有两个问题,

    1. form 中的内容 province/city/area 没有提交并被保存,所以 show 中看不到。
    2. china_city 在使用f.select时不工作但是能够提交。

    我给几个提示

    1. 你看一下 f.selectselect_tag生成的 HTML 代码有什么不同,它们具体是怎么用的。
    2. 再看一下 china_city 中 demo 中的 html 是什么样子的。
    3. province 被保存和没有被保存的两种情况下,HTML 代码有什么区别?
  • #4 楼 @xiaobai2 是你的判断逻辑有问题。 你想要在一个小时内只能插入 1 条,但是你判断的是 count > 1 ,当你插入第二条时,此时 count 是 1 啊,并不满足你的条件。你应该判断 count == 1

  • #7 楼 @Mineor 你是怎么发起请求的?

  • #2 楼 @zix 如 4 楼所说,你没明白你要做的是什么,你先你问的问题有点像是,1 + 1 = 2 了,但是你希望这个结果是 3,能不能想办法让 1 + 1 = 3,哪怕可以。但是你改变了基础的东西。😀 我的建议是,你回头想想你要实现什么?然后再想想,用什么来实现, 一定要页面跳转吗?不同用一个 Post 请求来实现?

  • 刷新页面不就是重新请求吗?!当然会执行 action 啊。

  • 哈哈哈,两斤花椒吃了 3 年😏

  • #5 楼 @xiaobai2 都可能是。

  • 你用错了find_by 看链接

  • #4 楼 @lehug 贴一下具体的代码吧 在用一下他贴的@u1440247613 网站,http://js2.coffee/ 看翻译出来的 JavaScript 是不是正确的。

  • 首先,(this)不是普通 JS 的用法,是带 jQuery 库的 JS。 所以如果你引入了 jQuery 库,在 CoffeeScript 中依然可以这么用$(this),没有问题,如果不行就要查一下其他原因了。 如果是纯 JavaScript,参见Element.getAttribute(attrName)