oj: Oj v3.13 seems to be freezing empty string values

Hey! We recently updated Oj from version 3.12.3 to v3.13.1, and something changed (I guess in Oj.load?) and it is causing errors in our rails app.

Here is a reproducible test case:

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  gem "activerecord", "~> 6.1.0"
  gem "sqlite3"
  gem "oj"
end

require "active_record"
require "minitest/autorun"
require "logger"
require "oj"

Oj.optimize_rails

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :users, force: true do |t|
    t.json :profile
  end
end

class User < ActiveRecord::Base
  before_validation :strip_profile_fields

  def strip_profile_fields
    profile.each_value { |v| v.strip! if v.respond_to?(:strip!) }
  end
end

class BugTest < Minitest::Test
  def test_saving_with_empty_string
    User.create!(profile: { special_property: "", working_property: "hello  " })

    assert_equal 1, User.count
  end
end

Commenting Oj.optimize_rails will make the test pass. I lacks the Oj internal knowledge to know what could have changed.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 29 (16 by maintainers)

Most upvoted comments

Released.

I did update the docs so either will work. Maybe better to just remove one of them though.

Value cache, like key caching reduces the number of Ruby objects created if the values are expected to occur more than once. Take for example status field what has 3 different values or a log entry where the log level has discrete values. Reducing the Ruby object creation reduces memory use as well as time.

That’s interesting. I wa using Ruby 3.0.2. I’ll try 2.6.7 and figure out why they would be different. Thanks for the example. Will look into it tonight.

Released v3.13.3 that should take case of this.

Oh, sorry, Oj.default_options = {cache_keys: false, cache_str: -1}