Skip to content

Can't set custom non-db attributes using ActiveRecord::Base#[]= #4583

mptre opened this Issue Jan 21, 2012 · 8 comments

8 participants

mptre commented Jan 21, 2012

This is probably not classified as an issue but I did notice a change in behavior after upgrading a Rails app from 3.1 to the newly released 3.2 version.

After running my test suite lots of errors occurred while trying to set a custom non-db attribute value using the ActiveRecord::Base#[]= method. See example below:

class User < ActiveRecord::Base
  # custom non-db attribute
  attr_accessor :activated

  before_save -> { self[:activated] = true if token? && !activated_at? }

  def activated?

The before_save lamba will throw the follwing exception:

ActiveModel::MissingAttributeError: can't write unknown attribute `activated'

Was this change of behavior intended with the 3.2 release?

Any clarity into this matter would be much appreciated!

deltadd commented Jan 23, 2012

Same issue.


Same issue here. Must have changed.


Triggers this issue in my gem rocket_tag. My issue is tracked here


My error manifests itself in the following way

class Foo < ActiveRecord::Base
    def bar=v
        @bar = v
end :bar => 10

which used to work in Rails 3.1 though according to a close reading of the doc it should not have worked.

new(attributes = nil) {|self if block_given?| ...}

New objects can be instantiated as either empty (pass no construction parameter) or 
pre-set with attributes but not yet saved (pass a hash with key names matching the 
associated table column names). In both instances, valid attribute keys are determined 
by the column names of the associated table — hence you can‘t have attributes that
aren‘t part of the table columns.

Seems to stem from this commit

Ruby on Rails member

The example in the issue description should no longer work but the example given by @bradphelan should work as he's using a virtual attribute. /cc @jonleighton do you agree?

Ruby on Rails member

@josevalim I cannot repro @bradphelan's issue with the following:

gem 'rails', '3.2.0'
require 'active_record'

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')

ActiveRecord::Schema.define do
  create_table :posts

class Post < ActiveRecord::Base
  attr_accessor :foo

p => "bar").foo

Maybe @bradphelan can help us with steps to reproduce for that.

Regarding the original issue, I should have added a deprecation I guess - just didn't really think to. I will add a deprecation to 3-2-stable.

fredngo commented Jul 27, 2012

So, moving forward, what is the correct way to write virtual attributes that are not DB-backed? I'm encountering this deprecation warning when working with virtual attributes.

mptre commented Jul 29, 2012

The following snippet works for me without any deprecation warnings. Currently running Rails 3.2.6.

class User < ActiveRecord::Base
  attr_accessor :activated

  before_save -> { self.activated = true if changed? }
@nickveys nickveys referenced this issue in ErwinM/acts_as_tenant Feb 18, 2014

Rails 3.2 write_attribute fix #2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.