About the Rails route namespace - ruby-on-rails

In my Rails app,I have a controller /app/api/mem_controller.rb
class MemController < AplicationApiController
before_filter :mem_login?
def follows
_mem = MemAccount.find(params[:id])
render json: {
:items=> _mem.follow_mems.limit(page_size).offset(page * page_size),
:count=> _mem.follow_mems.length
}.as_json(:methods=>['avatar_url'])
end
end
I add a config in application.rb
config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]
My route is:
namespace :api do
get "mem/:id/follows" => 'mem#follows'
end
Now I want the route is /api/mem/1/follows.
But this raise error:
uninitialized constant Api
If I take out the namespace wrapper,/mem/1/follows will do work.
Then I want to know how can I realize /api/mem/1/follows throuth the route keywords namespace,I need the api prefix to avoid the conflict.
I don't want to place the api folder under /app/controller/

yes sure, because you are using namespace.
try this:
class Api::MemController < AplicationApiController
...
end
and that controller MemController should be:
app/controllers/api/mem_controller.rb
if you don't want to create sub-folder, then you should use scope instead of namespace in routes.rb, and in that case you can keep your MemController without changing (I mean you don't need to add Api::)
scope '/api' do
end
more explanation: http://guides.rubyonrails.org/routing.html

Related

Rails 5: Encapsulating route files

