I have a question.
I'm new on rails 4 and ruby 2 and trying to find a way to allow controllers without typing several times on ROUTES
I'm tyring to create several actions inside my controller
Here my controller on rails 4:
class Managementbla::UserController < ApplicationController
class Managementpoke::UserController < ApplicationController
...
class Managementmultiple::UserController < ApplicationController
Here my routes on rails 4:
namespace :managementbla do
resources :user
end
namespace :managementpoke do
resources :user
end
...
namespace :managementmultiple do
resources :user
end
on rails 2.3 the sintaxis was
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
On rails 4 i found this:
match ':controller(/:action(/:id(.:format)))', via: [:get, :post]
The fact that you have 500 controllers suggests serious issues with the design of your application. Whatever problem you're solving, I really, really doubt that having 500 similarly-named controllers is the best solution. Do they all perform such vastly different tasks that you need 500 distinct controllers? Forced to guess, I would say that those controllers are all very similar and whatever work they're doing could, and should, be handled by a single controller instead.
If you're determined to continue down the 500-controllers path, though, it's not hard. It seems you may have forgotten that routes.rb is just Ruby code. You can solve this the same way you'd solve any problem that requires iterating over a bunch of numbers in Ruby:
1.upto(500) do |n|
namespace :"management#{n}" do
resources :user
end
end
Don't do this, though. Take a hard look at your 500 controllers. There's got to be a better solution.
It seems like you might simplify the application by using either a route parameter or query string parameter.
If you truly need this many routes in your application, you may consider a framework that does routing more efficiently. You might take a look at Roda: http://roda.jeremyevans.net/why.html.
They claim the routing algorithmic efficiency is on order O(log n) where n is the number of routes.
Related
I want to achieve something like this: /users/14/images/88 when developing my Rails application.
There I have users URL-segment, then comes user ID, and images that belong to this user, and image ID.
I'm asking you, SO, what is the best way to design my routes? Should I keep this pattern or not?
I've read this on Ruby On Rails Routing Docs:
[ ! ] Resources should never be nested more than 1 level deep.
And this is what confuses me. Not more that 1 level deep.
So, basically, this could mean that one level could be /users/14, but I need one more level (+ /images/88). And according to best practice in designing routes this is bad idea to make more-than-one-level-nested resources.
I'm confused a bit about that.
Thanks in advance!
#config/routes.rb
resources :users do
resources :images
end
This is one level deep.
#config/routes.rb
resources :users do
resources :images do
resources :comments
end
end
This is more than one level deep.
As you can see by the quoted resource, the issue is not about inability to match the resource, but in handling the flow. For example...
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def show
#user = User.find params[:user_id]
#image = #user.images.find params[:image_id]
#comments = #image.comments
end
end
Whilst not completely out of range, it shows how confusing deep linking resources can get. You're better advocating a more streamlined approach - for example, appending comments to images & showing them through the images#show controller action.
I'm learning Ruby and Rails and trying to figure out the most correct path to go for my scenario regarding possibly namespacing as well as routing.
Say I have a 'Zoo' model as well as 'Species' model. I also need a relationship between them to tell what Species are in what Zoos (a Zoo has many Species, which will also have their own properties such as qty, location, etc)
I would like my routes to be like:
/zoo
/zoo/:id
...
/zoo/:zoo_id/species/
/zoo/:zoo_id/species/:id
...
/species
/species/:id
I have tried messing with modules, namespaces, route scopes, etc. I can't seem to get it how I'd like and think there has to be a better/natural way to do this. The problem is mainly due to the fact that I have a species model as well as a species model of zoo (I've tried namespacing to Zoo and creating a Zoo::Zoo and Zoo::Species classes, creating a ZooSpecies class, and adjusting routes for those scenarios, etc)
From an organizational standpoint, it would be great to be able to have a Zoo class as well as a Zoo namespace, to have Zoo::Species and such, but that is not possible.
What is the proper way to organize something like this?
Update: My current setup...
Zoo Module
Zoo::Zoo Class
Zoo::Species Class
Species Class
Routes:
resources :zoos, path: 'zoos' do
resources :zoo_species, path: 'species', as: 'species', controller: 'zoo/species'
end
And a Zoo controller and a Zoo::Species controller. I feel like I'm getting closer to the desired result, but fighting against the framework more than I think I should. Still running into some issues properly setting up the relationships and paths, having to specify a lot of config values
Try using shallow nesting:
http://edgeguides.rubyonrails.org/routing.html#nested-resources
In your case:
resources :zoos
resources :species, shallow :true
To nest resources:
resources :zoos do # /zoos(/:id)
resources :species # /zoos/:zoo_id/species(/:species_id)
end
To namespace:
namespace :zoo do
resources :posts # /zoo/posts(/:id)
end
If you create that namespace, the you'll need to create app/controllers/zoo/posts_controller.rb with class definition:
class Zoo::PostsController < ApplicationController
# ...
end
Note: nested resources and namespaces are two different things. The Rails guide on routing is very readable - which you should definitely do: http://guides.rubyonrails.org/routing.html
So I am, like many before me, introducing the concept of "liking" items in my app. There are many different types of resources that could be liked (posts, replies, lists, actions etc.), and I am looking for the best way of structuring my routing file.
This may involve making a routes.rb file that looks something like:
resources lists do
resources posts do
resources replies do
resources likes
end
resources likes
end
resources likes
end
and a LikesController that doesn't know what it is meant to be load_and_authorize - ing:
class LikesController < ActionController:Base
load_and_authorize :list # only works if list_id exists in this request
load_and_authorize :post, through: :list # only works if post_id exists in this request
# and so on...
end
Are there any better ways of doing this? I had thought about just having a /likes path that everything posts to, but that means I can't use load_and_authorize, and also means it is harder to sensibly do things like Likes#index for a given list, post, reply, etc.
Thanks.
Instead of nesting Likes inside other resources, try this:
scope "/lists/:list_id(/posts/:post_id(/replies/:reply_id))" do
resources :likes
end
I believe that should get you a single set of LikesController routes which require a :list_id parameter and which optionally take a :post_id and a :reply_id. The url is pretty ugly, but I'm just trying to match the default for a quadruple-nested rails resource route. I recommend cleaning it up a bit.
Edit: It looks like this will also require some additional logic in your LikesController--like a before_filter that detects which params you've got and loads_and_authorizes only those objects. But that seems like a solvable problem to me?
Using Rails 3.1.1 and the gem acts_as_tree. I have googled the issue and checked similar questions here at SO (the answers are too old, or irrelevant).
I have a model called articles with a route that today looks like:
resources :articles, :path => '', :only => :show
resources :articles, :path => 'articles', :except => :show
I have three articles: "book", "chapter1" and "chapter2". Where book is parent to chapter1 and chapter2.
Today, my path to each article is: host.com/book, host.com/chapter1 and host.com/chapter2. I want the url path to be host.com/book/chapter1 and host.com/book/chapter2 , i.e. nested routes.
How can I create this in a clean simple manner?
Basically, I want a path that will be host.com/:parent_id/:parent_id/:id with N numbers of :parent_id. Pretty much how Wordpress-articles are routed.
I don't believe route globbers is the solution, but I might be wrong. It seems to give the same result for host.com/:id and host.com/foo/bar/:id which will result in duplicate content.
A)
If you have a solution for the routing and the only problem with it is that you're concerned about duplicate content issues, you could consider adding <link rel="canonical" href="..."> to the pages generated from those requests. It's not bulletproof though, as Google considers it a suggestion.
Not sure if the route globbers solution would take care of generating the URLs with parent IDs though.
B)
You don't need the parent IDs to perform the routing, correct? You just want to include them in the URLs and route those requests the same as if using the URLs like example.com/chapter1, correct?
If you'd consider a solution that's not purely at the Rails level, what about rewriting the URLs on those requests so that /:parent_id/:parent_id/:id becomes /:id before Rails processes it? That would be easier if there was a static prefix, like /articles/:parent_id/:parent_id/:id.
I imagine you'd need to write some helpers to generate the URLs with parent IDs for linking to those resources.
Duplicate Content
Either way, you'll need to generate URLs that include the parent IDs, so duplicate content issues probably aren't too likely if you only link to those resources using those URLs.
You have three "articles"... "book", "chapter1" and "chapter2" all represent same 'resources', named 'articles'. Same 'resource' cannot be nested. If you need nested routes you have to define separately parent resource and child resource. following code spinet may help you
class Book < ActiveRecord::Base
has_many :chapter
accepts_nested_attributes_for :chapters
end
class Chapter < ActiveRecord::Base
belongs_to :book
acts_as_tree :parent_id
end
match '*p1/*p2/*p3/.../*pn' => 'articles#show'
The ... is not literal, just define as many parameters as you need upto n.
URL:
host.com/book/chapter1
params[:p1] = 'book'
params[:p2] = 'chapter1'
params[:p3] = nil
URL:
host.com/book/chapter1/section2/sentence4
params[:p1] = 'book'
params[:p2] = 'chapter1'
params[:p3] = 'section2'
params[:p4] = 'sentence4'
params[:p5] = nil
That'd have to be your LAST route.
I think it would also make any catchall routes inoperable, but they're now commented out in the default routes.rb in Rails 3, If you use them, you'd have to manually specify all routes normally handled by the old style catchall routes.
And, if you have a controller named articles, you could never have a book titled 'articles' same with all your controllers, To be safe you probably have to rename all your controllers, i.e articles becomes X_articles. You could never have a book call X_articles then, and so on....
Totally untested.
What you're looking to do is use Rails for something it isn't made for. No matter what answer you get here, it either won't be RESTful, DRY, or make sense to be used with Active Record. Consider restructuring your idea, or bring your application to another platform if it's not too late.
Source to back up my claim: https://stackoverflow.com/a/174287/628859
Lets consider the following situation.
There is products_controller which can be accessed from "Admin" and "Configure" sections of the Ruby on Rails application.
In the view I need to differentiate which section I am currently in (i.e. "Admin" or "Configure"). What would be there best practice of achieving the right result?
Couple of solutions come to mind?
Append the "referrer" option as a parameter and use it to distinguish where I came from (i think this would be super-ugly and break the nature of rest).
Create separate action pairs in the controller(i.e. new/create and admin_new/ admin_create).
What would be the right approach in the given situation?
If it is just for logging purposes, adding a parameter should be enough.
If logic of how things are handled depends on where user came from, go for different routes mapping to different actions.
If you don't wan't to add a parameter, but it is for logging purposes, you can also create non-conventional route:
resources :products, :except => [:new, :create] do
collection do
get products/new(/:section) => "products#new"
post products(/:section) => "products#craete"
end
end
Now you can have new_message_path(:section => "admin") and it will result in path /products/new/admin, you will have the :section available in params[:section].