• Rails 6 之前的 loader 在一些设置不对的情况下会有些坑,主要是报错信息跟实际问题不相符。所以才有了新的 zeitwerk loader。zeitwerk 对文件名/常量名约束的更严格,报错信息也更明确。

    不方便用 Zeitwerk loader 的话先检查一下项目 autoload path 设置的有没有问题,再从错误堆栈找线索。sping stop 也能暂时缓解一下。

  • 用的比较多的规范是 (应该也是 rubocop 默认的) 如果只有一个条件unless condition优于if !condition,两个以上条件用if,比如if condition1 || condition2

  • Rails 性能优化 - 优化之前 at 2022年03月02日

    关于性能优化可以看一下 https://nateberk.gumroad.com/l/apocrypha。 优化的核心思路是

    1. Observation (Noticing behavior in production or development)
    2. Hypothesis (Profiling to figure out what's causing the behavior)
    3. Test (Benchmarking)
    4. Analyze (Observing new production behavior)

    书上的内容虽然作者的博客上大部分都有,不过现在才 10 美元,书也是这两年刚发得,内容没有过时,看看也能有不少收获。

  • Rails 性能优化 - 优化之前 at 2022年03月02日

    postgresql 可以用pgherostrong_migrations

  • Rails core team 都是用 MySQL,Postgres PR 基本没人理 😂 https://github.com/rails/rails/pull/41288

  • rails 是可以在不胖,胖,超胖之间取舍,别的只能选择不胖。

  • 就是充血模型跟贫血模型,Ruby 的表达能力强,比较适合容易实现充血模型。

  • 先说结论:Ruby 不适合做微服务。微服务也不一定适合你的项目。

    微服务主要解决的问题是“人”:项目越久,业务越复杂,团队扩张越快,一个巨型单体应用加新成员的边际效率就越低,微服务确实能解决这个问题。 有些人误以为微服务能解决性能问题跟 scalability 的问题,这些人主要是假设单体应用只有单关系型数据库。即,非单数据库的单体应用的性能,scalability,甚至可用性都高于或等于微服务。

    如果说微服务主要解决的问题是提高加人的边际效率,那么 Ruby 并没有比其他语言更好。像 go 语言就不挑人,有很多工具能保证程序员不会提交太愚蠢的代码,工程师可以做到“即插即用”;微服务后业务也足够简单,作为一个螺丝钉不需要很高级的抽象能力。Ruby 保证新人提交代码质量,只能通过 code review 跟 unit test(大家想想自己呆过的公司 code review 跟 unit test 做的好不好)。说到 Rails,本来就是为单体应用而生的,如果强用 Rails 做微服务,可能只会用到 Rails 中非常小的一部分功能,很多微服务特有的问题,比如文中提到的分布式事务,或者响应 rpc 请求都要自己开发或者找社区方案,这些都与 Rails 本身没关系。

    而且最重要的问题是你们公司有没有建设/维护一套微服务架构的能力,后端服务用什么语言/框架与这个能力相比都不值一提。

    总结一下是如果现在项目已经有成熟的微服务架构,Rails/Ruby 做微服务肯定没有问题,只是没有多大优势。如果靠把 Rails 应用做成微服务而反推微服务架构,有点本末倒置。

    其实解决“人”的问题不一定非要选择微服务。如果一个老的单体应用要继续前进、扩展,有另一条经济实惠的路:modular monolith。即可以现在单体应用本身分模块,建立边界,既可以减少新工程师理解业务知识的负担,也可以复用现有架构,shopify 就是这么做的https://shopify.engineering/deconstructing-monolith-designing-software-maximizes-developer-productivity

    当然微服务也有很多好处,比如你想混个架构师 title 方便过几年跑路,请务必推微服务 [狗头表情]

  • ruby 性能不拔尖,不过也够用了,99% 的 web 应用足以胜任。说差的要不就是那剩下的 1%,要不就是跟风的。

  • Ruby 值得一学 at 2021年04月28日

    例如我对 Phoenix 的 live view 有兴趣,不知道跟 Rails 最近出的 turbo_stream 有什么不同。

    turbo_stream 是服务端推 html 片段,页面直接替换相应的 html 片段,简单粗暴。

    live view 可以理解为 state 在服务端的 react。服务端 state 改变,通过 webocket 把 diff 发给页面,页面有一个小的 js 库根据 diff 改变 html。

    turbo_stream 是 sever agnostic 的,任何 web 后端框架都可以用,包括 Phoenix。

    live view 是基于 OTP 的,只有 Phoenix 可以用。

    turbo_stream 基本是 web 老一套包装包装,上手不难。

    live view 改变了 web 的开发方式,很多理念完全是新的,用起来别扭,我至今未上手。

    live view 是可以完全不写 js 的,turbo_stream 没有要革 js 命的意思,标配 stimulus 一起用。

  • 国外的企业同事之间不讨论政治宗教不是很正常的事情吗。越多元化的地方越什么都不能说,说什么都能得罪到部分人。

    我经历过的外企政治正确有

    1. 我自己头像是蒙面带墨镜的,被告知换一个,像恐怖分子。
    2. 同事头像是在靶场的,被告知换一个。
    3. 几个一起工作好几年的老外来中国出差的时候才知道彼此都是基督徒,因为只有中国人口无遮拦直接问人家信仰。
    4. 特朗特选举成功后问他看法,很郑重的拒绝回答(但是表情到位了)。
    5. 有同事在公司 IM 工具说某女同事漂亮被警告(这逻辑我还没太明白,貌似不能用直接评判别人长相?)
  • https://ruby-china.org/topics/40583

    但是,历史遗留问题依然需要解决。随着 Fiber Scheduler 在 Ruby 3 引用来提高 I/O 密集场景下单一线程利用率极低的问题;我们需要进一步解决,计算密集场景下,多线程的利用率。 为了解决这一问题,Ruby 3 引入了 Ractor 模型。

    先看你要解决的是什么问题,rails 项目可不是计算密集场景

    就算 ractor,fiber 成熟了,对 rails 使用者也应该是无感知的,业务代码都会跑在单个 ractor/fiber 里,是框架跟 webserver 决定的,就像现在 puma rails 都用多线程编程,但是作为 rails 使用者几乎不需要写多线程代码,如果对多线程理解不好,多线程代码反而会拖慢项目速度,比如你多线程查数据库,别的请求就拿不到数据库连接。

  • 您说的没错,Ruby 是众多编程语言“爬楼梯”吊车尾的,这点毋庸置疑。如果需要处理“爬楼梯”场景,java 也可以略过,直接上 c c++ rust。

    绝大部分应用处理的是“坐电梯”的事情,语言之间的差距是“走进电梯里的那一小步”,即使有差距也并不明显,主要看电梯调教的怎么样。

    Ruby 慢这种事没什么好争的,但是“应用慢是因为 Ruby”这样的结论大部分情况是不客观的。

  • 所以面试考算法是有道理的,这个方法慢主要是因为写的有问题。

    def fib(n, cache = {0 => 0, 1 => 1})
      return n if cache[n]
      cache[n - 1] ||= fib(n - 1, cache)
      cache[n - 2] ||= fib(n - 2, cache)
      cache[n - 1] + cache[n - 2]
    end
    

    java 可能对烂代码有优化,如果很需要这种优化就选 java 吧。

  • 对运维来讲 nosql 肯定方便一点;对开发来说还是 sql 数据库写业务简单,完全不需要提前设计 key 跟索引。

  • 测试性能优化建议 at 2021年01月21日

    规避网络请求

    可以用vcr

  • 请教一个线程安全的问题 at 2020年12月29日

    puts 是一个 IO 操作,可以看作是一个很短暂的 sleep,这样 2-1=1 的线程有很大几率等到 1-1=0 的线程,一起退出循环。多跑几次下面的代码也会有减到 -1 的情况。

  • 这个测试

    RSpec.describe do
      describe 'method' do
        let(:instance) { A.new }
    
        it 'test public method' do
          expect(instance.end_method).to eq('abcd')
        end
      end
    end
    

    class A
      def end_method
        return_a + return_b + return_c + return_d
      end
    
      private
    
      def return_a
        'a'
      end
    
      def return_b
        'b'
      end
    
      def return_c
        'c'
      end
    
      def return_d
        'd'
      end
    end
    

    代码覆盖率也是 100%,广义的覆盖率是指测试执行以后多少比率的被测代码被执行过。

    另外我更推荐用 Rails 内置的测试框架,一是因为 RSpec 语法太花哨,增加新手学习成本,学会了也没什么好处;二是 Rails 跟内置的测试框架配合更好,rspec-rails 现在还不支持并行跑测试,Rails 多数据库的测试 RSpec 也需要打 patch 才能跑。

    我支持提交的代码需要被测试覆盖,但是不一定要测试驱动,我更习惯先写代码再写测试,写代码的时候也能顺便理清思路。而且测试作用除了保证现有代码符合预期,也能增加日后重构/做改动的人的信心,对有年头的项目尤其重要。

  • Ruby 3 Fiber 变化前瞻 at 2020年11月17日

    mysql2 是一个 mysql c client 的 wrapper,io 操作在 c 那边,用不上 fiber。用 fiber 的是https://github.com/socketry/db-mariadb

  • 111 at 2020年11月13日

    生产力是杠杠,但我觉得 Rails 的性能还是要差些,当项目做大了以后,比如我们的一个 API,用 Rails 5.2 + Jbuilder。500 左右的 RPM,在缓存全中的情况下服务器响应时间还是要 400ms 左右,JSON 内容有 400kb 左右。

    我们 RPM 比 500 高非常非常多,响应时间 P50 不到 30ms,P95 150ms 左右,供参考。

  • Rails 一个 action 能根据 Accept Type 返回不同的形式,如 html, json, xml。Accept Type 可以通过 http header 指定,也可以通过 url 后缀指定。不指定的话默认的就是 html,即 https://ruby-china.org/topics/40441 等同于 https://ruby-china.org/topics/40441.htmlrails返回给你一个html页面。,告诉

  • 这是有人挖坑需要你来填的问题,就算你能找到捷径,也是坑上加坑,不是填坑。

    你想测一个本身很复杂的东西,你对它又不够了解,那是没法测的。

    真正解决方法也不是技术上的了:短期来说要让你老板知道这坑不是你挖的,要不就绕着走,要不就填。要填的话又需要多少工作量多少收益跟老板讲清楚。通过一些“技巧”坑上蹦迪是最害人的。长期来说是你们团队 code review、测试覆盖不规范,不纠正的话代码会走上超难维护的道路。

  • 你要是测 SaleReport,就往组成 view 的表里插数据。你的测试要依赖 SaleReport,就直接 mock。

  • 直接 mock SaleReport 查询的返回

  • 可以先加我们 hr 聊聊,微信 ch3_monkey

  • 威海路 696 号 WeWork

  • whenever 是用的系统的 crontab,到不了秒级,每次启动都要重新加载整个项目,又慢又没必要。