Question

I have a Rails engine namespaced Manager which has a Wine model (Manager::Wine).

The app that mounts the engine also has a Wine model which isn't namespaced, but inherits from Manager::Wine (see below). The problem I'm having is that the mounted engine has a find_model method that I want to call to get the instance for the app's controller to utilize; however calls to Wine.find_whatever actually return the Manager::Wine instead of the main app's Wine model - and thus certain methods that exist in Wine aren't accessible.

Is there a way to specify that a class shouldn't be parsed within the current namespace?

examples:

1) Within the Engine, calls to Wine.find_whatever returns Manager::Wine (as per the default behaviour)

2) Within the Engine, calls to Wine.top_level.find_whatever returns the object in Wine instead of Manager::Wine.


App's Wine class:

class Wine < Manager::Wine

    searchable do
        text :full_name, default_boost: 2, stored: true
        text :description, stored: true
        text :category_name, stored: true
        text :oak_status, stored: true
        text :blend_status, stored: true
        text :sweetness_description, stored: true
        text :sweetness_descriptor, stored: true
        text :body, stored: true
        boolean :stocked, using: :stocked?, stored: true
        boolean :available, using: :available?, stored: true
        boolean :publish_on_website, stored: true
    end

    def full_name
        args = args.merge({show_year: false}) if hide_year
        super args
    end

    def available?
        publish_on_website and publish_on_pos and super
    end

    def oak_status
        oaked? ? "oaked" : "unoaked"
    end

    def blend_status
        blend? ? 'blends' : ''
    end

end

Engine's find_model code (which is called via super in main app):

def find_model(args={})
    m = controller_name.classify
    find_by_attribute = args[:find_by].to_sym rescue :id
    with_attribute = args[:with] || params[:id]
    render_error = args[:render_error]
    render_error = true if render_error.nil?
    obj = "@#{ m.downcase }#{ 's' if args[:as_collection] }"
    e = "#{ obj } = #{ m }"
    e << ".includes(#{ args[:includes] })" if args[:includes]
    e << ".where('#{ find_by_attribute } = ?', \"#{ with_attribute.to_s.gsub('"', '\"') }\")"
    e << ".select(#{ args[:selects] })" if args[:selects]
    e << ".first" unless args[:as_collection]
    eval e
    eval "render_status(404) and return false if render_error and #{ obj }.#{ args[:as_collection] ? :empty : :nil }?"
    true
end
Was it helpful?

Solution

I figured out a solution. Regular models inherit from ActiveRecord::Base, so I modified my find_model method to allow for an override.

e = "#{ obj } = #{ 'ActiveRecord::Base::' if args[:use_activerecord_base] }#{ m }"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top