Many things has been deprecated or removed (preceded by earlier deprecation notices that we happily ignored). Code working in Rails 3 not necessarily works in Rails 4 without changes.
User.find(:all,
:conditions => {:name => 'Jane Doe'},
:limit => 3,
:order => :created_at)
User.where(name: 'Jane Doe').limit(3).order(created_at: :desc)
Gem: activerecord-deprecated_finders
https://github.com/rails/activerecord-deprecated_finders
But we are trying to avoid it.
[3] pry(main)> Order.includes(:owner_subject).limit(3)
Order Load (0.9ms) SELECT "orders".* FROM "orders" LIMIT 3
Subject Load (59.2ms) SELECT "subjects".* FROM "subjects" WHERE "subjects"."id" IN (13)
[5] pry(main)> Order.includes(:owner_subject).limit(3).where('subjects.id > 1')
SQL (2.0ms) SELECT "orders"."id" AS t0_r0, "orders"."created_at" AS t0_r1,
"orders"."type" AS t0_r2, "orders"."name" AS t0_r3, "orders"."number" AS t0_r4,
"orders"."job_process_id" AS t0_r5, "orders"."root_id" AS t0_r6,
"orders"."parent_id" AS t0_r7, "orders"."lft" AS t0_r8, "orders"."rgt" AS t0_r9,
"orders"."owner_subject_id" AS t0_r10, "orders"."status" AS t0_r11,
"orders"."deleted" AS t0_r12, "orders"."mis_ref" AS t0_r13,
"orders"."altered_at" AS t0_r14, "orders"."version_no" AS t0_r15,
"orders"."current_version_no" AS t0_r16, "orders"."seq_no" AS t0_r17,
"subjects"."id" AS t1_r0, "subjects"."kind" AS t1_r1, "subjects"."parent_id" AS t1_r2,
"subjects"."lft" AS t1_r3, "subjects"."rgt" AS t1_r4, "subjects"."domain_id" AS t1_r5,
"subjects"."language_locale" AS t1_r6 FROM "orders" LEFT OUTER JOIN "subjects"
ON "subjects"."id" = "orders"."owner_subject_id" WHERE (subjects.id > 1) LIMIT 3
2.1.2 :007 > Document.includes(:user).where('id > 2')
Document Load (1.0ms) SELECT "documents".* FROM "documents" WHERE (id > 2)
User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (3, 1)
2.1.2 :008 > Document.includes(:user).where('users.id < 2')
Document Load (1.5ms) SELECT "documents".* FROM "documents" WHERE (users.id < 2)
PG::UndefinedTable: ERROR: missing FROM-clause entry for table "users"
LINE 1: SELECT "documents".* FROM "documents" WHERE (users.id < 2)
^
: SELECT "documents".* FROM "documents" WHERE (users.id < 2)
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: missing
FROM-clause entry for table "users"
LINE 1: SELECT "documents".* FROM "documents" WHERE (users.id < 2)
2.1.2 :016 > Document.joins(:files).each {|d| d.files.map(&:id) }
Document Load (1.9ms) SELECT "documents".* FROM "documents" INNER JOIN "document_files" ON "document_files"."document_id" = "documents"."id"
DocumentFile Load (0.5ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 1]]
DocumentFile Load (0.5ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 2]]
DocumentFile Load (0.6ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 3]]
DocumentFile Load (0.5ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 4]]
DocumentFile Load (0.5ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 5]]
DocumentFile Load (0.5ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 6]]
DocumentFile Load (0.4ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 7]]
DocumentFile Load (0.4ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 8]]
DocumentFile Load (0.4ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 9]]
DocumentFile Load (0.3ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 10]]
DocumentFile Load (0.3ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 11]]
DocumentFile Load (0.3ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 12]]
DocumentFile Load (0.4ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 11]]
DocumentFile Load (0.4ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 10]]
DocumentFile Load (0.5ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 1]]
DocumentFile Load (0.5ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 13]]
DocumentFile Load (0.5ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 13]]
DocumentFile Load (0.6ms) SELECT "document_files".* FROM "document_files" WHERE "document_files"."document_id" = $1 [["document_id", 14]]
[...]
2.1.2 :017 > Document.joins(:files).includes(:files).each {|d| d.files.map(&:id) }
SQL (2.6ms) SELECT "documents"."id" AS t0_r0, "documents"."name" AS t0_r1,
"documents"."status" AS t0_r2, "documents"."user_id" AS t0_r3, "documents"."created_at" AS t0_r4,
"documents"."updated_at" AS t0_r5, "documents"."file_file_name" AS t0_r6,
"documents"."file_content_type" AS t0_r7, "documents"."file_file_size" AS t0_r8,
"documents"."file_updated_at" AS t0_r9, "documents"."details" AS t0_r10,
"document_files"."id" AS t1_r0, "document_files"."document_id" AS t1_r1,
"document_files"."intent" AS t1_r2, "document_files"."created_at" AS t1_r3,
"document_files"."updated_at" AS t1_r4, "document_files"."file_file_name" AS t1_r5,
"document_files"."file_content_type" AS t1_r6, "document_files"."file_file_size" AS t1_r7,
"document_files"."file_updated_at" AS t1_r8, "document_files"."file_processing" AS t1_r9
FROM "documents" INNER JOIN "document_files" ON "document_files"."document_id" = "documents"."id"
In Rails 4 routing with "match" without specifying verbs is illegal.
# DON'T
match 'orders/:id/condemn' => 'orders#condemn'
# DO
match 'orders/:id/condemn' => 'orders#condemn', via: [:post]
# DO BETTER
post 'orders/:id/condemn' => 'orders#condemn'
# DON'T
post '' => 'orders#create', :as => :orders
match '' => 'orders#index', :as => :orders
# DON'T
scope :not_deleted, where(deleted: false)
has_many :good_comments, conditions: 'karma > 1'
# DO
scope :not_deleted, -> { where(deleted: false) }
has_many :good_comments, -> { where('karma > 1') }
Rails 4 has native support for JSON and hstore types in PotgreSQL. Calling "serialize" causes double serialization, which is never good.
# DON'T
serialize :options, ActiveRecord::Coders::Hstore
# DO
# well, just make sure that column is of hstore type and you're good to go
# DON'T
@model.options[:active] = true
@model.save!
# DO
@model.options_will_change!
# or @model.attribute_will_change!(:options)
@model.options[:active] = true
@model.save!
# OR DO
opts = @model.options
opts[:active] = true
@model.options = opts
def safe_params
params.require(:document).permit(files_attributes: [:file])
end
PATCH is default verb for update action since Rails 4.0, however PUT is still supported.