CodeSmith
CodeSmith

Reputation: 2233

Rails NameError uninitialized constant (Model and Namespace Collision)

I have a model named Organization. It is defined in app/models/organization.rb

class Organization < ActiveRecord::Base
... code
end

I have a controller named Admin::Organization::ActivitiesController. It is defined in app/controllers/admin/organization/activities_controller.rb. It has an index action in it.

class Admin::Organization::ActivitiesController < ApplicationController
  def index
    @organization = Organization.new
    ... more code
  end
end

I get the following message when I execute the above index action:

NameError in Admin::Organization::ActivitiesController#index
uninitialized constant Admin::Organization::ActivitiesController::Organization

For some reason it's scoping the Organization model inside the controller class. If I change the index method to use

@organization = ::Organization.new

then it works fine.

This behavior doesn't seem to appear in a pry console. If I add a binding.pry call in the index method, then I can call Organization.new or ::Organization.new from the command line it works fine.

Every other model in the app works correctly and doesn't have this weird behavior. I didn't write the code originally so I'm trying to figure out what is going on.

I think it might have something do with a namespace in the routes.rb file. There is a namespace that uses the organization word.

namespace :admin do
  namespace :organization
    resources :activities
  end
end

As a test, I changed the namespace to :organizations, and I was able to get things to work without needing ::. Is there a way to structure things, or a routing setting, so we can have a namespace of :organization that doesn't interfere with the model named Organization?

Upvotes: 6

Views: 1800

Answers (1)

Ashik Salman
Ashik Salman

Reputation: 1879

If you just want to make the path correct, you don't require to put the activities controller under admin/organization namespace folder. Another option would be like using scope instead of namespace.

# app/controllers/activities_controller.rb
class ActivitiesController < ApplicationController
  def index
    @organization = Organization.new
    ... more code
  end
end

Now configure routes,

# config/routes.rb
scope 'admin/organization', path: 'admin/organization'  do
  resources :activities
end

This will produce routes like this,

Prefix Verb   URI    Pattern                                      Controller#Action

activities    GET    /admin/organization/activities(.:format)     activities#index
              POST   /admin/organization/activities(.:format)     activities#create
......

Upvotes: 2

Related Questions