修改rails为4.1.5,及依赖的gem包 升级rails关联组建的版本号到4
-gem 'sass-rails', '3.2.6'
-gem 'coffee-rails', '3.2.2'
-gem 'uglifier', '2.1.2'
-gem 'cells', '3.8.8'
-gem 'rails', '3.2.15'
+gem 'rails', '4.1.5'
+gem 'sass-rails', '~> 4.0.3'
+gem 'coffee-rails', '~> 4.0.0'
+gem 'uglifier', '>= 1.3.0'
+gem 'cells', '3.9.1'
添加如下gem包,处理rails4新增特性,比如rails4去掉了observers和参数检查的特性
+gem 'protected_attributes'
+gem 'rails-observers'
+gem 'mongoid-observers'
+gem 'actionpack-page_caching'
+gem 'actionpack-action_caching'
执行bundle update更新到最新的版本,如果发生依赖冲突,则暂时去掉版本号
-gem 'mongo', '1.9.1'
-gem 'mongoid', '3.1.4'
-gem 'bson_ext', '1.9.1'
+gem 'mongo'
+gem 'mongoid'
+gem 'bson_ext'
例如:db-charmer发生了版本冲突,则去掉版本1.9.0, 更新到最新的版本
In Gemfile:
db-charmer (= 1.9.0) ruby depends on
activesupport (< 4.0.0) ruby
rails (= 4.1.5) ruby depends on
activesupport (4.1.5)
启动应用,根据log来检查所有gem包的加载是否报错,根据错误提示解决
有问题的几个gem
#client_side_validations 没有支持rails4的版本,暂时去掉
#gem "client_side_validations"
#替换为rails4支持的版本,否则会报错
-gem "galetahub-simple_captcha", '0.1.5', :require => "simple_captcha"
+gem 'simple_captcha2', require: 'simple_captcha'
-gem 'pry-debugger'
+gem 'pry-byebug'
Gem Install Debugger Error
No such file or directory @ rb_file_s_stat - ./213/ruby_debug.h (Errno::ENOENT)
Ruby 2.1.2 isn't supported by debugger, unfortunately. Instead,
use the byebug gem. See this discussion for more details.
修改gem 'pry-debugger' 为 gem 'pry-byebug'
rails4.1 Rails 4.1 breaks Cells
uninitialized constant Cell::Base::Layouts
修改cells版本为3.9.1 gem 'cells', '3.9.1'
rails4 强制加载路由文件
undefined method `concat' for nil:NilClass (NoMethodError)
在rails3中,config.paths['config/routes'].concat %w{admin schools}
在rails4中,使用Rails.application.reload_routes!替代
替换解析器
去掉ActiveSupport::XmlMini.backend = 'Nokogiri', activeSupport4,默认使用nokogiri解析xml文件 application.rb
# 替换解析器
+config.gem 'yajl-ruby', :lib => 'yajl/json_gem'
-ActiveSupport::XmlMini.backend = 'Nokogiri'
-ActiveSupport::JSON.backend = 'yajl'
undefined method `backend=' for ActiveSupport::JSON:Module (NoMethodError)
Yail advertises as much faster than JSON and YAML
ActiveSupport::JSON.backend = 'yajl' #activeSupport4 去掉了backend方法
https://github.com/brianmario/yajl-ruby/
http://stackoverflow.com/questions/3073711/whats-the-best-way-to-use-yajl-ruby-with-my-rails-project
更新配置文件 config/environments/*.rb
注释掉: config.active_record.auto_explain_threshold_in_seconds = 0.5
新增: config.eager_load = false
mongoid配置文件
去掉配置文件mongoid.yml中的
allow_dynamic_fields: true
identity_map_enabled: true
合法的配置选项有:
:include_root_in_json, :include_type_for_serialization, :preload_models, :raise_not_found_error,
:scope_overwrite_exception, :duplicate_fields_exception, :use_activesupport_time_zone, :use_utc
在升级Rails4的同时, mongoid 也从3.1.4 升到4.0.0, 运行rails server 命令, 结果报错 说:allow_dynamic_fields 是无效参数。
查看mongoid的change log, 发现 allow_dynamic_fields 已经从配置文件中 移除了,
如果想继续使用动态属性, 只需要在model 中添加
include Mongoid::Attributes::Dynamic
修改模型关联关系,去掉:conditions, order等rails3中的方法,在rails4中使用 ->{} 代替
- has_many :ws, :class_name => "B", :conditions => "b_type = 'b", :order => "status desc"
- has_many :ss, :class_name => "S", :conditions => "s_type = 's'", :order => "status desc"
- has_many :ws, -> { where("b_type = 'b'").order("status desc")}, :class_name => "B"
- has_many :ss, -> { where("s_type = 's'").order("status desc")}, :class_name => "S"
validates 正则表达式
check_options_validity': The provided regular expression is using multiline anchors (^ or $)
rails4中validates不支持 ^ 和 $ , 替换成\A 和 \z
- ACCOUNT_EMAIL_FORMAT = /^\s*#{FORMAT}\s*$/
- ACCOUNT_EMAIL_FORMAT = /\A\s*#{FORMAT}\s\z/
方式一,使用\A \z替代 ^ $
validates :mobile_number, :format => { :with => FORMAT }, :allow_blank => true
方式二,使用multiline: true说明
validates :content, format: { with: /^Meanwhile$/, multiline: true }
http://stackoverflow.com/questions/17759735/regular-expressions-with-validations-in-ror-4
http://guides.rubyonrails.org/security.html#regular-expressions
rails4 has_many uniq
uniq在rails4中的关联关系中需要放在一个block中,而且作为has_many的第二个参数
The uniq option needs to be moved into a scope block.
Note that the scope block needs to be the second parameter to has_many
(i.e. you can't leave it at the end of the line,
it needs to be moved before the :through => :donations part):
rails3: has_many :ds, :through => :ds, :uniq => true
rails4: has_many :ds, -> { uniq }, :through => :ds
rails3: has_many :ds, :through => :ds, :uniq => true, :order => "name", :conditions => "age < 30"
rails4: has_many :ds, -> { where("age < 30").order("name").uniq }, :through => :ds
http://stackoverflow.com/questions/16569994/deprecation-warning-when-using-has-many-through-uniq-in-rails-4
mongoid扩展
mongoid 从3.1.4升级到4.0.0, 查看源代码,发现mongoid的结构有了比较大的变化,那么我们在
3.1.4上做的扩展在这里就不适用了,主要从以下几个方面来进行检查
1.文件结构
3.1.4: Mongoid::Persistence
4.0.0: Mongoid::Persistence::Updatable
updatable是mongoid4抽象出来的一个module,原来放在Persistence这个module里的方法,一部分放到了
updatable中,重写方法的时候,注意函数的位置
2.函数
def update_attributes_with_format(attributes = {}, options = {})
update_attributes_without_format(attrs, options)
alias_method_chain :update_attributes, :format
end
扩展的时候重写了update_attributes方法,但是mongoid4.0.0版本中,已经去掉了options参数,这里也需要去掉
change logs mongoid去掉了IdentityMap,如果重写了IdentityMap相关的方法,就需要重新根据mongoid4.0.0 change log:
Scopes and default scopes must now all be defined within lambdas or procs.
skip_version_check config option was removed.
IdentityMap removed. (Arthur Neves)
Eager load rework. Eager load now doesnt need the identity map to load
related documents. A set of preloaders can eager load the associations
passed to .includes method. (Arthur Neves)
https://github.com/mongoid/mongoid/blob/006063727efe08c7fc5f5c93ef60be23327af422/CHANGELOG.md
https://github.com/mongoid/mongoid/issues/3406
rails4 加载多个路由文件
rails3中,项目比较大,很多路由被单独存放在 config/routes/*.rb 中,
加载的时候,在application.rb文件中使用下面的代码进行加载
-config.paths['config/routes'].concat %w{aa bb cc ...}
而在rails4中,Rails::Engine.paths 去掉了 ["config/routes"] 的key
解决办法,在config/routes.rb 的首行进行加载
+Dir[Rails.root.join("config/routes/*.rb")].each{|route| load route}
rails 路由
rails4中如果使用match,必须指定http方法
match 'homejson', to: 'afterwork#home_json', via: [:get, :post]
否则 需要替换match方法为get
- match 'like'
-
get 'like'
get 'file/:file_id', action: 'file', as: 'file'
delete 'file/:file_id', action: 'delete_file', as: 'file'
上面的这种配置,在rails4中会报以下错误, 解决办法是去掉最后一个,rails4会根据上一个自动添加
You may have defined two routes with the same name using the :as option
delete 'file/:file_id', action: 'delete_file'
find_or_create_by find_or_initialize_by
rails3:
User.find_or_create_by_name('XXX')
rails4:
User.where(name: 'XXX').first_or_create
User.where(name: 'XXX').first_or_create!
User.find_or_create_by(name: 'XXX')
rails3:
User.find_or_initialize_by_name('XXX')
rails4:
User.where(name: 'XXX').first_or_initialize
http://snippets.aktagon.com/snippets/620-rails-find-or-initialize-and-find-or-create-methods-are-deprecated
client_side_validations
client_side_validations 3.2.6 不适用rails4,暂时先去掉
preloading : no such column问题
class Corp < ActiveRecord::Base
has_many :ins, ->{where("corp_enus.category=2")}, class_name: "CorpEnu"
end
方式一: 使用includes, 添加references
rails3
includes(:ins).where("corp_enus.enum_value1 = ?",id).order("followers desc").limit(limit)
rails4, 添加.references(:industries)
includes(:ins).where("corp_enus.enum_value1 = ?", id).order("followers desc").limit(limit).references(:ins)
方式二:使用eager_load替换includes
includes(:ins).where("corp_enus.enum_value1 = ?",id).order("followers desc").limit(limit)
eager_load(:ins).where("corp_enus.enum_value1 = ?",id).order("followers desc").limit(limit)
http://api.rubyonrails.org/v4.0.1/classes/ActiveRecord/QueryMethods.html#method-i-eager_load
http://api.rubyonrails.org/v4.0.1/classes/ActiveRecord/QueryMethods.html#method-i-preload
http://api.rubyonrails.org/v4.0.1/classes/ActiveRecord/QueryMethods.html#method-i-includes
http://blog.arkency.com/2013/12/rails4-preloading/
Mongoid::Errors::InvalidField
错误信息
Mongoid::Errors::InvalidField -
Problem:
translation missing: zh-CN.mongoid.errors.messages.invalid_field.message
Summary:
translation missing: zh-CN.mongoid.errors.messages.invalid_field.summary
Resolution:
translation missing: zh-CN.mongoid.errors.messages.invalid_field.resolution:
class AuthorizationMongo
include Mongoid::Document
include Mongoid::Timestamps
field :deleted, type: Boolean, default: false
end
修改字段 deleted 为 is_deleted, 问题解决
SystemStackError - stack level too deep
错误信息:
actionpack (4.0.0) lib/action_dispatch/middleware/reloader.rb:70:in `'
可能是写法问题导致的,调试发现把user.name 改成 user[:name]就不会出现这个错误
但是不清楚为什么
代码:
def link_to_user(user, opt={})
return if user.blank?
inner = opt.delete(:inner)
opt[:title] ||= "#{user[:name]}, #{user[:headline]}"
end
把user.name 改成 user[:name]
uninitialized constant Mongoid::Observer
mongoid4去掉了Mongoid::Observer, 所以找不到Mongoid::Observer
在Gemfile中添加gem 'mongoid-observers'问题解决,用法和原来一样
# 资料完整度的观察者
class Profile::ProfileCentObserver < Mongoid::Observer
observe :user_mongo
def after_save user
end
end