Rails 7.1 raises an error on generating model attributes with dangerous name

railsOctober 27, 2023Dotby Alkesh Ghorpade

A Rails migration is a Ruby file that describes changes to your database schema. Migrations are used to add, remove, or modify database tables and columns. They are also used to create database indexes and constraints.

While adding table attributes, a developer can easily make a mistake and mention column names, which are keywords in Ruby language. For example, if a developer adds a column name as any of the column names as attributes, attribute_names, changes, to_global_id, the Rails application should raise an error. These are known as dangerous_attributes in Rails.

Before Rails 7.1

Before Rails 7.1, neither a warning nor any error was raised when a developer specified the dangerous attributes as column names in the table. This would create issues in the code if the column names are unchecked, and it would be hard to debug the root cause.

Let's say you have a User model and added a column attribute to it in the database migration.

bin/rails generate model User name:string email:text attributes:jsonb

class CreateUsers < ActiveRecord::Migration[6.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.jsonb :attributes, default: '{}'
      t.timestamps
    end
  end
end

The migration would work fine without raising any issues or concerns. But when you try to create a User record in the Rails console, it will raise the below error:

User.create!(name: "alkesh", email: "alkesh26@gmail.com", attributes: { country: 1 })

=> attributes is defined by Active Record. 
Check to make sure that you don't have an attribute 
or 
method with the same name. (ActiveRecord::DangerousAttributeError)

The developer needs to rework the migration or create a new migration to rename it.

In Rails 7.1

Rails 7.1 raises error on generating model attributes with dangerous name. The feature will raise an error if you specify any dangerous attribute when generating a migration.

bin/rails generate model User name:string email:text attributes:jsonb

=> Could not generate field 'attributes', as it is already defined by Active Record.

The feature saves you time by not proceeding with an invalid attribute and then figuring out the issue.

If you want to check the list of dangerous_attributes, you need to execute the command below in the Rails console or refer to the method dangerous_attribute_methods.

def get_dangerous_attributes
  (
    ActiveRecord::Base.instance_methods + 
    ActiveRecord::Base.private_instance_methods - 
    ActiveRecord::Base.superclass.instance_methods - 
    ActiveRecord::Base.superclass.private_instance_methods + 
    %i[__id__ dup freeze frozen? hash object_id class clone]
  ).map { |m| -m.to_s }.to_set.sort
end

get_dangerous_attributes
=> [
 "[]",                     
 "[]=",                    
 "__callbacks",            
 "__callbacks?",           
 "__id__",
 ....
 ....
]

To know more about this feature, please refer to this PR.

Closing Remark

Could your team use some help with topics like this and others covered by ShakaCode's blog and open source? We specialize in optimizing Rails applications, especially those with advanced JavaScript frontends, like React. We can also help you optimize your CI processes with lower costs and faster, more reliable tests. Scraping web data and lowering infrastructure costs are two other areas of specialization. Feel free to reach out to ShakaCode's CEO, Justin Gordon, at justin@shakacode.com or schedule an appointment to discuss how ShakaCode can help your project!
Are you looking for a software development partner who can
develop modern, high-performance web apps and sites?
See what we've doneArrow right