Search code examples
ruby-on-railsrubyalpine-linux

params.permit undefined method `=~' for Active::Record after ruby3.2.1 update


recently I updated from ruby3.1.2-alpine3.15 -> ruby3.2.1-alpine3.17, the only gem update I did was mysql2, from 0.5.3 to 0.5.5 to support openssql3. And folow Ruby3.2.0 Breaking Changes and add the --jit --yjit flags. Almost all the app work just fine. But somehow a piece of code dont. Just a simple params.permit:

permitted_params = params.permit(:category_id, :private, tags: [])

which fail with a

NoMethodError:
       undefined method `=~' for #<HereGoes::MyModel>

And my params looks like this: (where "fields" y just extra data). Only weird thing i see is nested ActionController::Parameters but this same params is just parsed fine in older ruby version.

"#<ActionController::Parameters  {\"field_values\"=>[#<ActionController::Parameters 
{\"field_id\"=>4, \"value\"=>\"Test changed\", \"type\"=>\"string\"} permitted: false>], #
<HereGoes::MyModel id: nil, category_id: nil, uuid: \"87ebb507-e381-4d57-b66c-10e51f10c014\", 
created_at: nil, updated_at: nil, name: \"Alphazap5\", \"fields\"=> {\"Viva11\"=>nil,\"Y-solowarm4 
TextField\"=>nil,\"Y-solowarm4 StringField\"=>nil,\"Y-solowarm4 LocationsField\"=>nil}}, 
backup_id: 0, options: {}, tag_list: nil>=>{\"id\"=>1}} permitted: false>"

If I back to ruby3.1.2 it works again. Both params are the same in ruby3.1.2 and ruby3.2.1 at the moment of execute the .permit method.

I dont know what more could it be. I haven't found anything in the ruby ​​or rails issues related to my problem. So... if anyone have an idea, I'll be grateful.

  • I tried to keep same gems between ruby versions
  • I compare both params in both ruby versions being exact the same
  • I saw for changes in ruby3.2.x may affect indirectly ActiveRecord
  • I tried disabling --jit --yjit para

Solution

  • Object#=~ has been removed (aka Kernel#=~):
    https://rubyreferences.github.io/rubychanges/3.2.html#removals


    The issue is here:
    https://github.com/rails/rails/blob/v7.0.4.2/actionpack/lib/action_controller/metal/strong_parameters.rb#L1069

    next unless key =~ /\(\d+[if]?\)\z/
    

    You have HereGoes::MyModel as a key in params:

    { "field_values" => [...], #<HereGoes::MyModel...> => {"id"=>1} }
    

    This never got permitted before, since Object#=~ just returns nil, which was the reason for removal:

    # v3.1.2
    >> ActionController::Parameters.new({field_values: [], Class.new => {id: 1}}).permit(:id, field_values: [])
    => #<ActionController::Parameters {"field_values"=>[]} permitted: true>
    
    # v3.2.1
    >> ActionController::Parameters.new({field_values: [], Class.new => {id: 1}}).permit(:id, field_values: [])
    /home/alex/.rbenv/versions/3.2.1/lib/ruby/gems/3.2.0/gems/actionpack-7.0.4.2/lib/action_controller/metal/strong_parameters.rb:1069:in `block in permitted_scalar_filter':
    undefined method `=~' for #<Class:0x00007fd63c224380> (NoMethodError)
    

    You must be doing something else somewhere else to make it work.

    Your models shouldn't really be in params, you'd have to share some code if you need help with that.