考虑到在一个容器版本里, public
内容不会变的情况下,比较 tricky 的实现思路我想到两种:
在启动容器的时候调用 docker cp
指令将 public
复制到宿主机中。
docker-compose.yml
使用 volumes:
,利用 docker 创建空的 named volume
时会自动复制对应 path 文件到宿主机 volume 的特性,通过 /var/lib/docker/volumes/{volume名称}/_data
访问 volume 数据。但是这要求更新镜像版本时删除这个 volume。
总的来说,比如 docker-compose
就没有原生对 pre script
的支持,坑多不好用就是了。
从 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
邮箱域名是 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
设置了 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
用 foreman:export
会在服务器生成各个 foreman 任务相关的 systemd 配置。
我的理解是,Rails 项目需要管理的进程除了 puma, sidekiq,可能还会有一系列用户编写的常驻进程,以 Procfile 的方式提供启动指令(比如监听 MQTT/RabbitMQ 的 worker)
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::DatabaseError
, SQLite3::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 个财务培训的。