• 性能估计没有差别。一旦执行了外部方法,内部方法就会被定义在类中,整个类均可见,不会因为外部方法执行完毕而 undef 内部方法。跟直接定义在类中没有差别,反而显得奇怪。你还不如内部用 lambda

  • []=是另一个方法,a[3]='x'是 a.[]=(3,'x') 的语法糖,而不是先调用[]后再用等号赋值。

  • 只要 a 和 b 是不同的对象,你这个需求就很难实现。想知道什么情况下需要实现这样的效果? Array#slice和Array#[]没区别,Array.instance_method(:[])==Array.instance_method(:slice) 返回 true。其实看文档就知道了

  • 同楼上。不过 codewar 上有个怪风气,就是偏爱简短的代码,而非清晰的代码。有时候要很熟悉 API 才能看懂靠前的解法,不过正好用来熟悉 API

  • 都是比较靠谱实际的问题,没有整算法之类高大上的东西。

    不过楼主发视频不给面试者名字、视频打个马赛克么

  • 搞调试还要在 production 下玩。。。如果你没有源码部署经验,会踩很多坑 预编译 RAILS_ENV=production bin/rails assets:precompile 之后再配置 nginx,具体配置内容谷歌

  • 你确定要运行的 production 环境而不是 development?我怀疑你是想整开发环境但误以 production 启动了

  • production 环境下应该是先把静态文件编译到 public 目录下,再用 web 服务器来伺服静态文件。具体看看你的 production.log

  • null at 2020年05月30日

    楼主可能想考察面试者的动手能力和自学能力。 个人经验是不难,我还在做测试工程师的时候就是这么搭的环境,不过当时还是踩了很多坑

  • 应该不能哦,watir 不是基于 http 的。你的原始需求是啥

  • break

  • 牛啤,必须围观👍

  • [] 这东西你可以理解为取数组元素,但在某些情况下又是调用方法 (或函数),这就是设计的不一致性

    看来你并不知道“多态”。。。

    我开始认为上面很多人的回复 (包括我的) 你其实并没有完全看懂。

  • 那么 def 定义的方法为什么不能被一个变量接受呢

    只要拿到这个方法的引用,自然将其赋值给变量。js 里 obj.foo 就能拿到函数引用,加个小括号,obj.foo() 就表示函数调用,而ruby 中小括号并无特殊语义,obj.foo 直接表示方法调用,method(:foo) 就是获取该方法的引用,通过 call 来调用,其它 [] 等写法只是 call 的别名。我觉得问题就在于小括号这里,一旦习惯无小括号的写法,写起来就十分的潇洒。如果赋予小括号语义,那就不能兼容当前几乎所有的 ruby 代码

    其实他们都是方法不是吗?

    严格的答案是:不是。有的是方法,有的只是函数。我猜你没有仔细想过我上个回复中贴的那段代码需求

    那么设计可以简化一下,简化之后其实就是函数式编程了,传递方法,闭包,甚至回调函数

    传递闭包一直都可以实现,只是未按照你想要的方式实现而已。还是那句话,你把 js 当标准,自然可以说 ruby 不标准。单单说“函数式编程”这样的概念并无太大的实际意义,重要的是解决实际问题。而且你一直在顶级作用域搞,没有考虑 OO,实在是把问题场景想得太简单了

  • 比如你说的 block 和 proc 其实都是可以写成 def 定义的方法

    我没有说过 block 和 proc 可以写成 def 定义的方法。。。proc 返回是个对象。

    你依然没有弄清 def、proc 的区别,甚至没有严格区分“函数 (function)”和“方法 (method)”的概念。 如果你认为 proc 和 def 是一类东西,尝试在不破坏封装的情况下用 proc 来重写下面的代码

    class Person
      def initialize(str); @name = str; end
    
      def introduce
        "My name is #{@name}"
      end
    end
    

    你现在认为 proc、lambda 之类的是过度设计,我个人觉得,一是因为你当前没有熟练掌握 ruby,缺少对 ruby 的“语感”;二是因为你先入为主,把 js 的相关实现当做标准,自然就衬托出了 ruby 的不标准

  • 楼主勇气可嘉。

    def,define_method,proc,lambda 这几个,def 是关键字,用于定义方法,隔离作用域; define_method 也用于定义方法,但他本身就是个方法,因此可以通过传参来动态定义方法,扁平化作用域; proc 是对象化的 block(block 更接近于匿名函数的概念),lambda 是特殊的 proc,在 return 和参数上与 proc 有区别。

    整个语言就是参数可以是函数,返回也可以是函数

    传个 block,返回 proc,不就是这个么。

    至于装饰器,可以用元编程自己封个方法去实现,aop 还有现成的 gem

    另外。你可能还不知道 ruby 有 method 对象和 unbound_method 对象这样的东西。。。

    你觉得这些东西太乱,其实是因为你新摄入太多 ruby 概念,又没有完全理解,写的 ruby 代码又太少。你现在最最重要的不是给官方提建议,而是多写代码

    祝楼主学习愉快

  • 关键字:作用域门

    想实现闭包请使用 Proc

    def method1()
      param = []
      method2 = proc { |x| param.push(x) }
      return method2
    end
    f = method1
    f.call(10)
    
  • 问题在于读取的长度限制,r.read(2048) 只会在读取够了 2048 个字符时 (或者遇到了 eof) 才会返回,如果你改成 r.read(1),就会立即输出了。实际上一般的需求都是逐行输出,不用 read 而用 gets

    r, w = IO.pipe
    
    if fork
      w.close
      until r.eof? do
        input = r.gets
        puts input
      end
      r.close
    
      Process.wait
    else
      r.close
      loop do
        str = gets
        break if str.chomp == 'exit'
        w << str
      end
      w.close
    end
    
  • 原因找到了,除了 rails 的 fresh_when 有处理条件请求的逻辑外,rack 的 condition_get.rb 也有相关逻辑

    Rails::Rack::Logger 先行打印日志,此时 status 为 200。

    在 rack 2.2 的版本,rack/lib/rack/conditional_get.rb 中的 fresh?方法逻辑是优先判断 if-none-match,只要 if-none-match 和 etag 匹配,就不再处理 If-Modified-Since,直接返回 true。当 fresh?为 true 时 call 方法会将 200 的 status 重写为 304。因此服务器日志中看到是 200,实际客户端收到是 304

    而在 rack 2.1 的版本,conditional_get.rb 中的 fresh?会判断 if-none-match 和 if-modified-since,都满足条件才会返回 true。因此在较老版本的 rails(rack 低于 2.2) 中不会遇到帖子中描述的问题。

    #rack/conditional_get.rb
        def call(env)
          case env[REQUEST_METHOD]
          when "GET", "HEAD"
            status, headers, body = @app.call(env)
            headers = Utils::HeaderHash.new(headers)
            if status == 200 && fresh?(env, headers)
              status = 304
              headers.delete(CONTENT_TYPE)
              headers.delete(CONTENT_LENGTH)
              original_body = body
              body = Rack::BodyProxy.new([]) do
                original_body.close if original_body.respond_to?(:close)
              end
            end
            [status, headers, body]
          else
            @app.call(env)
          end
        end
    
    #rack 2.1
        def fresh?(env, headers)
          modified_since = env['HTTP_IF_MODIFIED_SINCE']
          none_match     = env['HTTP_IF_NONE_MATCH']
    
          return false unless modified_since || none_match
    
          success = true
          success &&= modified_since?(to_rfc2822(modified_since), headers) if modified_since
          success &&= etag_matches?(none_match, headers) if none_match
          success
        end
    
    #rack 2.2
        def fresh?(env, headers)
          # If-None-Match has priority over If-Modified-Since per RFC 7232
          if none_match = env['HTTP_IF_NONE_MATCH']
            etag_matches?(none_match, headers)
          elsif (modified_since = env['HTTP_IF_MODIFIED_SINCE']) && (modified_since = to_rfc2822(modified_since))
            modified_since?(modified_since, headers)
          end
        end
    
  • 谢谢大佬的认真回复。nginx 一直是关闭的。

    etag 的变化其实不在这个问题讨论的范畴了。etag 一旦不一致,服务端确实会返回 200,客户端也会收到 200。

    Rack::ConditionalGet 会比较 etag 和 last_modifed. 如果 etag 和请求的 If-None-Match 匹配的话,它会自动帮你改为 304

    之前看过这一段源码

    def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, template: nil)
      weak_etag ||= etag || object unless strong_etag
      last_modified ||= object.try(:updated_at) || object.try(:maximum, :updated_at)
    
      if strong_etag
        response.strong_etag = combine_etags strong_etag,
          last_modified: last_modified, public: public, template: template
      elsif weak_etag || template
        response.weak_etag = combine_etags weak_etag,
          last_modified: last_modified, public: public, template: template
      end
    
      response.last_modified = last_modified if last_modified
      response.cache_control[:public] = true if public
    
      head :not_modified if request.fresh?(response)
    end
    
        def fresh?(response)
          last_modified = if_modified_since
          etag          = if_none_match
    
          return false unless last_modified || etag
    
          success = true
          success &&= not_modified?(response.last_modified) if last_modified
          success &&= etag_matches?(response.etag) if etag
          success
        end
    

    fresh_when 的最后一行的逻辑就是返回 304 的响应,但需要同时满足 etag 和 If-Modified-Since 这两项条件才行。当我的 if-modified-since 使用的是较老的时间时,当然不会 head :not_modified。日志中看到 render 200,但客户端显示了 304。

    我之前怀疑客户端收到的是 200,但由于某种逻辑 (比如返回的 etag 没有改变) 显示为 304,于是用 charles 抓包,但抓包结果就显示 304。

    我刚才又用 rails6.0.2.2 新建了一个纯净的项目,依然遇到了这个问题。但在一个不纯净的 rails6.0.2 版本上就没有遇到此问题

  • 兄弟你还是没明白我的问题。论坛里相关的帖子我都看过了

    当请求的资源没更新时,在 stale? @subjects时就会返回 304,客户端收到的也是 304,这是正常的,使用了客户端缓存。

    但资源更新后,用同样的请求,会执行render plain: 'stale', status: 200,从日志看,服务器返回的是 200。到这一步为止也是正常的。问题时客户端收到的不是 200,而是 304。

    而将 render 中的 status 改成 201、202、203 之类的,同样的请求,客户端就能正常显示 201、202、203,而非 304

  • 感叹一哈撒。8 年人生大起大落,回头一看,才二十六七岁。人生经验赶超我辈啊

  • 我知道 304 是使用客户端缓存,关键是我的服务器的 response status 是 200,为什么到了客户端就成了 304

  • 刺激!8 年过去了也比我年轻

  • 俺们不相信,哪的培训起步 12k

  • 专业!👍 👍 👍 明白了,2.7 中,单例类的类变量的查询不在 receivers' ancestors 上了,而以前版本的查询又有 bug。

  • 确实😅 。2.7 里修正了这个行为,只能通过A.singleton_class.singleton_class.class_variables来获取了

  • 居然行了,但是想不通原因

  • 😂 ,我想错模型了

  • 一楼的想法和我一样。应该把中间表作为查询的主表。

    我注意到另一个问题,最开始@topics = @user.topics,这里查出的所有的 topic 是@user的了,那么视图中 topic.topic_users 查出来的结果自然也应该是@user的,为什么还需要 with_user(@user.id) 来再次限定。我在想去掉这个 with_user 后,配合原来的 includes 会不会还有 N+1