Question

I thought I understood attr_* and the shorthand notation for map(&:name.to_proc).join(' '), but I ran across this today.

Why does setting attr_accessor keep my from being able to write something like NaughtyWord.all.collect(&:word) and instead require me to write out a much longer NaughtyWord.all.collect{|naughty_word| naughty_word["word"]}

class NaughtyWord < ActiveRecord::Base
  attr_accessor :word, :must_review

  validates_presence_of :word

  def self.regex_filter
    words = NaughtyWord.all.collect(&:word).join("|")
  end
end

#irb(main):014:0> NaughtyWord.all.collect(&:word)
#  NaughtyWord Load (0.4ms)  SELECT `naughty_words`.* FROM `naughty_words` 
#=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]

#irb(main):024:0> NaughtyWord.last
#  NaughtyWord Load (0.3ms)  SELECT `naughty_words`.* FROM `naughty_words` ORDER BY `naughty_words`.`id` DESC LIMIT 1
#=> #<NaughtyWord id: 11, word: "word", must_review: true>

#irb(main):025:0> NaughtyWord.last.word
#  NaughtyWord Load (0.6ms)  SELECT `naughty_words`.* FROM `naughty_words` ORDER BY `naughty_words`.`id` DESC LIMIT 1
#=> nil

# irb(main):026:0> NaughtyWord.last["word"]
# NaughtyWord Load (0.6ms)  SELECT `naughty_words`.* FROM `naughty_words` ORDER BY `naughty_words`.`id` DESC LIMIT 1
# => "word"

#irb(main):030:0> NaughtyWord.all.collect{|naughty_word| naughty_word["word"]}
# NaughtyWord Load (0.6ms)  SELECT `naughty_words`.* FROM `naughty_words` 
#=> ["word", "word", "word", "word", "word", "word", "word", "word", "word", "word", "word"]

Everything works if I comment out the attr_accessor line

Was it helpful?

Solution

I think you want to use attr_accessible instead of attr_accessor. The first is a Rails method to white label for mass assignment attributes so it's possible to use something like User.new params[:user] in your controller. The second one is plain Ruby, it's a helper to create both the read and write (aka getter and setter) methods for a given instance variable.

So what you are doing with attr_accessor is actually overriding the attribute accessor method made by ActiveRecord and that's why it returns nil.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top