Rails 3 : Anticipating migration for 2.3 beginners - ruby-on-rails

I am a beginner in Rails. I use 2.3.X.
I just saw Rails 3 is pre-released [edit: now in release candidate!]. I will most probably eventually switch to it.
What are the common coding habits in 2.3 I should not take, so that the switch is as smooth as possible ?
Edit:
I've done my homework and read the Release notes. But they are far from clear for the most crucial points, for example :
1.5 New APIs
Both the router and query interface have seen significant, breaking changes. There is a backwards compatibility layer that is in place and will be supported until the 3.1 release.
This is not comprehensive enough for a beginner like me. What will break ? What could I do already in 2.3.X to avoid having troubles later ?

Looking at my personal coding habits (I have been using Rails since 1.2.x), here's a list of API changes you can anticipate according to Rails 3 release notes.
find(:all)
Avoid the usage of:
Model.find(:all)
Model.find(:first)
Model.find(:last)
in favour of:
Model.all
Model.first
Model.last
Complex queries
Avoid the composition of complex queries in favor of named scopes.
Anticipate Arel
Rails 3 offers a much cleaner approach for dealing with ActiveRecord conditions and options. You can anticipate it creating custom named scopes.
class Model
named_scope :limit, lambda { |value| { :limit => value }}
end
# old way
records = Model.all(:limit => 3)
# new way
records = Model.limit(3).all
# you can also take advantage of lazy evaluation
records = Model.limit(3)
# then in your view
records.each { ... }
When upgrading to Rails 3, simply drop the named scope definition.
Constants
Avoid the usage of the following constants in favour of the corresponding Rails.x methods, already available in Rails 2.x.
RAILS_ROOT in favour of Rails.root,
RAILS_ENV in favour of Rails.env, and
RAILS_DEFAULT_LOGGER in favour of Rails.logger.
Unobtrusive Javascript
Avoid heavy JavaScript helpers in favour of unobtrusive JavaScript.
Gem dependencies
Keep your environment.rb as clean as possible in order to make easier the migration to Bundler. You can also anticipate the migration using Bundler today without Rails 3.

The release notes are the most important thing to keep an eye on. Other than that Jeremy McAnally has some neat blog posts about the whole Rails 3 thing (and has just released a gem to help you with the migration).

I'd say, read the rails release notes and see for yourself what seems the more surprising to you. A lot of stuff changed so reading this is definitively very important.

Related

"Status is Invalid" - Active Record - Rails 4.1 -> 5.2

