• 我的同事也问过我为啥一定要用 form_for。我说我们是用 Rails 的,不是写 php 的,既然用了,就试着写出 rails stype 的东西吧。

  • 提供便利

    ActionView::Helpers 里面这么写的

    Form helpers are designed to make working with resources much easier compared to using vanilla HTML.

    rails 在做数据库的操作的时候,有很多约定。比如 User.find(1).update(name: "bar") 就直接做了更新。那生成的代码,就要符合这样的约定。

    多数时候,更新和创建我们会使用类似的 form,只是 url 和 request method 不同。我们可以判断,要更新的对象是不是 new_record? 来生成对应的代码。

    这个时候,你会发现手写,就要处理一些逻辑上的问题,那么引入 helper 就是一个不错的选择。

    其实这个时候,还不算有趣。如果 user 有很多 (has_many) books 呢?如果想要在一个表单做 books 的操作呢?

    可以这么搞,Book.new.book_attributes = [:name => "Ruby"] (之前要声明 accepts_nested_attributes_for :book) 。

    这个时候,如果我们想用这个约定,就要构建对应的 form,要根据 nested 的关系构建对对应的 input 的字段。books 还是有序的。等等一系列的操作,但 form_helper 都帮我们搞定了。

    减少重复

    到现在,其实已经没有不用 form helper 的理由了。但 rails 没有止步于此。rails 用继承的方式,避免了代码上的重复 -- FormBuilder 。 我们看下面的代码

    <%= form_for(@company) do |f| %>
      <%= f.text_field :name %>
      <%= f.submit %>
    <% end %>
    

    多数的 input 前是要放 label,有一天,我们不想在写这样重复的代码,怎么办? FormBuilder !

    可以这样搞

    class LabellingFormBuilder < ActionView::Helpers::FormBuilder
      (field_helpers - [:label, :check_box, :radio_button, :fields_for, :hidden_field, :file_field]).each do |selector|
        class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
              def #{selector}(method, options = {})  # def text_field(method, options = {})
                @template.send("label", @object_name, method) +
                 @template.send( #{selector.inspect}, @object_name, method, objectify_options(options))
              end
            RUBY_EVAL
      end
    end
    
    <%= form_for(@company, builder: LabellingFormBuilder) do |f| %>
      <%= f.text_field :name %>
      <%= f.submit %>
    <% end %>
    
    

    具体可以看看这篇文章 https://segmentfault.com/a/1190000004425543 (只有一,没有二、三。。。)

    还有更好玩的 - simple_form

    很多 ruby 程序员,说 simple_form 不好用。

    但 simple_form 是大大的简化了代码。怎么搞呢,直接 custom 一个 form_builder 来,然后,大家套用这个 builder 就可以了。

    custom 一个 form_builder 难不难呢?我们优秀的前端小伙 zack,第一次玩,就 custom 出来了一个。

    不用这些可以吗?

    先说,这是一个非常好的问题。

    除了这些便利无法享受到以外。项目中的每一个人,每一个 form,都要重头写 form!都要了解 rails 的细节,都要了解 HTML form 的细节(笔记 array 在 rails 里生成的参数是什么样的?)。

    代码变得不可 review -> 错误不好发现 -> 隐藏的 bug。

    在约定和继承的路上渐行渐远

    Rails 复杂,就是因为 Rails 提供了很多这样的便利。

    有的时候,难免会想,这些到底值不值得?

    accepts_nested_attributes_for 我第一次用,也是一脸懵逼。但我花了一天左右的时候,就搞差不多了,顺带还知道 Rails 的很多细节,比如 create、update 几个方法的关系。影响了我后今后的编码生涯(虽然听着很夸张,但却是如此)。以后 form 可以用的很爽。

    搞了这么多,做起来难不难?不难,就像 simple_from,我们前端的小哥,半天就定制好了!Rails 难的时候,可能是你用它的姿势不对。

    为啥要用框架?

    框架,不但能提供了好用的方法,能解决常见的问题。

    还封装了细节,让我们不那么懂的时候,可以写出东西来。

    提供了解决问题的姿势,大家可以用一样分流程解决类似的问题。

    用 Rails,不能写完业务就万事大吉,还要读文档,了解 Rails 的机制。

  • 招募项目合伙人 at July 20, 2017

    八成是,现在不给钱,要钱?以后给。。。

  • 没人会否认 Lisp/Clojure 的价值。语言有自己的特点,也有自己的适用范围。

    有很多人从 Ruby 转向 clojure,也有很多人在用 ruby 做函数式的尝试。

    Ruby / Rails 本身都在函数式编程上学习了很多。比如 rails 的 ActiveRecord::Relation User.wher(xx: xx).find(xx) 。每一个方法都返回一个 ActiveRecord::Relation 的实例,而且是 lazy evaluation 的。

    Clojure 也在做解决状态的尝试,比如 https://github.com/stuartsierra/component

    面向对象,会带来复杂度,但也能解决问题,比如被很多 rails 程序员诟病的 https://github.com/josevalim/inherited_resources ,也可以极大程度上提高生产力。开发效率和能力成正比。这种东西所带来的好处就是,大多数情况下,隐藏了细节,团队开发就变成了有经验的 + 经验少的这种组合。而不是所有人都要有经验。

    有些问题,需要通过 提供抽象、提供解决方案来解决。 比如创建数据,需要用到 factory,需要实现的就是 factory_girl 的那些方法,无论是 ruby 还是 clojure。

  • 高手潜水呀

    ruby-china 也有人潜水。但国内有很多牛人都不潜水,有管理论坛的的,有回答新手问题的、有分享撕逼的。至少看起来,是团结、热闹的。

  • 同样的帖子,http://clojure-china.org/t/clojure-sdk/691 ruby-china 的热度更高啊!

  • 搜索搜到这个帖子,没啥事,就试着写了下,跑通那几个用例,一共用了不到 30 分钟。

    感觉挺好写的。这个算法我知道怎么回事。翻译成代码就 ok 了,ruby 又这么好写。二分法的递归也是属于比较容易的递归。写个骨架,然后再加最简单的测试用例(下面的前 4 个),之后对着用例开始微调,无外乎就是加减 1 的问题,试几次就 ok 了。再之后,就看看给的测试用例有没用问题。

    递归转遍历,只要理解递归的原理,把递归维护的状态,手动维护下,就 ok 了。反正测试用例有了,测试一直跑的,开始微调。

    倒是觉得测试用例挺重要的。要是让我直接用面试官给的用例,我估计就要懵逼了。

    递归是基本功。可以很好的锻炼抽象和分解问题的能力。递归学东西,一大片算法可以随便撸了。

    递归可以这么考,先递归实现,之后用尾递归实现,再之后用遍历实现。再问问为啥尾递归可以被优化之类的。哈哈哈哈,我承认我挺无聊的。。。

    代码如下,算法相关的,就没注意命名之类的问题。

    ## recursive version
    def binary_search_helper(arr, ele, start, end_)
      return false if start > end_
      middle = (start + end_) / 2
    
      middle_ele = arr[middle]
    
      if ele > middle_ele
        binary_search_helper(arr, ele, middle + 1, end_)
      elsif ele < middle_ele
        binary_search_helper(arr, ele, start, middle - 1)
      else
        middle
      end
    end
    
    def binary_search(arr, ele)
      end_ = arr.length
    
      binary_search_helper(arr, ele, 0, end_ - 1)
    end
    
    def expect(r, expected)
      unless r == expected
        puts expected
      else
        puts "Success"
      end
    end
    
    ## iterative version
    def binary_search_helper(arr, ele, left, right)
      return false if left > right
    
      while left <= right
        middle = (left + right) / 2
    
        middle_ele = arr[middle]
    
        if ele > middle_ele
          left, right = middle + 1, right
        elsif ele < middle_ele
          left, right = left, middle - 1
        else
          return middle
        end
      end
      false
    end
    
    def binary_search(arr, ele)
      length = arr.length
    
      binary_search_helper(arr, ele, 0, length - 1)
    end
    
    expect binary_search([0], 0), 0
    expect binary_search([0], 1), false
    expect binary_search([0], -1), false
    expect binary_search([], 0), false
    
    expect binary_search((1..15).to_a, 8), 7
    expect binary_search((1..15).to_a, 1), 0
    expect binary_search((1..15).to_a, 14), 13
    expect binary_search([2,3,8,15], 8), 2
    
  • 破解密文是为了达到某种目的。

    通过事实验证。 比如破解登陆密码,那么,拿这个密码登陆下就知道对不对了。再比如二战时候,破解的密文,就包含要攻打某某地的信息,只要真的攻打这个地方了,就能证明破解正确。

    明文实际上就是看起来的“乱码”怎么办 接着破解。本来就是乱码的话,只能说,人家在逗你玩。。。

    一个加密算法的安全性,是建立同时知道明文和密文的前提下,是否能得到秘钥。

  • 可以呼吁,可以倡导,但不要给别人下定义。让人反感。

  • view 里面调用了 edit 那个路由,我猜是没声明找回密码的路由,试试这个 https://stackoverflow.com/a/7403353/2477886

    如果还是不行,试试重启下 sidekiq。

  • [ 招聘] 多了一个空格, [招聘]

  • 暴露我年龄 😭

  • 办活动不容易 👍

  • CEO 人很靠谱 👍

  • 加油加油!望楼主坚持下去!

  • 我觉得深究这些东西,还有一个原因,就是好奇。就是想搞懂到底是怎么回事。

  • 量产型炮灰工程师 at May 22, 2017

    从认知过程上来说,人理解事物需要时间。一个技能,连着学 7 小时的效果远不及每天学 1 小时,学 7 天效果来的好。

    但效率是可以提高的。但对老师,学生、习题、教材要求都十分高。berkeley 有在教 SICP(简化版),学时是 4 个月。知识量非常惊人。

    我个人来说,一部分靠学习(课程、老师、同事),一部分靠积累。

    比如,定义变量、函数都能提高优先级,维护性更好。比如递归。比如分解问题。都是通过课程学习到的。

    有些是观察别人(同事多一些)是怎么处理的。有些是别人告诉我的,比如 CTO 跟我 carrierwave 把一个开发级别的任务,变成配置级别的任务。一下就明白了一个 gem 的意义。

    有些是自己坑自己,一边骂自己傻逼,一边默默填坑。

    学习和训练都很重要。

    比如我在学递归的时候,怎么都不会。是按照老师、教材(sicp)的思路,才开始理解递归。 之后写了几个月的 clojure(遍地递归),撸了门算法课(撸的第二门了。。。),每一次都有更进一步的理解。

    不同程序员有不同的要求

    我对 ROR 理解是,几个人,能力最强的那个,搭架子,别人搬砖。

    在比如 simple_form,有一个人懂就可以,剩下的人,有问题,就找那个人解决就好。

    新人开始的时候,能照葫芦画瓢就好。知道 rails 的概念,看完 guides,看完 ruby 元编程。之后了还要知道 rails 的实现思路。HTTP,数据库等知识。

    最后,学习这东西,要想学好,需要付出很大的努力,包括时间、别人的指点、正确的方法。

  • @sec 如果只是想学东西的话,可以不要那个证书,就是免费的。

  • 楼主的分析挺正确! 这门课程是伯克利本科高年级的课程,建议学过 cs61a 或者 cs61b 的人学,要求是,有较好的编程基础。 这门课程讲到了软件工程的方法面面,全面但深刻,关键点都讲到了,剩下的可以在实践中慢慢体会。

    顺便说一句,作为写过几年代码的人,我始终认为,写测试比写代码难。。。

  • 数据分析师与 R 语言 at April 27, 2017

    语法好啊,很适合那群搞数学的。 还有数据随随便便就能读进来。 当然还有轮子多。

  • poltergeist问题很邪乎,经常是有的机器上有问题,有的没有。

    我本地跑了下,似乎是用到了 CSS Animations,可以先试试直接禁用掉(很多都这么干),具体可以参考这个链接

    还可以点击事件换成find('#xxx').trigger('click'),这个是不管是否有遮挡,都能 click。

  • 我直接 revert 8f5df2358e7ee9c9a65d0412e0299e4f14659564 这个 commit,集成测试是可以跑过的。配置应该没问题。我猜可能是 phantomjs 版本的问题,我本地的是

    phantomjs --version
    2.1.1
    

    另外 selenium 和 poltergeist 方法有一些的不同,同时使用(我们一个用在本地调试,一个用于 CI),略蛋疼,有想解决办法,但一直也没时间去搞。

    同时建议使用screen_size: [1400, 1400],因为屏幕太小的话,会有因为点不到东西(元素不在显示器内)而报错的时候。

  • 只是对自己的看法罢了。不会把这种看法加到别人身上,能解决问题,就是好样的。我对我自己的希望就是基础功再扎实一点。记忆本来就是学习的一部分,遗忘也是。

    要求本来就是多样的。 很多时候要求不一样,比如 form 可以手写,可以用 form_for。有的时候我还会建议去了解 form_for 如何构建参数的,参数拿到了如何做赋值的。

    需求总是多种多样的,总有彼此合适的。

  • 我毕业的时候数学不会,算法不不会,数据库不会。但都慢慢补回来了。倒不是觉得这些在工作中能用到,而是觉得作为一个程序员,这些不会,说不过去。 再一个就是给自己一个可能。真的有一天要用到这些呢,比如实现个算法,比如玩玩机器学习?数学、算法这些都是没办法在短时间学会的。

  • ActiveRecord::Relation用到了很多函数式编程的思想。

    1. 有需要,才会真的去做查询、装载成对象,这样可以避免没意义的执行。 也就是是函数式中的 lazy。lazy 可以带来很多好处,比如模块化,不需要对中间值进行计算,无限长的数组

    2. 每一次方法的调用,都返回一个新的ActiveRecord::Relation对象,而不是做修改。 所谓的 pure function。另外用到了 chain 这个 pattern,jQuery 采用了同样的设计方法。

    想进一步了解的话,可以看下这篇文章 http://patshaughnessy.net/2014/9/17/20000-leagues-under-activerecord

  • @scriptfans 哈哈,改天分享下 elixir?

  • Python 没在项目里用过,不做评论。但觉得可以同 Julia 比较一下。

    机器学习,或者科学计算,和其它领域最大的不同就是,它和数学关系密切。有一句话是 show me your code。放在机器学习、算法里,反倒是 show me your formula 来得实在。

    因为是和数学打交道,语法越接近数学越好。

    比如 Julia 的方法定义

    foo(x) = x
    foo(x, y) = x + y
    l = (x, y, z) -> x + y + z
    

    再就是是否有为常见问题提供解决方案 比如矩阵运算

    julia> A = [[1, 1] [2, 3]]
    
    julia> A + A
     2  4
     2  6
    
    julia> A * A
     3   8
     4  11
    
    julia> transpose(A)
     1  1
     2  3
    

    还有是否能使用现有的 lib,Julia 可以很轻松的调用 C 和 Fortran,以及 python 还有 java 的代码。 t = ccall( (:clock, "libc"), Int32, ())

    Type 比 Class 更适合科学计算。

    Julia 的背后支持者也非常强大,一些大学已经开始使用 Julia 授课。

    最后是速度,Julia 足够,当一段代码,一跑就是一天的时候,语言速度优势就提现出来了。

  • 哈,pre condition, post condition,都是 clojure 的特性啊。

    有点对 ruby 失望的意味,ruby 3 没有明确的目标,ruby 2 没有什么令人激动的新特性。还顺带强烈吐槽了写法太多,只要一种就好。

    感触最深的是

    The feature has already here it just not evenly distributed. Ruby has fallen behind and we are not the community that was known for leading the innovation anymore.

    clojure 或者 lisp 确实是值得学习的语言。

    顺便贴下视频连接

  • numpy 速度快,语法友善。

    如果一个程序动不动就要跑一天,就需要考虑语言的快慢了。