0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

rails 4 与 rails 3 的差异记录

Posted at

修改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
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?