Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails routing and controller modules -namespacing?

I have trouble creating a module for my controller, and getting my routes to point to that module within the controller.

Getting this error:

Routing Error
uninitialized constant Api::Fb

So, this is how my routes are set up:

namespace :api do
  namespace :fb do
    post :login
    resources :my_lists do
      resources :my_wishes
    end
  end
end

In my fb_controller i want to include modules that will give me paths like this:

/api/fb/my_lists

This is some of my fb_controller:

class Api::FbController < ApplicationController
  skip_before_filter :authenticate_user!, :only => [:login]

  include MyLists # <-- This is where i want to include the /my_lists
                  # namespace(currently not working, and gives me error 
                  # mentioned above)

  def login
    #loads of logic
  end
end

The MyLists.rb file(where i define a module) is in the same directory as the fb_controller.rb.

How can i get the namespacing to point to my module inside of the fb_controller, like /api/fb/my_lists ?

like image 652
Pål Avatar asked Dec 21 '22 08:12

Pål


2 Answers

The namespace you have set up is looking for a controller class that looks like this

class Api::Fb::MyListsController

If you want to have a route that looks like /api/fb/my_lists but you want to still use the FbController instead of having a MyListsController you need to set up your routes to look like this

namespace :api do
  scope "/fb" do
    resources :my_lists, :controller => 'fb'
  end
end

In my opinion, instead of including a module MyLists in your FbController seems kind of awkward.

What I would probably do is have a module FB with a generic FbController then have MyListsController < FbController. Anyway, this is beyond the scope of your question.

The above should answer for your needs.

EDIT

From your comments, and my assumptions on what you're trying to do this is a small example:

config/routes.rb

namespace :api do
  scope "/fb" do
    post "login" => "fb#login"
    # some fb controller specific routes
    resources :my_lists
  end
end

api/fb/fb_controller.rb

class Api::FbController < ApiController
  # some facebook specific logic like authorization and such.
  def login
  end
end

api/fb/my_lists_controller.rb

class Api::MyListsController < Api::FbController
  def create
    # Here the controller should gather the parameters and call the model's create
  end
end

Now, if all you want to create a MyList Object then you could just do the logic directly to the model. If, on the other hand, you want to handle some more logic you'd want to put that logic in a Service Object that handles the creation of a MyList and its associated Wishes or your MyList model. I would probably go for the Service Object though. Do note, the service object should be a class and not a module.

like image 99
Leo Correa Avatar answered Jan 04 '23 17:01

Leo Correa


In your example, Fb isn't a namespace, it's a controller. The namespace call is forcing your app to look for a Fb module that doesn't exist. Try setting up your routes like this:

namespace :api do
  resource :fb do
    post :login
    resources :my_lists do
      resources :my_wishes
    end
  end
end

You can optionally define a new base controller for the API namespace:

# app/controllers/api/base_controller.rb
class Api::BaseController < ApplicationController
end

If you do so, your other controllers can inherit from this:

# app/controllers/api/fb_controller.rb
class Api::FbController < Api::BaseController
end

Running rake routes should give you an idea of how your other controllers are laid out. Just a warning - it's generally not recommended to have resources nested more than 1 deep (you're going to end up with complex paths like edit_api_fb_my_list_my_wish_path). If you can architect this in a simpler way, you'll probably have an easier time of this.

like image 42
Zach Kemp Avatar answered Jan 04 '23 16:01

Zach Kemp