http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-3-2-to-rails-4-0
commits marked with [rails 4]
##no more match routes # change match 'logout' => 'user_sessions#destroy', :as => :logout
# to
post 'logout' => 'user_sessions#destroy', :as => :logout
if different http verbs needed this can be set with the as:
option
match 'logout' => 'user_sessions#destroy', :as => :logout, via: [:get, :post]
##Change scopes to use lambdas # change scope :training, where(:name => "Training User")
# to
scope :training, -> { where(:name => "Training User") }
# change
@user = User.find(:first, :conditions => ["lower(email) = ?", @email])
# to
@user = User.where("lower(email) = ?", @email).first
-
#change has_many :loop_component_notification_responses, :through => :notification, :conditions => { :override_id => nil }
has_many :loop_component_notification_responses, -> { where(override_id: nil) }, through: :notification
##change serialized columns to pg json columns. # removed serialize :preferences, JSON
# change column
change_column :accounts, :preferences, :json, default: {}
json columns cannot be changed as
hash[:key] = value
ActiveModel does not detect that the hash has changed.
If changed this way mark object as will be changed
class CannedMessageMatrix
def remove_canned_message(message_id)
...
self.matrix_will_change!
self.matrix.each do |k,v|
v.delete(message_id)
self.matrix[k] = v
end
end
...
end
or change the whole hash object
hash = object.hash.clone
hash[:a] = 1
object.hash = hash
##dynamic find methods deprecated except find_ by_ ...
# change
token = TrainingToken.find_or_create_by_email_and_practice_id(row[:email_address], practice.id)
#to
token = TrainingToken.find_or_create_by(email: row[:email_address], practice_id: practice.id)
-
matrix = klass.find_or_initialize_by_account_id_and_practice_id(current_account.id, current_account.practice.id)
matrix = klass.find_or_initialize_by(account_id: current_account.id, practice_id: current_account.practice.id)
we had this and I was getting a NoMethodError: undefined method 'delete_at' for ActiveRecord_Relation ...
entities = self.order(:name)
...
other = entities.delete_at(other_idx)
User.all.delete_at(1)
# NoMethodError: undefined method `delete_at' for #<User::ActiveRecord_Relation:0x007fe5c67e2b48>
entities = self.order(:name).to_a # to actually execute the query and get an array
other = entities.delete_at(other_idx)
##strong parameters
gem 'protected_attributes'
I added this gem for backward compatibility so we can keep using
attr_accessible :account_id, :acknoweldged_at, :content, …
Rails 4 now uses strong parameters. Lets try to change code to this method so on refactoring we know which parameters are needed for an specific action
params = ActionController::Parameters.new({a: 1, b: 2, c: 3})
params.permit(:a)
# => {"a"=>1}
when a parameter is required use #require
params.require(:d)
# => ActionController::ParameterMissing: param is missing or the value is empty: d
require returns the value of the required attributes
params = ActionController::Parameters.new({user: {name: 'Adrian', number: 12}})
params.require(:user)
=> {"name"=>"Adrian", "number"=>12}
params.require(:user).permitted?
=> true
we need the parameters to return true
on #permitted?
params = ActionController::Parameters.new({ user: {username: "john"}})
User.new(params[:user])
# => ActiveModel::ForbiddenAttributesError
User.new(params.require(:user))
example.
class UserController
def create
User.create(user_params)
end
private
def user_params
params.require(:user).permit(:username, :other, :other2, ...)
end
end
more here http://blog.trackets.com/2013/08/17/strong-parameters-by-example.html