I'm working on upgrading a Ruby 2.2.2 (Rails 4.1) app to Ruby 2.5.7 (Rails 5.2) and for a couple of models I'm getting some errors
From searching around, it sounds like there are some generic activerecord validation rules / messages? The messages are:
Status is invalid
User is invalid`
I am a novice at best with Ruby - so any suggestions on the best way to work through this error are appreciated!
In Rails 5, whenever a belongs_to association is defined, it is required to have the associated record present by default. That means, compared to Rails 4, each belongs_to :foo association basically adds internally a validate :foo, presence: true to the code too.
You have two choices:
Follow the new Ruby on Rails conventions and fix your tests by adding all required associated objects to the models.
Switch back to the old behavior for these kinds of associations by adding , optional: true to each belongs_to :foo line in your code.
There is actually the third option to switch off this behavior in the whole application, by adding a line like this to your application.rb
Rails.application.config.active_record.belongs_to_required_by_default = true
But that means your application will not follow Ruby on Rails conventions and defaults anymore and IMHO this ofter leads to problems with a later update.
Therefore my advice is: Fix your tests now and only make those associations optional that are really optional from the user's point of view – this might take a bit longer but causes certainly less trouble in the future.

Can you tell me about any methods that Rails adds to existing Ruby classes?

Before I ask a question, I like to caution everyone that I am a programming newbie, so please correct me if I ask something ridiculous.
I have been reading about Ruby having open classes, i.e a method can be added. However, I am trying to get a few examples of how Rails might have added to existing Ruby classes.
Rails has so many core extensions they're in a separate gem – ActiveSupport.
No sense trying to explain everything here, I'll just point you to the Rails guides. After you are familiar with them, refer to the documentation when you need to.
I second Matheus. ActiveSupport is a good example. Take a look at some source code files here:
https://github.com/rails/rails/tree/master/activesupport/lib/active_support/core_ext
And, here's a typical and simplistic example which adds useful and somewhat controversial methods on standard Array class in Ruby.
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/array/access.rb
Most Ruby libraries have a directory named 'core_ext', 'ext' or something along this line which includes methods that extend Ruby's core library in a way or another. People always reinvent methods and in a sense, ActiveSupport is the definitive compilation of those.
I have found that a great example is Time
From a rails application
Time.
Loading development environment (Rails 3.2.3)
1.9.3p125 :001 > Time.
Display all 252 possibilities? (y or n)
Time.module_exec
Time.__delay__ Time.mongo_thread_local_accessor
Time.__id__ Time.name
...
Total = 252
From a plain ruby console (IRB)
$ irb
1.9.3p125 :001 > Time.
Time.hash Time.private_method_defined?
Time.__id__ Time.include? Time.private_methods
Time.__send__ Time.included_modules Time.protected_instance_methods
...
Total = 93

How to set transaction isolation level using ActiveRecord connection?

I need to manage transaction isolation level on a per-transaction basis in a way portable across databases (SQLite, PostgreSQL, MySQL at least).
I know I can do it manually, like that:
User.connection.execute('SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE')
...but I would expect something like:
User.isolation_level( :serializable ) do
# ...
end
This functionality is supported by ActiveRecord itself:
MyRecord.transaction(isolation: :read_committed) do
# do your transaction work
end
It supports the ANSI SQL isolation levels:
:read_uncommitted
:read_committed
:repeatable_read
:serializable
This method is available since Rails 4, it was unavailable when the OP asked the question. But for any decently modern Rails application this should be the way to go.
There was no gem available so I developed one (MIT): https://github.com/qertoip/transaction_isolation
Looks Rails4 would have the feature out of box:
https://github.com/rails/rails/commit/392eeecc11a291e406db927a18b75f41b2658253

Best Practice for Detecting Rails Version for Plugin Compatibility?

I'm working on upgrading a plugin for Rails 3.0.5, specifically, this commit. Essentially, ActiveRecord requires a proc instead of a string for condition interpolation.
In general, I think the best way to handle something like this is with a respond_to? call, but in this case all of the methods that were changed are private. What's the best practice for checking the rails version so that the plugin can give new versions a proc, and old versions a string? I'd rather not rely on checking that private methods exist, since that is likely to break in the future.
Rails.version
# => "3.0.5"
Rails::VERSION::MAJOR
# => 3
Rails::VERSION::MINOR
# => 0
Rails::VERSION::TINY
# => 5

Integer ordinalization in Ruby/Rails

I'm looking for a way to handle integer ordinalization in Ruby/Rails, ie. "st", "nd", "rd", and "th" suffixes to integers. Ruby on Rails used to extend FixNum with an "ordinalize" method, but that functionality seems to have been deprecated in version 3.
I am currently just using the source for the old Rails method, which is fine... but this seems like functionality that most scripting languages / web frameworks would have built in, and I feel like the folks behind Rails must have had a reason for deprecating the functionality (perhaps it is now available in Ruby proper?).
Please advise!
The method you want is still ordinalize.
Active_Support was refactored a bit to provide better granularity. Instead of loading in everything at once, you can select smaller chunks depending on what you need.
You can either load everything in Active_Support using require 'active_support/all', or break it down using
require 'active_support/core_ext/integer/inflections':
>> require 'active_support/core_ext/integer/inflections' #=> true
>> 1.ordinalize #=> "1st"
Lately (last I knew) there has been a trend to not modify core classes. The Rails-Core mailing list might have a better answer for this one.
It looks like that functionality was moved to Inflector from a Fixnum extension which makes sense. Hopefully someone else can confirm this.

Resources