Rails 6.1 升级
一、 步骤
1. rm Gemfile.lock
2. bundle update
3. rails app:update
二、 说明
1. dockerfile
第一步构建,需要下载安装 oracle, 后续在第一步镜像上构建
dockerfile 如下:
FROM ruby:2.7.2
ENV RAILS_ROOT /var/www/research
ENV port 3000
ENV RAILS_ENV production
ENV LD_LIBRARY_PATH=/opt/oracle/instantclient_11_2
EXPOSE $port:$port/tcp
WORKDIR $RAILS_ROOT
RUN cd / && rm -rf $RAILS_ROOT
COPY . .
RUN mv vendor/sources.list /etc/apt/sources.list && \
apt-get update && apt-get install -y libpq-dev libaio1 &&\
cd /opt && curl -O http://rccdevops.oss-cn-hangzhou.aliyuncs.com/oracle.zip && unzip oracle.zip && rm -rf oracle.zip &&\
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
curl -O http://rccdevops.oss-cn-hangzhou.aliyuncs.com/utils/rcc-confd &&\
chmod +x rcc-confd &&\
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
mkdir -p $RAILS_ROOT/tmp/pids/ &&\
mkdir -p $RAILS_ROOT/tmp/sockets/ &&\
mkdir -p $RAILS_ROOT/log &&\
bundle
CMD ./rcc-confd
2. deployment.yml
Could not find rake
-
gems 安装到 /usr/local/bundle/gems 下
-
pod 里取的是 /usr/local/bundle/ruby/2.7.2/gems 下的 gems
-
删除 BUNDLE_PATH
-
添加 GEM_PATH /usr/local/bundle
这是 ruby 版本升级和 bundle 的原因
参考: https://github.com/docker-library/ruby/pull/306
deployment.yml 配置文件如下:
apiVersion: apps/v1beta2
kind: Deployment
metadata:
labels:
app: research
name: research
spec:
progressDeadlineSeconds: 600
replicas: POD_REPLICAS
revisionHistoryLimit: 10
selector:
matchLabels:
app: research
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: research
spec:
containers:
- env:
- name: LANG
value: C.UTF-8
- name: RUBY_MAJOR
value: '2.7'
- name: RUBY_DOWNLOAD_SHA256
value: 9bf6370aaa82c284f193264cc7ca56f202171c32367deceb3599a4f354175d7d
- name: GEM_HOME
value: /usr/local/bundle
- name: GEM_PATH
value: /usr/local/bundle
- name: BUNDLE_SILENCE_ROOT_WARNING
value: '1'
- name: BUNDLE_APP_CONFIG
value: /usr/local/bundle
- name: RAILS_ROOT
value: /var/www/research
- name: LD_LIBRARY_PATH
value: /opt/oracle/instantclient_11_2
- name: port
value: '3000'
- name: RAILS_ENV
value: production
- name: CONFD_ENV
valueFrom:
configMapKeyRef:
key: CONFD_ENV
name: resource
- name: CONFD_RUN
value: puma -C config/puma.rb
- name: aliyun_logs_research
value: /var/www/research/log/*.log
securityContext:
privileged: true
image: 'registry-vpc.cn-hangzhou.aliyuncs.com/rcc_image/research:IMAGE_TAG'
imagePullPolicy: Always
name: research
resources:
limits: #最高运行限制
cpu: 500m #容器启动后最多可用CPU核数。
memory: 3000Mi #容器启动最多可用内存数 单位MiB、GiB
requests: #最低启动限制设置
cpu: 100m #最低容器启动可用CPU核数。
memory: 2244Mi #最低容器启动可用内存数 单位MiB、GiB
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/www/research/public/download
name: volume-pangu-download
- mountPath: /var/www/research/public/files
name: volume-reach-files
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: dev
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
nodeSelector:
group: oms
volumes:
- name: volume-pangu-download
persistentVolumeClaim:
claimName: pangu-download
- name: volume-reach-files
persistentVolumeClaim:
claimName: reach-files
3. undefined Rack::Protection
6.1.0
Web UI - Dark Mode fixes [#4543, natematykiewicz]
Ensure Rack::ContentLength is loaded as middleware for correct Web UI responses [#4541]
Avoid exception dumping SSL store in Redis connection logging [#4532]
Better error messages in Sidekiq::Client [#4549]
**Remove rack-protection, reimplement CSRF protection [#4588]**
Require redis-rb 4.2 [#4591]
Update to jquery 1.12.4 [#4593]
Refactor internal fetch logic and API [#4602]
注释如下配置:
# Sidekiq::Web.class_eval do
# use Rack::Protection, origin_whitelist: ['http://research.rccchina.com', 'https://research.rccchina.com'] # resolve Rack Protection HttpOrigin
# end if Rails.env.production?
4. ActiveRecord::UnknownAttributeReference
ActiveRecord::UnknownAttributeReference (Query method called with non-attribute argument(s): "projects.urgent desc, projects.reject, project_messages.submit_at "):
order_sql = 'projects.urgent desc, projects.reject, project_messages.submit_at '
因为 order 后面的参数前后不能有空格, 也不能用函数,比如 NVL(projects.urgent, 0) desc
去除前后空格,函数使用,用 Arel.sql(‘NVL(projects.urgent, 0) desc’)
order(Arel.sql('NVL(projects.urgent, 0) desc'))
5. update_attributes
remark = ReachRemark.where(remark_type: obj_type, type_id: obj_id).last
remark ||= ReachRemark.new(remark_type: obj_type, type_id: obj_id)
if remark.update_attributes(remark: remarks)
remark.remark
else
errors.add(:remarks, :invalid, message: '保存失败')
end
NoMethodError (undefined method `update_attributes' for #<ReachRemark:0x00007fc79db87e70>
Did you mean? update_attribute):
Remove deprecated `ActiveRecord::Base#update_attributes` and `ActiveRecord::Base#update_attributes!`.
全部改为 update
6. Grape
undefined method translate_attribute for #<Grape::Exceptions::ValidationErrors:0xxxxx>
translate_attribute
已经删除, 只有 translate_attributes
7. ActiveModel
# FrozenError: can't modify frozen Hash: {}
errors.details.delete(attr.to_sym) # 这行报错
原因是:
errors.details.freeze # 不能被修改
源代码如下:
module ActiveModel
class Errors
class DeprecationHandlingDetailsHash < SimpleDelegator
def initialize(details)
details.default = []
details.freeze
super(details)
end
end
def details
hash = group_by_attribute.transform_values do |errors|
errors.map(&:details)
end
DeprecationHandlingDetailsHash.new(hash)
end
end
end
参考:https://github.com/rails/rails/blob/6-1-stable/activemodel/CHANGELOG.md
8. utf-8
ActiveRecord::StatementInvalid: Encoding::UndefinedConversionError: "\xE5" from ASCII-8BIT to UTF-8
导入文件,文件名字
"\xE5\xBC\x80\xE5\x8F\x91\xE5\x95\x86\xE5\xAE\xA2\xE6\x88\xB7\xE8\xB5\x84\xE6\xBA\x90\xE4\xB8\x8A\xE4\xBC\xA0_20210105115722.xlsx"
# 使用 force_encoding('utf-8') 方法
转为 “开发商客户资源上传_20210105115722.xlsx”
总结:
Rails 6.1 升级须知:
- update_attributes 和 update_attributes! 这个方法不能用了
Remove deprecated `ActiveRecord::Base#update_attributes` and `ActiveRecord::Base#update_attributes!`.
具体文档:https://github.com/rails/rails/blob/6-1-stable/activerecord/CHANGELOG.md
- Order SQL 前后不允许有空格, 也不允许直接写函数
- 比如:
a. Project.order('created_at desc ') # Error b. Project.order(' created_at desc') # Error c. Project.order('created_at desc') # success d. Project.order(Arel.sql(' created_at desc ')) # success e. Project.order('NVL(projects.urgent, 0) desc') # Error f. Project.order(Arel.sql('NVL(projects.urgent, 0) desc')) # success
推荐使用:Project.order(created_at: :desc, updated_at: :desc)
的形式
如果非要嵌入字符串,可以使用 Arel.sql()
包装一下,用 Arel.sql
, Rails
就认为你这个字符串是安全的,并不会做 Rails
安全检查, 必须格外小心使用
具体文档:https://github.com/rails/rails/blob/master/activerecord/lib/arel.rb
遗留问题:
- scope
- where.not
- can’t modify frozen attributes
- ActiveRecord::Base.has_many_inversing = true