• 考虑到在一个容器版本里, public 内容不会变的情况下,比较 tricky 的实现思路我想到两种:

    1. 在启动容器的时候调用 docker cp 指令将 public 复制到宿主机中。

    2. docker-compose.yml 使用 volumes: ,利用 docker 创建空的 named volume 时会自动复制对应 path 文件到宿主机 volume 的特性,通过 /var/lib/docker/volumes/{volume名称}/_data 访问 volume 数据。但是这要求更新镜像版本时删除这个 volume。

    总的来说,比如 docker-compose 就没有原生对 pre script 的支持,坑多不好用就是了。

  • Ruby 怎么就是网红了? at 2022年04月08日

    从 Ruby 里直接搬运东西的基本都失败了,因为没有理解到 Ruby 语言本质的不同,比如 Meta Programming,在主流竞争语言里没有一个实用的替代。

    有句话说得好,大多数从 Ruby 社区搬运过去的东西,都只是“摹其形”而不能“得其魂”,这是由 Ruby 语言的特点决定的。

    相反的是 Elixir 社区,从 Ruby 社区吸取优秀特性的同时,针对自身语法定位的特点,大胆地摒弃一些 Ruby 中的习惯用法,形成了具有自己独特价值的框架。

  • 我也觉得具体公司具体分析,一味地只看见一线 996 公司和 996 薪资太浮躁了。单纯攀比薪资是不利于公司形成对开发者友好的工作环境的。

  • type 字段是 STI 的核心,存放的是子类的名称,同时是保留字段名,不能用于 STI 之外的用途。通过子类 create 的对象会自动设置这个字段的值,不需要手工维护,通过父类 find 到的对象会跟据 type 的值实例化对应子类。Magic happens here~

  • 国内对 STI 的讨论确实非常少,题主对代码的语义化和简练的追求我十分看好。我在工作项目里对 STI 的使用还算比较多,对这方面有问题欢迎多探讨,发贴可以 @我

  • irb(main):003:0> Person.first.destroy
      Person Load (0.1ms)  SELECT "people".* FROM "people" ORDER BY "people"."id" ASC LIMIT ?  [["LIMIT", 1]]
      TRANSACTION (0.0ms)  begin transaction
      Teacher::HABTM_Courses Delete All (0.1ms)  DELETE FROM "courses_teachers" WHERE "courses_teachers"."teacher_id" = ?  [["teacher_id", 1]]
      Teacher Destroy (0.0ms)  DELETE FROM "people" WHERE "people"."id" = ?  [["id", 1]]
      TRANSACTION (1.5ms)  commit transaction
    

    Teacher::HABTM_Courses Delete 这一行,我这里测试下来,是没问题的,题主检查一下单表继承有没有配置正确。

    验证方式:

    irb(main):001:0> Person.first
       (0.3ms)  SELECT sqlite_version(*)
      Person Load (0.1ms)  SELECT "people".* FROM "people" ORDER BY "people"."id" ASC LIMIT ?  [["LIMIT", 1]]
    =>
    #<Teacher:0x00007f70a00bbba8
     id: 1,
     name: "Miss Cao",
     type: "Teacher",
     created_at: Mon, 04 Apr 2022 02:16:33.331678000 UTC +00:00,
     updated_at: Mon, 04 Apr 2022 02:16:33.331678000 UTC +00:00>
    

    注意 #<Teacher:0x00007f70a00bbba8 ,用 Person.first 获取的对象,会自动变成对应子类的对象, 这是 STI 的精髓所在,是通过 type 字段里的魔法实现的。

    Person.rb

    class Person < ApplicationRecord
    end
    

    Teacher.rb

    class Teacher < Person
      has_and_belongs_to_many :courses, join_table: :courses_teachers
    end
    

    Course.rb

    class Course < ApplicationRecord
      has_and_belongs_to_many :teachers, join_table: :courses_teachers
    end
    

    create_people.rb

    class CreatePeople < ActiveRecord::Migration[7.0]
      def change
        create_table :people do |t|
          t.string :name
          t.string :type
    
          t.timestamps
        end
      end
    end
    

    create_course.rb

    class CreateCourses < ActiveRecord::Migration[7.0]
      def change
        create_table :courses do |t|
          t.string :name
    
          t.timestamps
        end
      end
    end
    

    create_courses_teachers.rb

    class CreateCoursesTeachers < ActiveRecord::Migration[7.0]
      def change
        create_join_table :courses, :teachers do |t|
          t.index %i[course_id teacher_id], unique: true
          t.index %i[teacher_id course_id]
        end
      end
    end
    
  • Atlantis: 可确定的执行计划 at 2022年03月31日

    邮箱域名是 workstraem.is

  • 试试 308 Permanent Redirect ?

  • 在尝试 Monorepo 是吗? 我只在用 Gitlab CI 的,看起来是这样的:

    /.gitlab-ci.yml

    include: 'react/.gitlab-ci.yml'
    

    /react/.gitlab-ci.yml

    .react:
      before_script:
        - cd react
    
    react-build:
      extends: .react
      stage: build
      only:
        - react-prod
        - react-stage
      cache: { policy: pull }
      environment: { name: $CI_COMMIT_REF_SLUG }
      artifacts:
        name: react-build-$CI_COMMIT_REF_SLUG
        paths: [react/build]
      script: [pnpm build]
    
  • 你看 def a 这个方法定义的主体,是不是 def c .. end 这一整块?

    把这一整块看作一个表达式,那么 def c 这个表达式返回什么呢?

    答案就是 符号c 表示为 :c

  • Dalmore

  • 返回 union 类型能解决你的需求吗?我对 c 语言不熟,抛砖引玉一下,在别的支持类型的语言里,是可以声明某个値属于几个类型中的一个的。比如

  • 简单来说,充血模型表示实体对象负责实现与自己相关的功能,相对应地,贫血模型表示实体对象只负责数据模型,相关功能一般由相应的 Manager 类实现。

    《松本行弘的程序世界》里详细区分过这两个概念。

    举例来说,你有一个 Human 类,在类里实现了 walk 方法,通过 person.walk() 这种形式调用,可以理解为充血模型,因为这个 Human 类是活的,不需要借助其它方式辅助就能走路。

    对应的贫血模型可以实现一个 WalkManager 类,以 WalkManager.walk(person) 这种形式调用,这里 Human 本身不能走路,需要 WalkManager 扶着它走,就好像一个失血的人一样。

  • 听君一席话,胜似一席话。

  • 处理并发的技术确实很多编程语言都能做到,但 Erlang 借助 OTP Supervisor 的 let it crash 这种神奇的错误处理理念还没见有其它语言能学到。

  • 要不要考虑一下 iptables 方案?敏感话题就不公开讨论了,对这项技术感兴趣可以 PM 我。最近发现这个方案理解了的话,处理服务器访问互联网的问题超级容易。

  • --build-arg 读环境变量?看下来你的 Gitlab CI 是能读环境变量的。

  • 车票买好了 😋

  • 阿里云/AWS 配置 GitLab Runner,利用 Role 获取 OSS/S3 文件并用 KMS 解密?

  • 不是可以直接用 RAILS_MASTER_KEY 这个环境变量吗? custom-credentials

  • 使用 OpenWrt 默认的 DHCP 的话,可以直接使用设备 主机名.lan

  • null at 2021年11月25日

    设置了 MALLOC_ARENA_MAX=2 ,使用 3.1.0-preview1 的时候我的 Rails 项目有一个常驻进程会持续内存泄漏,降级到 3.0.3 后这个现象就消失了。

    另外之前用 3.1.0-preview1 的时候我需要禁用 newrelic_rpm

    当时我需要添加 4 个 gem:

    gem 'digest', '~> 3.1.0.pre2', require: false
    gem 'net-imap', '~> 0.2.2', require: false
    gem 'net-pop', '~> 0.1.1', require: false
    gem 'net-smtp', '~> 0.3.0', require: false
    
  • mac 上 emacs 入门 at 2021年11月23日
  • foreman:export 会在服务器生成各个 foreman 任务相关的 systemd 配置。

    我的理解是,Rails 项目需要管理的进程除了 puma, sidekiq,可能还会有一系列用户编写的常驻进程,以 Procfile 的方式提供启动指令(比如监听 MQTT/RabbitMQ 的 worker)

  • capistrano-foreman

    cap production foreman:export
    

    Capfile

    require 'capistrano/foreman'
    

    lib/capistrano/tasks/foreman.rake

    after 'deploy:finished' do
      invoke 'foreman:export'
      invoke 'foreman:restart'
    end
    

    拿走不谢 😏

  • 这段代码抛的异常是 Sequel::DatabaseErrorSQLite3::SQLException 不是 Sequel::DatabaseError 的父类,自然捕获不到。

  • rescue StandardError => e
      puts e.class # Sequel::DatabaseError
    end
    
    e.inspect # #<Sequel::DatabaseError: SQLite3::SQLException: table posts has no column named mail>
    
  • Fork 改 Gemfile 用 github:

  • 一共要选出 4 个人,可以先从 8 个人里把 2 个培训计算机的选出来,然后从剩下 6 个人里选出 1 个英语培训的,最后 5 个人里选出 1 个财务培训的。

  • 学前端直接入 Next.js 啊,结合国内情况,考虑到小程序之类的支持,Rails 只提供 API 也还好啦。完美的前后端同构方案我目前是还没了解到。