Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: Default value for composed-of aggregate field ignored in ActiveRecord 6.1.0 #40843

Closed
mintyfresh opened this issue Dec 14, 2020 · 0 comments · Fixed by #40849
Closed

Comments

@mintyfresh
Copy link

mintyfresh commented Dec 14, 2020

Steps to reproduce

  • Create an aggregate field on a model using composed_of
  • Set a default value for the field using attribute

This was encountered when upgrading an existing application from 6.0.3.4 to 6.1.0.

Executable 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" }

  # Activate the gem you are reporting the issue against.
  gem "activerecord", "6.1.0"
  gem "sqlite3"
end

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

# 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.string :currency
  end
end

class Currency
  attr_reader :id

  def initialize(currency)
    @id = currency
  end

  def ==(other)
    other.is_a?(Currency) && other.id == id
  end
end

class User < ActiveRecord::Base
  attribute :currency, :string, default: -> { 'CAD' }

  composed_of :currency, allow_nil:  true,
                         class_name: 'Currency',
                         converter:  -> (value) { Currency.new(value) },
                         mapping:    [:currency, :id]
end

class BugTest < Minitest::Test
  def test_default_value
    assert_equal Currency.new('CAD'), User.new.currency
  end
end

Expected behavior

Attribute should have default value wrapped in aggregate class:

# Running:

.

Finished in 0.003190s, 313.5189 runs/s, 313.5189 assertions/s.

1 runs, 1 assertions, 0 failures, 0 errors, 0 skips

Actual behavior

Attribute has no default value:

# Running:

F

Finished in 0.003208s, 311.7013 runs/s, 311.7013 assertions/s.

  1) Failure:
BugTest#test_default_value [testcase.rb:52]:
Expected: #<Currency:0x00005598e7fd9320 @id="CAD">
  Actual: nil

1 runs, 1 assertions, 1 failures, 0 errors, 0 skips

NOTE: Changing the activerecord gem version to 6.0.3.4 will make this test case pass, so this appears to be a regression.

System configuration

Rails version: 6.1.0

Ruby version: 2.6.6

@mintyfresh mintyfresh changed the title Default value for composed-of aggregate field ignored in ActiveRecord 6.1.0 Regression: Default value for composed-of aggregate field ignored in ActiveRecord 6.1.0 Dec 14, 2020
@kamipo kamipo self-assigned this Dec 15, 2020
kamipo added a commit to kamipo/rails that referenced this issue Dec 15, 2020
Use `{read,write}_attribute` public API in `composed_of` because
`_read_attribute` internal API should be passed argument as a string
since 7834363.

Fixes rails#40843.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants