Rails 4, Ruby 2.7.1 schema.rb shows "Could not dump table because of following FrozenError"
Asked Answered
F

2

9

After upgrading to Ruby 2.7.1 my schema.rb is peppered with the following warnings for multiple tables:

# Could not dump table "pages" because of following FrozenError
#   can't modify frozen String: "false"

# Could not dump table "proxies" because of following FrozenError
#   can't modify frozen String: "true"

I've searched high and low for a solution and have checked (as far as I'm able) the migrations, of which there are many. Downgrading Ruby at this staging isn't an option.

Anyone has a similar situation and managed to resolve it?

Forgetmenot answered 25/6, 2020 at 8:3 Comment(5)
Which specific version of Rails are you using?Benzvi
I'm running Rails 4.2.11Forgetmenot
Tried to replicate your problem, I couldn't even run the migrations. Is there a way to reproduce your problem?Benzvi
You will either need to downgrade ruby to around 2.4.5 or upgrade rails. Here is a closed issue against rails 5.x saying it 2.7 is not supported due to numerous warnings and issues: github.com/rails/rails/issues/38426Dashtikavir
thanks @mlockerd I guess its time to upgrade Rails :|Forgetmenot
A
8

If someone is still looking for this.

The error is because in the old version of rails the schema dumper used the to_s to convert database default column value to string and then perform operations on that string. But in ruby 2.7 the to_s method for nil, true and false return a frozen string and hence the FrozenError, so if upgrading rails version is not an option you can just put this in an initializer to override the schema dumper method to use the dup instead of actual string.

module ActiveRecord
  module ConnectionAdapters
    module ColumnDumper
      def prepare_column_options(column, types)
        spec = {}
        spec[:name]      = column.name.inspect
        spec[:type]      = column.type.to_s
        spec[:null]      = 'false' unless column.null

        limit = column.limit || types[column.type][:limit]
        spec[:limit]     = limit.inspect if limit
        spec[:precision] = column.precision.inspect if column.precision
        spec[:scale]     = column.scale.inspect if column.scale

        default = schema_default(column).dup if column.has_default?
        spec[:default]   = default unless default.nil?

        spec
      end
    end
  end
end

Aftmost answered 9/8, 2021 at 7:38 Comment(1)
this is helped, thank you !Selfcentered
D
0

I know you mentioned that downgrading RUby isn't an option for you.

But if you are able to downgrade Ruby here's what worked for me.

This is a Ruby 2.7 issue as noted by rmlockerd.

I ended up downgrading my Ruby version to '2.6.6'.

After downgrading my Ruby, I ran db:schema:load and was able regenerate the schema file without the above errors.

Deeannadeeanne answered 28/6, 2021 at 16:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.