step-wise refactoring and has-one

Hi There,

Wondering if anyone has thoughts on this. Right now my User has lots of responsibilities. I want to start to move some of them from a User to a Profile (where a user has-one Profile). I don't want to do any big refactorings, so I want to take small steps so I can commit working code that I could push to master if necessary every hour or so.

I was trying to get User to delegate :bio, :website, :to => :@current_profile (real situation has a lot more complexity, but that's the first step).

Trying to figure out best approach to this because of course when factories (Factory_girl) or my code call a user, they want to call user.bio and user.bio=, so before they call I have to ensure that I have an @current_profile.

How does Ruby actually call instance variables? Does it make sense for me to def a method to overload the getter for the current_profile instance variable that looks to see if the actual instance variable exists and if not finds/creates it?

Just trying to find the best way to approach the problem. Any input much appreciated.

Best Wishes, Peter

Wondering if anyone has thoughts on this. Right now my User has lots of responsibilities. I want to start to move some of them from a User to a Profile (where a user has-one Profile). I don't want to do any big refactorings, so I want to take small steps so I can commit working code that I could push to master if necessary every hour or so.

I was trying to get User to delegate :bio, :website, :to => :@current_profile (real situation has a lot more complexity, but that's the first step).

Trying to figure out best approach to this because of course when factories (Factory_girl) or my code call a user, they want to call user.bio and user.bio=, so before they call I have to ensure that I have an @current_profile.

As an aside: if your User has_one Profile, then normally you'd just access that via User's instance method 'profile', which ActiveRecord provides. Is there a particular reason you need to use a separate instance variable to reference the profile?

How does Ruby actually call instance variables? Does it make sense for me to def a method to overload the getter for the current_profile instance variable that looks to see if the actual instance variable exists and if not finds/creates it?

AFAIK, there isn't any way to hook into the access of an instance variable. Overriding a getter method will only work if you only ever access that instance variable via the getter method and not directly; unfortunately for your case, ActiveSupport's Delegation module will generate code that accesses your @current_profile instance variable directly.

As a first attempt, I'd probably just use ActiveRecord's after_initialize hook in User to make sure I find/create a profile whenever a new User instance is made.

Not sure if that approach will play well with your factories, but then they probably ought to be creating the Profile instance explicitly anyway.

Chris

As an aside: if your User has_one Profile, then normally you’d just access that via User’s instance method ‘profile’, which ActiveRecord provides. Is there a particular reason you need to use a separate instance variable to reference the profile?

Yeah - MongoMapper. I keep on running into issues with the has_one relationship, so I’m persisting a current_profile_id as an ObjectId and I need to handle the retrieval of the profile usine a Profile.find(current_profile_id)

How does Ruby actually call instance variables? Does it make sense for me to def a method to overload the getter for the current_profile instance variable that looks to see if the actual instance variable exists and if not finds/creates it?

AFAIK, there isn’t any way to hook into the access of an instance variable. Overriding a getter method will only work if you only ever access that instance variable via the getter method and not directly; unfortunately for your case, ActiveSupport’s Delegation module will generate code that accesses your @current_profile instance variable directly.

Hmmm, OK, thanks

As a first attempt, I’d probably just use ActiveRecord’s after_initialize hook in User to make sure I find/create a profile whenever a new User instance is made.

I can’t find support for after_initialize in MM unfortunately (http://mongomapper.com/documentation/plugins/callbacks.html), but I can look for the closest possible on the MM list.

Not sure if that approach will play well with your factories, but then they probably ought to be creating the Profile instance explicitly anyway.

That’s certainly something I can do. So probably use a callback for the runtime code and just pass in the object in the factories. Seems like a way I can go - thanks!

Best WIshes,

Peter