-
-
Save dhh/2492118 to your computer and use it in GitHub Desktop.
class ActionDispatch::Routing::Mapper | |
def draw(routes_name) | |
instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb"))) | |
end | |
end | |
BCX::Application.routes.draw do | |
draw :api | |
draw :account | |
draw :session | |
draw :people_and_groups | |
draw :projects | |
draw :calendars | |
draw :legacy_slugs | |
draw :ensembles_and_buckets | |
draw :globals | |
draw :monitoring | |
draw :mail_attachments | |
draw :message_preview | |
draw :misc | |
root to: 'projects#index' | |
end |
why something like "draw" method doesn't get into core?
how about defining the routes in the controllers, that could be done in a similar manner.
@joaomilho See DHH's comment above. The draw
method should be in master soon.
@nicholaswyoung /me facepalm
@brainopia probably in anticipation of moving it to core. I don't know relative paths would work from a gem to your project where the file would actually be held. Or if he actually had this abstracted into a lib rather than sitting in the top of his rails.config. Prolly just makes it obvious where the path is going to be referenced so that the code can sit anywhere.
sexy as, thanks.
Very nice indeed. I slightly updated it to keep namespaced routes in subfolders: https://gist.github.com/2507892. Works great for me.
draw :projects # => config/routes/projects.rb
namespace :admin do
draw :projects # => config/routes/admin/projects.rb
end
@azendal since you seem to be missing the implicit point: organizational changes for files has known value. It's an 'ergonomic' improvement that aides the mind in the workflow. Your chiding misrepresents that value.
yes i already commented that its an organizational improvement, and that from that point is really good.
"@azendal Highly recommend you read Martin Fowler's "Clean Code". Perhaps when you understand the concept of seperating things that change from things that don't, you'll understand this small optimisation has value."
Gavin Laking
"This trips my rant bit. "Value" compared to what? The 800 outstanding
Issues in github/rails? Who says he doesn't understand that? And I'd wish
people would stop worshiping other people books like they're the solution
to cancer and a something to beat other peoples opinions with."
Christopher H. Laco
Thx Christopher.
Gavin
... did you really read the book? lets assume you did.
naming methods should reveal intention right?
def draw(routes_name)
instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb")))
end
since when draw is an alias for loading and evaluating a file?
Chapter 2 on the book you recommend Meaningful Names i still assume you read the book.
class ActionDispatch::Routing::Mapper
def draw(routes_name)
ok so we patched the class here nice API right?
BCX::Application.routes.draw do
draw :api
draw :account
draw :session
draw :people_and_groups
draw :projects
draw :calendars
draw :legacy_slugs
draw :ensembles_and_buckets
draw :globals
this is called sequence, but as you see we use the same draw method called inside a draw method and we do this many times
instead of passing an array.
or even better:
Remember that thing convention over configuration?
how about
Application.routes.load :all
now this is something that reveals a good intention.
instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb")))
instance_eval reveals that the code inside assumes that its on the class forcing the developer to know in advance
about this constrain, that once into the rails core you will have to read the documentation.
Other possible problems. if you want to avoid listing manually all the files that need to be included, how do you do this
in the right order? something i don't have an answer for right now without putting more stuff on the API.
with all this, i hope you think i know what i am talking about?
Also http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882
Clean Code is a book from Robert C. Martin.
Looks great.
I agree with @kulesa that there should be some nesting functionality.
Probably by namespace, or else by successive draw
. I mean if in routes.rb
there is draw :admin
and in routes/admin.rb
there is draw :usersites
, it could look up routes/api/usersites.rb
instead of routes/usersites.rb
.
Thanks
Another slight update to @kulesa's solution for namespace
support. This adds support for scope
, in addition to namespace
routes ( see https://gist.github.com/2507892 ):
class ActionDispatch::Routing::Mapper
def draw(routes_name)
instance_eval(File.read(Rails.root.join("config/routes#{@scope[:path]}", "#{routes_name}.rb")))
end
end
seems like routes get cached in development env, any advice on how to avoid it?
@freegenie +1
@freegenie +1
@freegenie +1
any workaround to that?
To get paths reloaded in dev mode, I ended up using in application.rb
:
config.paths['config/routes'].unshift *Dir[Rails.root.join('config/routes/*.rb')]
Not the best line of code ever but does the job..
@apneadiving Thanks! Additionally I had to wrap the code in config/routes/*.rb files by a "ApplicationName::Application.routes.draw do" block otherwise I get undefined method `resources'.
@apeadiving @applicat I think it might be better form to throw that line into config/environments/development.rb rather than application.rb, since it is unclear to me how this would affect the loading order of the routes. This way, at the very least, in production the @dhh 's 'draw' method would allow your routes to be defined in the order that you declare each draw method.
@logical42 You could make a diff of "rake routes" results on your terminal before and after to see the affect on loading order.
But after some Rails updates my application is now on Rails 3.2.13 and don't need these hacks anymore (path unshifting and "ApplicationName::Application.routes.draw do" block).
Reload just seem to work through Rails now.
This is an awesome feature. Is it in master yet? I'm unable to find it in the code nor is it documented.
this fails for RAILS 4:
config.paths['config/routes'].unshift Dir[Rails.root.join('config/routes/.rb')]
Any thoughts?
@rubytastic you can always force Rails to reload routes from your middleware!
class RoutesReloader
def initialize(app)
@app = app
end
def call(env)
Rails.application.reload_routes!
@app.call(env)
end
end
# in config/environments/development.rb
config.middleware.use RoutesReloader
Enjoy reloading routes on every request!
@shime it works, but makes application very slow:
time = Benchmark.measure { 10.times { Rails.application.reload_routes! } }
=> #<Benchmark::Tms:0x007fb4809b3840
@cstime=0.0,
@cutime=0.0,
@label="",
@real=4.654909,
@stime=0.020000000000000018,
@total=4.640000000000004,
@utime=4.6200000000000045>
It adds more than 450 ms for every request.
Hopefully there is still other possible solution: we can use ActiveSupport::FileUpdateChecker
for tracking changes in config/routes directory:
class RoutesReloader
ROUTES_PATH = Dir.glob("config/routes/*.rb")
def initialize(app)
@app = app
@routes_reloader = ActiveSupport::FileUpdateChecker.new(ROUTES_PATH) do
Rails.application.reload_routes!
end
end
def call(env)
@routes_reloader.execute_if_updated
@app.call(env)
end
end
@sharipov-ru, it's much better but I'd like to add a small improvement:
ActiveSupport::FileUpdateChecker.new([], 'config/routes' => 'rb') do ... end
This way it should find new files as well.
Guys, it's very outdated. You now can just require other routes files without monkey patching, they just have to repeat the Rails.application.routes.draw do
:
config/routes.rb:
Rails.application.routes.draw do
load Rails.root.join("config/routes/dev.rb")
#...
end
config/routes/dev.rb:
Rails.application.routes.draw do
scope "dev" do
# ...
end
end
No dynamic reloading tho, probably @sharipov-ru's reloader still works.
Anyone found a nice solution on how to seperate route files and still make them auto reloading during development?
Edit: Going now with a combination of the mentioned solutions...
# config/environments/development.rb
class RoutesReloader
def initialize(app)
@app = app
@routes_reloader = ActiveSupport::FileUpdateChecker.new([], 'config/routes' => 'rb') do
Rails.application.reload_routes!
end
end
def call(env)
@routes_reloader.execute_if_updated
@app.call(env)
end
end
Rails.application.routes.draw do
...
config.middleware.use RoutesReloader
end
# config/routes.rb
Rails.application.routes.draw do
routes = [:admin_routes, :admin_routes_old, :public_routes, :api_routes]
routes.each{ |route_file| load Rails.root.join("config", "routes", "#{route_file}.rb") }
end
How can I use concern with this conven?
https://guides.rubyonrails.org/routing.html#routing-concerns
concern :commentable do
resources :comments
end
resources :messages, concerns: :commentable
can I do this?
draw :api, concerns: :commentable
or there another way?
austinthecoder nothing, and its irrelevant to the point of putting them into other files
fullybaked, that is right ;). its just organizational change, nothing else