Foreword
Hi everyone, in this article I would like to share about some quite important points in the process of upgrading Rails 4 to Rails 6 which I was very fortunate to be directly doing and some additional points of reference. From all the documents.
This was a very positive experience for myself and I also learned a lot from this. Especially practicing perseverance and not thinking about giving up !!! : v
And before going into the main content, I want to note one thing that is “If you intend to upgrade the version for Rails, please control the previous version as well as possible, or in other words, should upgrade the version”. new when you are using its immediate previous version: v ”
I. Update from Rails 4.2 to 5.0
1. Application code
a. ActiveRecord
ActiveRecord inherits from ApplicationRecord, so in model files you should create the following
1 2 3 4 | <span class="token keyword">class</span> <span class="token class-name">ApplicationRecord</span> <span class="token operator"><</span> <span class="token constant">ActiveRecord</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token constant">Base</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> abstract_class <span class="token operator">=</span> <span class="token keyword">true</span> <span class="token keyword">end</span> |
And then update all the models to inherit from ApplicationRecord
. The only class inheriting from ActiveRecord::Base
will be ApplicationRecord
With associations belongs_to
created by default in the model, this means that if the link does not exist for the model when saving, an error will be triggered. Use option: true
to avoid this error belongs_to :user, optional: true
b. Controllers
When I performed the upgrade operation for Controllers, I encountered a problem related to Parameters as follows: from Rails 5 onwards, ActionController :: Parameters does not inherit Hash, this is equivalent to the params in Rails 5 later, methods like fetch, slice, except, etc. will not be used.
Example error:
1 2 3 4 5 | <span class="token constant">NoMethodError</span> <span class="token operator">-</span> undefined method `exclude <span class="token operator">?</span> ' <span class="token keyword">for</span> <span class="token comment">#<ActionController::Parameters:0x00005626cd391508>:</span> app <span class="token operator">/</span> controllers <span class="token operator">/</span> admin <span class="token operator">/</span> manager_items_controller <span class="token punctuation">.</span> rb <span class="token punctuation">:</span> <span class="token number">145</span> <span class="token symbol">:in</span> `block <span class="token punctuation">(</span> <span class="token number">2</span> levels <span class="token punctuation">)</span> <span class="token keyword">in</span> create_event_items' <span class="token constant">ActionController</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token constant">UnfilteredParameters</span> <span class="token operator">-</span> unable to convert unpermitted parameters to hash |
You need to permit the params you want to use Hash methods or use to_unsafe_h to convert to HashWithIndifferentAccess. Imagine the number of places to use params in your system, you will have to sweat when knowing how to upgrade Rails 5 will be like this: v because its impact is almost the whole system !!!
2. Testing
In Rails 5.0, the Rspec (Unit Test) change point could include the assigns
method, which has been incorporated into the rails-controller-testing
gem. If you want to use it you need to add on the gem 'rails-controller-testing'
Gemfile gem 'rails-controller-testing'
II. Update from Rails 5.0 to 5.1
1. Application code
a. ActiveRecord
In Rails 5.1, there is a significant change in ActiveRecord that I encountered that is ActiveRecord::Base#uniq
has been ActiveRecord::Base#uniq
and replaced by distinct
.
In addition, there are a number of other changes such as raise_in_transactional_callbacks
have now been removed and use_transactional_fixenses
is replaced by use_transactional_tests
b. Controllers
Prior to 5.1, conditions in filters could be called via “string”, in Rails 5.1 it was called via “symbol” Before:
before_action :authenticate_user!, unless: 'has_project_guest_id'
After:
before_action :authenticate_user!, unless: :has_project_guest_id
All *_filter
methods will now switch to calling via *_action.
For example
Before:
1 2 3 4 | skip_before_filter <span class="token symbol">:authenticate_user!</span> before_filter <span class="token symbol">:authenticate_user!</span> after_filter <span class="token symbol">:do_something</span> |
After:
1 2 3 4 | skip_before_action <span class="token symbol">:authenticate_user!</span> before_action <span class="token symbol">:authenticate_user!</span> after_action <span class="token symbol">:do_something</span> |
2. Testing
With Rspec in version 5.1 there is a very important point about the params key. Rails 5.1 supports parameter passing without using keyword arguments.
Before:
1 2 | expect <span class="token punctuation">{</span> post <span class="token symbol">:create</span> <span class="token punctuation">,</span> params <span class="token punctuation">}</span> <span class="token punctuation">.</span> to <span class="token function">change</span> <span class="token punctuation">(</span> <span class="token constant">Project</span> <span class="token punctuation">,</span> <span class="token symbol">:count</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">by</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> |
After:
1 2 | expect <span class="token punctuation">{</span> post <span class="token symbol">:create</span> <span class="token punctuation">,</span> params <span class="token punctuation">:</span> params <span class="token punctuation">}</span> <span class="token punctuation">.</span> to <span class="token function">change</span> <span class="token punctuation">(</span> <span class="token constant">Project</span> <span class="token punctuation">,</span> <span class="token symbol">:count</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">by</span> <span class="token punctuation">(</span> <span class="token number">1</span> <span class="token punctuation">)</span> |
III. Update from Rails 5.1 to 5.2
Application code
a. ActiveRecord
In rails 5.2, ActiveRecord :: Dirty has some noticeable changes. There are several warnings regarding API changes when running rails 5.1. Most of them are action changes.
b. Controllers
When I check for some errors related to DateTime type data that cannot be used in some functions such as year (), date (), … as_json in the old version, when converting a data, it will not classify the data type. Data DateTime should be used.
Thus, with rails 5 or rails 6, the data classification has been more clear, ie as_json will now return the string data type for DateTime when converting.
Another error about to_josn and as_json is undefined methods when the only parameter or method containing the method / attribute does not belong to the current object, so it is necessary to remove these redundant methods from the as_json parameter. If this is the case, it is necessary to declare the parameters separately with the separate methods used for each part rather than calling the same methods for 1 parameter.
c.Active Storage
I have found an error related to the image_tag tag as follows
1 2 | <span class="token constant">ActionView</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token constant">Template</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token constant">Error</span> <span class="token punctuation">:</span> <span class="token constant">Can</span> <span class="token string">'t resolve image into URL: undefined method `to_model'</span> <span class="token keyword">for</span> <span class="token comment">#</span> |
The reason is because the object belongs to ImageUploader of gem carrier wave when used with image_tag, the image_tag receives an object rather than a string
To solve this problem, I have a safe solution to avoid increasing the scope of influence as follows
1 2 3 | chuyển result từ <span class="token constant">ImageUploader</span> thành string như sau <span class="token string">" <span class="token interpolation"><span class="token delimiter tag">#{</span> object <span class="token delimiter tag">}</span></span> "</span> nếu object không phải <span class="token keyword">class</span> <span class="token class-name">ImageUploader</span> thì vẫn sẽ chuyển về string |
IV. Update from Rails 5.2 to 6.0
Some elimination of Rails 6
- Some removal of Rails 6 include: after_bundle, capify !, config.secret_token
- In Action Pack, remove fragment_cache_key and replace with combined_fragment_cache_key
- In ActionDispatch :: TestResponse have some changes like #success? Replace with #successful ?, #missing? Replace with #not_found? , error? Replace with #server_error?
- Action View removes image_alt , RecordTagHelper instead of gem record_tag_helper
- Active Record removes #set_stat from object’s transaction, #supports_statement_cache? of database adapters, “sum, count” when working with column
- Remove ActiveRecord :: Migrator.migrations_path =, expand_hash_conditions_for_aggregates
The above is a small part of the Rails 6 upgrade process that I and the team have done, thank you for watching, hello and see you again ^^!
Source of reference: some quotes from The Complete Guide To Upgrade Rails
https://stackoverflow.com/questions/53883893/cant-resolve-image-into-url-undefined-method-to-model
https://github.com/rails-api/active_model_serializers/issues/1851
https://stackoverflow.com/questions/46029084/rails-unable-to-convert-unpermitted-parameters-to-hash