Forum: Rails Engines development Problem with assocations

Posted by Peter Bex (Guest)
on 2007-02-26 16:17
(Received via mailing list)
Hi there,

We're having some problems with some code in our Engine:

This code, in our _application's_ (not the engine's) user_controller
goes wrong:
  current_company = current_user.employees[0].company
it raises an exception that the method 'company' does not exist for
the instance of Employee current_user.employees[0].

Employee is defined in the application itself, and User is defined in
the engine.  Employee belongs_to :company and Company has_many 
:employees.

This works fine:
  current_company = Company.find(current_user.employees[0].company_id)

To check it's not because the user object is instantiated in code from 
our
engine, I tried this:
  current_company = User.find(current_user.id).employees[0].company
This didn't work either.  Gives the same error (unknown method company 
for
Employee)

Any ideas what could cause this?  (or if it could be engines-related at 
all)

Regards,
Peter Bex
Solide ICT - http://www.solide-ict.nl
Posted by James Adam (Guest)
on 2007-02-26 16:35
(Received via mailing list)
The engines plugin doesn't do any messing with ActiveRecord's
associations - so long as your classes are both loaded, I can't see
any reason why this would result from having the engines plugin
installed....
Posted by Peter Bex (Guest)
on 2007-02-28 11:29
(Received via mailing list)
On Mon, Feb 26, 2007 at 04:15:45PM +0100, Peter Bex wrote:
> Employee is defined in the application itself, and User is defined in
> the engine.  Employee belongs_to :company and Company has_many :employees.
> 
> This works fine:
>   current_company = Company.find(current_user.employees[0].company_id)

It gets weirder.  I can ask Dependencies if the Employee class is loaded
with Dependencies.send(:qualified_const_defined?, "Employee") and it 
says it
isn't.  If I then ask for current_user.employees[0].class.id and for
Employee.id, then it returns different values!

It looks like the Rails unloading mechanism doesn't handle dependencies
right in combination with different load paths or with engines, somehow.
I'll continue my investigations.  This might be related to the
'lib folders and application controllers' thread on engines-users.

Regards,
Peter Bex
Solide ICT - http://www.solide-ict.nl
Posted by Peter Bex (Guest)
on 2007-02-28 16:20
(Received via mailing list)
On Wed, Feb 28, 2007 at 11:30:06AM +0100, Peter Bex wrote:
> It gets weirder.  I can ask Dependencies if the Employee class is loaded
> with Dependencies.send(:qualified_const_defined?, "Employee") and it says it
> isn't.  If I then ask for current_user.employees[0].class.id and for
> Employee.id, then it returns different values!
> 
> It looks like the Rails unloading mechanism doesn't handle dependencies
> right in combination with different load paths or with engines, somehow.
> I'll continue my investigations.  This might be related to the 
> 'lib folders and application controllers' thread on engines-users.

Problem solved!  In my model, I used:

require RAILS_ROOT + "/vendor/plugins/myplugin/app/models/user"

class User < ActiveRecord::Base
end

This means Rails does not mark the User class as unloadable, which means 
it
does not get unloaded on the next request.  Some classes that User 
depends
on (like Employee), do get reloaded, meaning the class that the old User
pointed to is some kind of "empty shell", a class which doesn't exist
anymore.  The new Employee class has all the right functions, but the 
old one
that User still points to doesn't.

At least, that's my understanding of how it works.  The solution was

require_dependency RAILS_ROOT + 
"/vendor/plugins/myplugin/app/models/user"

class User < ActiveRecord::Base
end

James, could you please add some kind of warning to the engines
documentation that any classes you use in an engine have to be loaded
with require_dependency instead of require, because otherwise it does
weird stuff?

Regards,
Peter Bex
Solide ICT - http://www.solide-ict.nl
Posted by Brett Walker (Guest)
on 2007-02-28 17:39
(Received via mailing list)
Son of a gun!  I spent all day ripping my app apart to provide a test
case (cause I couldn't figure out how to recreate it from scratch.
I've been posting on a similar thread on the engine-user forum).
With everything stripped out, removing a

   require 'user'

that was at the top of my controller fixed the problem.  Also
changing it to require_dependency fixed it as well.  Peter, thanks
for finding the fix!  Nice job.

James, I hope you will add this method of overriding an engine model
into the readme/docs - I think it's a better solution than using mixins.

Cheers,
Brett
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.