jeudi 26 février 2015

The correct way to do inheritance in Rails mountable engine

Today, I found a very strange issue while writing a mountable engine using Rails 3. I have the following ApplicationController in my engine:



module Marketplace
class ApplicationController < ::ApplicationController
before_filter :merge_abilities

layout 'marketplace/application'

def marketplace_current_user
Marketplace::User.find(current_user.id)
end

private

def merge_abilities
current_ability.merge(Ability.new(current_user))
end
end
end


And my User model definition is



module Marketplace
class User < ::User
devise omniauth_providers: [:facebook, :paypal]

has_one :payout_identity, class_name: "Marketplace::PayoutIdentity"
has_many :course_purchases, class_name: "Marketplace::CoursePurchase"

def has_verified_payout_identity?
self.payout_identity and self.payout_identity.receiver_id
end
end
end


After starting up the rails server, the first request to load a page will have the controller run the marketplace_current_user method correctly and load the engine's User class. However any request after the first one will given a strange NameError - "uninitialized constant Marketplace::Marketplace::User".


I tried removing the namespace in marketplace_current_user definition but it will load the main app's User class instead.


At last when I change my ApplicationController to look like this:



class Marketplace::ApplicationController < ::ApplicationController
before_filter :merge_abilities

layout 'marketplace/application'

def marketplace_current_user
Marketplace::User.find(current_user.id)
end

private

def merge_abilities
current_ability.merge(Ability.new(current_user))
end
end


Everything would work fine.


Could someone enlighten me where I got it wrong at the beginning? Was it wrong to do inheritance that way?


Aucun commentaire:

Enregistrer un commentaire