I'm refactoring my companies routes file following this SO post to look like the following.
config/application.rb
module YourProject
class Application < Rails::Application
config.autoload_paths += %W(#{config.root}/config/routes)
end
end
config/routes/admin_routes.rb
module AdminRoutes
def self.extended(router)
router.instance_exec do
namespace :admin do
resources :articles
root to: "dashboard#index"
end
end
end
end
config/routes.rb
Rails.application.routes.draw do
extend AdminRoutes
end
However much of our newer RoR code we put into appsules, which are self contained little pieces of the application that contain their own controllers, models, serializers, etc, and someone mentioned how nice it would be if they also contained their own routes. The path to that would look like the following
/appsules/#{appsule_name}/routes.rb
But when I look at the config.paths in my application.rb I don't see any paths pertaining to the appsules directory. Is this possible to read in routes files in that fashion?
Are you updating the autoload path to use the new folder structures? Something like:
module YourProject
class Application < Rails::Application
config.autoload_paths += %W(
#{config.root}/config/routes
#{config.root}/appsules/appsule1_name/routes.rb
#{config.root}/appsules/appsule2_name/routes.rb
)
end
end
If you want them added dynamically, you should be able to iterate the appsule directory and add these files dynamically to the autoload path.

Ruby route for custom controller

So I want when I access: site.com/panel to look into /app/controller/panel/index_controller.rb
Before I start I'm new to ruby, I started a couple hours ago
So in my routes.rb I have this
namespace :panel do
root 'index#index'
resources :index
end
And I created a file called index_controller.rb in /app/controller/panel/index_controller.rb which looks like this
class IndexController < ApplicationController
def index
#foo = "Foo"
end
end
Now when I go to site.com/panel I get this: superclass mismatch for class IndexController
What I did wrong?
Also can I setup different views and layout here to use for the controllers inside /app/controller/panel/*_controller.rb
replace this
class IndexController < ApplicationController
with
class Panel::IndexController < ApplicationController
update:
to automatically generate namespaced controller you can use rails build in generator like this
rails g controller panel/users
this will generate Panel::Users < ApplicationController controller under app/controllers/panel/users_controller.rb
Since you've namespaced the index resource routes within panel, you'll need to prefix your IndexController declaration to reflect this:
# app/controllers/index_controller.rb
class Panel::IndexController < ApplicationController
Then, you can similarly reflect the namespace in your filesystem in order to get Rails to properly invoke the correct views:
/app/views/panel/index/index.html.erb
/app/views/panel/index/show.html.erb
... etc
A note: the Rails convention is that routes that are declared as resources should be named plural, as this denotes an entirely resourceful class. Thus, according to this paradigm, index should actually be indexes. However, I suspect you may mean to use a singular route, in which case the declaration would be as follows:
namespace :panel do
resource :index
end
Which creates the following singular routes (which may conform better to what you're trying to accomplish):
panel_index POST /panel/index(.:format) panel/indices#create
new_panel_index GET /panel/index/new(.:format) panel/indices#new
edit_panel_index GET /panel/index/edit(.:format) panel/indices#edit
GET /panel/index(.:format) panel/indices#show
PUT /panel/index(.:format) panel/indices#update
DELETE /panel/index(.:format) panel/indices#destroy

Add a Rails controller from a gem

I am developing a rubygem specifically for Rails applications and I want to add a controller from my gem so that it will be available on the Rails app(Similar to what devise does with RegistrationsController, SessionsController).
On the gem side:
I've tried adding the following
app/controllers/samples_controller.rb
class SamplesController < ApplicationController
def index
.
.
end
end
And then on my rails routes add it either as:
match 'route' => 'samples#index'
or
resources :samples
Clearly I got something wrong over there but I have no idea what is it? Do I need to explicitly require my SampleController somewhere or an initializer on the app?
Right now I am getting this error when accessing the route
uninitialized constant SamplesController
Thanks :)
Let's assume your gem is called MyGem and you have a controller called SamplesController that you want to use in the app. Your controller should be defined as:
module MyGem
class SamplesController < ApplicationController
def whatever
...
end
end
end
and in your gem directory it should live at app/controllers/my_gem/samples_controller.rb (not under the lib folder).
Then create engine.rb in your gems lib/my_gem folder with code
module MyGem
class Engine < Rails::Engine; end
end
You can write routes inside your gem by writing creating routes.rb in config folder with code
# my_gem/config/routes.rb
Rails.application.routes.draw do
match 'route' => 'my_gem/samples#index'
end
Final structure something like this
## DIRECTORY STRUCTURE
#
- my_gem/
- app/
- controllers/
- my_gem/
+ samples_controller.rb
- config/
+ routes.rb
- lib/
- my_gem.rb
- my_gem/
+ engine.rb
+ version.rb
+ my_gem.gemspec
+ Gemfile
+ Gemfile.lock
Thats it.
First of all you have a typo in your code: AppicationController should be ApplicationController.
Then, you're not following the Rails naming conventions (plural for resources etc.):
In your routes it would have to be either resources :samples or resource :sample.
Your controller class should be class SamplesController and
the filename of the controller should be samples_controller.rb.
Follow the conventions and you should be fine.
to set up your route, create a routes.rb file in the config directory of your project. To have it match on the sample route, do the following:
config/routes.rb
Rails.application.routes.draw do
<resource definition here>
end
app/controllers/samples_controller.rb
module Samples
class SamplesController < ApplicationController
def index
.
.
end
end
end
Remember to include the module in the application controller
include 'samples'
Have you looked at this site:
http://coding.smashingmagazine.com/2011/06/23/a-guide-to-starting-your-own-rails-engine-gem/

Routes, gems and generators

I have written a gem with an install generator. I would like to use this generator to add routes to the config/routes.rb file, much in the same way as the devise gem does by adding devise_for :model_name. Therefore, I need to know how to:
Make a method (like devise_for) available within the scope of routes?
Ok I've figured it out. To add to the routes file you can use the method route in the generator. I have accomplished this by adding the following to my install_generator.rb file:
def setup_routes
route("add_gem_routes")
end
Note that I am in fact calling a method, which can be added to the scope of routes by defining it in the following namespace:
module ActionDispatch::Routing
class Mapper
def add_gem_routes
#routing code...
end
end
end

How can I make routes from a Rails 3 engine available to the host application?

I have a Rails 3 application with several engines containing additional functionality. Each engine is a separate service that customers can purchase access to.
I am, however, having a problem with routes from the engines that aren't readily available to the controllers and views.
controller:
class ClassroomsController < ApplicationController
..
respond_to :html
def index
respond_with(#classrooms = #company.classrooms.all)
end
def new
respond_with(#classroom = #company.classrooms.build)
end
..
end
app/views/classrooms/new.html.haml:
= form_for #classroom do |f|
..
f.submit
config/routes.rb in engine:
MyEngineName::Engine.routes.draw do
resources :classrooms
end
config/routes.rb in app:
Seabed::Application.routes.draw do
mount MyEngineName::Engine => '/engine'
...
end
lib/my_engine_name.rb in engine:
module MyEngineName
class Engine < ::Rails::Engine
end
end
attempting to go to /classrooms/new results in
NoMethodError in Classrooms#new
Showing app/views/classrooms/_form.html.haml where line #1 raised:
undefined method `hash_for_classrooms_path' for #<Module:0x00000104cff0f8>
and attempting to call classrooms_path from any other view results in the same error.
I can, however, call MyEngineName::Engine.routes.url_helpers.classrooms_path and get it working. I'm thinking I might have defined the routes wrong, but can't find another way that works.
Tried running the app with both Passenger (standalone and Apache module) and WEBrick (rails server). Using latest Rails from Git (7c920631ec3b314cfaa3a60d265de40cba3e8135).
I had the same problem, and found this in the documentation:
Since you can now mount an engine inside application’s routes, you do not have direct access to Engine‘s url_helpers inside Application. When you mount an engine in an application’s routes, a special helper is created to allow you to do that. Consider such a scenario:
# config/routes.rb
MyApplication::Application.routes.draw do
mount MyEngine::Engine => "/my_engine", :as => "my_engine"
get "/foo" => "foo#index"
end
Now, you can use the my_engine helper inside your application:
class FooController < ApplicationController
def index
my_engine.root_url #=> /my_engine/
end
end
Change config.routes in your engine to:
Rails.application.routes.draw do # NOT MyEngineName::Engine.routes.draw
resources :classrooms
end
The way you have it, the routes are only available in the MyEngineName::Engine namespace and not in the rest of the host rails application.
There used to be a blog post with more info, but unfortunately it is no longer available:
http://blog.loopedstrange.com/modest-rubyist-archive/rails-3-plugins-part2-writing-an-engine
For me also help to add
require 'engine' if defined?(Rails)
to my main gem file (lib/.rb).
Good example - https://github.com/mankind/Rails-3-engine-example/blob/master/lib/dummy.rb

Resources