,的确很坑,得定义 permissions= 的行为才行
哦,这个用法没试过,回头试试。我想当然以为 serialize 要求数据库类型必须为 string 了
不过搜了下 5.0 的 doc,貌似不推荐这种情况用 serialize 了
http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html
If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object, then specify the name of that attribute using this method and it will be handled automatically. The serialization is done through YAML. If class_name is specified, the serialized object must be of that class on assignment and retrieval. Otherwise SerializationTypeMismatch will be raised.
Empty objects as {}, in the case of Hash, or [], in the case of Array, will always be persisted as null.
Keep in mind that database adapters handle certain serialization tasks for you. For instance: json and jsonb types in PostgreSQL will be converted between JSON object/array syntax and Ruby Hash or Array objects transparently. There is no need to use serialize in this case.
For more complex cases, such as conversion to or from your application domain objects, consider using the ActiveRecord::Attributes API.
这个功能只要 orm 层可以反射为 hash 就可以实现了,使用 hstore 或者 serialize 在这个场景并没有啥区别,但是我的意思是 hstore 的好处是,它是 pg 原生支持的类型,可以做
SELECT
sum (attrs -> 'like_count') As total_likes
FROM
posts;
GROUP BY xxx
这种级别的操作,所以如果数据库层面原生支持 json,最好直接用原生类型,而不是 serialize。
是不冲突,效率低功能少呀
postgre 原生的数据类型支持索引,支持数据库级别的操作,能用原生就用原生的 active record 的方案是在数据库不支持的前提下没办法的方案。
比如下面 payment 里面这段代码
def self.create_from_orders! user, *orders
orders.flatten!
payment = nil
transaction do
payment = user.payments.create!(
total_money: orders.sum(&:total_money)
)
orders.each do |order|
if order.is_paid?
raise "order #{order.order_no} has already paid"
end
order.payment = payment
order.save!
end
end
既没有看到使用悲观锁,订单上也没有创建乐观锁,方法内也并没有分布式锁做排他调用保证
create_table "orders", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.integer "user_id"
t.integer "product_id"
t.integer "address_id"
t.string "order_no"
t.integer "amount"
t.decimal "total_money", precision: 10, scale: 2
t.datetime "payment_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "payment_id"
t.string "status", default: "initial"
t.index ["order_no"], name: "index_orders_on_order_no", unique: true, using: :btree
t.index ["payment_id"], name: "index_orders_on_payment_id", using: :btree
t.index ["user_id"], name: "index_orders_on_user_id", using: :btree
end
也没有考虑地址可能修改的问题
貌似代码没有考虑 concurrency 问题
任务管理简单点可以用 sidekiq,worker 放在 docker 里面,集群部署不是啥问题~
简单点可以以行做为最小单位来保存,记录行的初始状态和最后编辑结果
多个行操作对应一次操作动作(实现复制粘贴多行的 redo 需求),前进和后退的操作就转换成为了每个操作动作对应行历史的批量操作
如果所有结果只能存在内存里,需要借限制保存的行数或操作动作数来限制总内存使用。
docker 一般建议 nginx+passenger/puma/... + 服务打包在一个 container 里面,作为一个随时可以工作的整体来发布。
我们目前的做法是:bundle 依赖包的 path 放在项目目录下,打包的过程可以放在 jenkins 上,jenkins 环境配成和 docker 内部一样,通过 jenkins 做 bundle,然后把项目文件 + 依赖直接 copy 入 container 打包。
日志文件需要通过日志归集服务统一做收集。
总的来说是有一定成本的,应用需要考虑成本和收益是否合算,我们因为微服务拆分的比较多,也有动态扩容的需求,所以在往这个方向走。如果只是做单一网站这种需求,并不建议这么做。
dy1901
有意思~
关键就在于显示器的高低,一定要平视
改成 int 吧,用 rails 早晚是个坑
#13 楼 @yukihiro_matz 你这头像和用户名太高大上了~
#13 楼 @yukihiro_matz 是,用 docker gem 以外的依赖会简单一点,比如如果你需要 es 或者 redis 服务来支撑的话
上 docker 吧
es 不是关系型数据库,如果想用 tag 搜其他的模型,可以在建立 mapping 的时候把 tag 放到其他的 index 里面,然后 tag 标签就可以作为搜索条件了,搜英文的时候需要设置相应的分词规则,因为 es 全文搜索是基于倒排表的,建议楼主先简单看看 es 全文的原理
Splunk, ELK
#30 楼 @xieyu33333 正常用户访问用前端渲染,搜索引擎可以根据 user agent 用 v8 做 server 端渲染,直接输出 html 给搜索引擎。
#2 楼 @jimrokliu 可以用来做服务间异步调用,丢出去不用管那种,不知道楼主是不是也用来做这个
基本都写,不写心里空空的~
写两套 api 就好:一套开放的不用鉴权,一套封闭的加 before filter 鉴权,只需要在 router 里面分别 mount 两个 api 的根文件,两套 api 就可以并行工作了。而且鉴权代码和不鉴权代码分开两个文件夹,代码安全性上也比较便于管理
自荐~ 上次分享过微服务和我们的跨服务分享组件 zombie model 与 Dynamic Router 以后,随着业务的推进,这两个组件又有了进步一的演进。想借着这个机会和大家深入交流交流。
#21 楼 @wppurking load balance 是不能从跟上解决阻塞问题滴~ 遇到这种情况框架和日志都有要有,两手都要硬~
另外对于 api 来说,非阻塞的模式要好于阻塞模式,可以避免一个慢请求导致其他正常请求排队,最后一堆请求全部超时。非阻塞既可以加强服务的健壮性,出问题的时候也比较容易找到问题点。这方面 rails 明显不给力啊~