5

I have

class Fruit < ActiveRecord::Base
    includes Skin
end

and the mixin module

module Skin
    def initialize
        self.skin = "fuzzy"
    end
end

I want it so that

>> Fruit.new
#<Fruit skin: "fuzzy", created_at: nil, updated_at: nil>

3 Answers 3

5

Use the ActiveRecord after_initialize callback.

module Skin
  def self.included(base)
     base.after_initialize :skin_init
  end

  def skin_init
    self.skin = ...
  end
end

class Fruit < AR::Base
  include Skin
  ...
end
Sign up to request clarification or add additional context in comments.

5 Comments

Doesn't seem to work for me. Would it matter if Fruit was in a namespace? i.e. Food::Fruit
@Axsuul - see my edit. The after_initialize callback works a bit differently for Rails 3. Code updated now. Give it a try.
Thanks, that worked. Sorry, forgot to mention I'm on Rails 3. Ah, so much hacking that Rails needs =/
Bonus Question: if I do Fruit.create(:skin => "smooth"), it does #<Fruit skin: "fuzzy">. How do I make it so that create override the mixin's value?
Change the code in the module to self.skin ||= "fuzzy". That should do the trick :)
0

Try defining the reader/writer for skin instead:

module Skin
  def skin
    @skin||="fuzzy"
  end
  attr_writer :skin
end

class Fruit
  include Skin
end

f=Fruit.new
puts f.skin # => fuzzy
f.skin="smooth"
puts f.skin # => smooth

Edit: for rails, you'd probably remove the attr_writer line and change @skin to self.skin or self[:skin], but I haven't tested this. It does assume that you'll access skin first in order to set it, but you could get around this by coupling it with a default value in the database. There's probably a rails specific callback that will provide a simpler solution.

Comments

0

I think you just need to call super before you make any adjustments:

module Skin
  def initialize(*)
    super
    self.skin = "fuzzy"
  end
end

class Fruit < ActiveRecord::Base
  include Skin
end

Untested.

2 Comments

You shouldn't override initialize on ActiveRecord objects. Rails does not guarantee initialize is called in all situations. See here: blog.dalethatcher.com/2008/03/…
Interesting, thanks. I don't personally use ActiveRecord, but this is good to be aware of :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.