Routes, gems and generators - ruby-on-rails

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

Related

How can i put app subdir classess under a namespace

I want to namespace all my classes put in a app/cms folder under Cms module. So, let's say i have a following file:
# /app/cms/types/post.rb
class Cms::Types::Post
end
Rails assumes that class definition of a file put in this dir should be Types::Post instead of Cms::Types::Post. So, when calling Cms::Types::Post.new, rails throws
LoadError (Unable to autoload constant Types::Post, expected /Users/xxx/workspace/personal/xxx/app/cms/types/post.rb to define it)
How can i namespace all these files under Cms?
I'm on rails 5.2.0
What is Post? I mean, what is the nature of Post? For instance, is it a service?
If it were a service (for example), I would put it in:
/app/services/cms/types/post_service.rb
And then define it as:
class Cms::Types::PostService
end
If it were a type (which seems like it might be a problematic name), then I would define it in:
/app/types/cms/post_type.rb
and define it as:
class Cms::PostType
end
In other words, name the directory under /app using the description of what Post is (just like rails does with models, controllers, etc.) and then add the description (in the singular form) to the end of your definition (rails does this with controllers, helpers, and mailers, but not with models).
Normally, when you use namespace you need to have your file structure as below:
module Cms
module Types
class Post
end
end
end
EDIT: Also to make it, autoload the path, you could add the below line in your application.rb:
config.autoload_paths << Rails.root.join('app', 'cms').to_s

How to add method that can be used in routes to Gem?

I am building a gem for Rails and would like to make a method available to the routes of the Rails app that uses my gem.
Basically, I want whoever uses my gem to be able to say
websockets_for :messages
which will create a bunch of routes for them. I am unsure where to define that method so that it's available in the routes file.
The method looks something like this:
def websockets_for(resources)
get "/#{resources}", to: "#{resources}#index", as: resources
end
It's basically a helper method I want to make available to generate routes.
I have only found this: https://www.pgrs.net/2007/09/28/add-routes-with-a-rails-plugin-or-gem/
It seems pretty old (from 2007), and I don't think ActionController::Routing is still being used. What's the best way to do this?
Based on Frederick Cheung's comment, I was able to implement this:
require 'action_dispatch/routing'
require 'active_support/concern'
module ActionDispatch::Routing
class Mapper
def websockets_for(resource, &block)
# here, use methods like get, match, etc
get "/#{resources}", to: "#{resources}#index", as: resources
end
end
end
It works! Now, the method websockets_for is available in a Rails app's routes if the gem is installed.

Rails: How to define routes when include a module

I want to define a new routes when a module be included, I try the following code but it didn't work:
included do
ActionDispatch::Routing::RouteSet.draw do
get "test" => "public#test"
end
end
Please correct me, thanks!

About the Rails route namespace

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

How to define own routing helpers in rails 3?

I use polimorphic_path and it some buggy. This method require some route helper that not defined. How can I define (like regular method) own route helper which will be used like "model_name_path, model_name_url etc"?
This solution worked for me.
Add this code to the end of config/routes.rb file. Make sure to replace MyApp with your application's name.
MyApp::Application.routes.named_routes.module.module_eval do
def model_name_path(*args)
# Your code here
end
def model_name_url(*args)
# Your code here
end
end
MyApp::Application.routes.named_routes.instance_eval do
#helpers += [:model_name_path, :model_name_url]
end
These custom methods will be available in controllers, views and tests.
I know one possible answer for _path, but the same isn't working for me for _url. Anybody know why?
# at the bottom of config/routes.rb
module ActionView::Helpers::UrlHelper
def model_name_path model, args={}
# your implementation
end
end

Resources