rails 3: custom routes in routes.rb - ruby-on-rails

I want to get link to user like: /chicago/123-olegpasko .
In my helper:
def users_path(user)
"/#{if user.city; user.city.name; else; "city";end}/#{user.to_param}"
end
How can I create a right routes?
Now I have something like:
match 'dontknow/:id' => 'users#show', :as => :users

Check out the Railcasts about friendly_url
Also take a look at the routes casts

Simple add this lines in you model:
def to_param
"#{id}-#{name.parameterize}"
end

The solution was simple:
match ':name/:id' => 'users#show', :as => :users

Related

how to make dynamic nested routes on rails?

I'll explain when open www.domain.com/:id should be check the :id is a page then use
get ':id' => 'pages#show'
else if :id is a Category use
get ':category' => 'categories#show'
sorry for my english
get ':page' => 'pages#show'
resources :categories, :path => '/' do
resources :posts, :path => '/'
end
constraints for routes is way to go, but I would suggest a bit different solution for your problem.
Consider creating custom Constraint objects, which will query the database in order to check if Post or Category exists:
app/lib/post_constraint.rb
class PostConstraint
def matches?(request)
Post.exists?(request[:id])
end
end
app/lib/category_constraint.rb
class CategoryConstraint
def matches?(request)
Category.exists?(request[:id])
end
end
In your app/config/routes.rb
get ":id" => "posts#show", constraints: PostConstraint.new
get ":id" => "categories#show", constraints: CategoryConstraint.new
You have to be aware of the fact, that id is very poor candidate for such comparison, because the Post is checked in first place, and if there is record matching, the "posts#show" will be accessed, and CategoryConstraint wot be even bothered.
For more, check the documentation.
You should consider adding a slug for both models to easier serve exactly what user expects to see. For this purpose, try gem friendly_id.
Hope that helps! Good luck!
why dont you write something like this:
routes.rb
get '/:category_id/:post_id', to: 'categories#post'
and in your categories_controller.rb
def post
#params[:category_id] and params[:post_id] will contain the params from the url
end
Couple of solutions
If your post id and category id follow a pattern you can add constraints to your routes
1)
get ':post_id' => 'posts#show', :constraints => { :id => /[A-Z]\d{5}/}
get ':category_id' => 'categories#show', :constraints => { :id => /[1-9]\d{5}/ }
2)
Add a custom method where both post_id/category_id routes point, in that check if the id is a post id or category id and based on that render the page

How can I create custom route helpers for usage in routes.rb

I have a few reoccurring patterns in my routes.rb and I would like to make it DRY by creating a method that creates those routes for me.
An example of what I want to accomplish can be seen in the Devise gem where you can use the following syntax:
#routes.rb
devise_for :users
Which will generate all the routes necessary for Devise. I would like to create something similar. Say for example that I have the following routes:
resources :posts do
member do
get 'new_file'
post 'add_file'
end
match 'files/:id' => 'posts#destroy_file', :via => :delete, :as => :destroy_file
end
resources :articles do
member do
get 'new_file'
post 'add_file'
end
match 'files/:id' => 'articles#destroy_file', :via => :delete, :as => :destroy_file
end
This starts getting messy quite quickly so I would like to find a way to do it like this instead:
resources_with_files :posts
resources_with_files :articles
So my question is, how can I create the resources_with_files method?
Put this in something like lib/routes_helper.rb:
class ActionDispatch::Routing::Mapper
def resources_with_files(*resources)
resources.each do |r|
Rails.application.routes.draw do
resources r do
member do
get 'new_file'
post 'add_file'
delete 'files' => :destroy_file
end
end
end
end
end
end
and require it in config/routes.rb

rails routing aliases

I have a model called Spaces which has different types of places... such as Bars, Restaurants, etc. It has the same columns, same, model, controller, etc. no fancy STI, I just have one field called Space_type which I would like to determine an aliased route.
Instead of domain.com/spaces/12345 it would be /bars/12345 or /clubs/12345
Currently I have:
resources :spaces do
collection do
get :update_availables
get :update_search
get :autocomplete
end
member do
post :publish
post :scrape
end
resources :photos do
collection do
put :sort
end
end
resources :reviews
end
Also, Is there a way I can do this so that anytime I use the space_url it can figure out which one to use?
The routes are not a way to interact with your model directly. So, as long as you write a standard route, you can make things work. For instance, to make /bars/12345 and /clubs/12345 for your spaces_controller (or whatever the name of the controller is) , you can create routes like :
scope :path => '/bars', :controller => :spaces do
get '/:id' => :show_bars, :as => 'bar'
end
scope :path => '/clubs', :controller => :spaces do
get '/:id' => :show_clubs, :as => 'clubs'
end
# routes.rb
match "/:space_type/:id", :to => "spaces#show", :as => :space_type
# linking
link_to "My space", space_type_path(#space.space_type, #space.id)
which will generate this urls: /bars/123, /clubs/1 ... any space_type you have
And it looks like STI wold do this job little cleaner ;)
UPD
Also you can add constraints to prevent some collisions:
match "/:space_type/:id", :to => "spaces#show", :as => :space_type, :constraints => { :space_type => /bars|clubs|hotels/ }
And yes - it is good idea to put this rout in the bottom of all other routes
You can also wrap it as a helper (and rewrite your default space_url):
module SpacesHelper
def mod_space_url(space, *attrs)
# I don't know if you need to pluralize your space_type: space.space_type.pluralize
space_type_url(space.space_type, space.id, attrs)
end
end

How to route to different actions depending on the request method in Rails?

As we all know, a simple
resources :meetings
will generate 7 actions for me. Two of these are index and create. A really cool thing about these two!: The URL for both is /meetings, but when I GET /meetings I am routed to the def index action and when I POST /meetings, I am routed to the def create action. Nice.
Now I want to do this:
resources :meetings do
member do
get 'scores'
post 'scores'
end
end
And, you guessed it!, I want them to route to different actions in MeetingsController: GETting /meetings/1/scores will route to def scores and POSTing to meetings/1/scores will route to def create_scores.
Try:
resources :meetings do
member do
get 'scores' => :scores
post 'scores' => :create_scores
end
end
I suppose you will be also interested in having named routes:
resources :meetings do
member do
get 'scores' => :scores, :as => 'scores_of'
post 'scores' => :create_scores, :as => 'create_scores_of'
end
end
Then you get scores_of_meeting_path and create_scores_of_meeting_path helpers.
Above may be DRYed more with:
get :scores, :as => 'scores_of'
Define the routes such as this:
resources :meetings do
member do
get 'scores', :action => "scores"
post 'scores', :action => "post_scores"
end
end
But it sounds to me like it would be much easier to create another controller to handle this, as scores to me feels like another resource entirely, even if they don't have their own model association.
Ha! Never underestimate the ability of asking a question well to lead you to its answer.
resources :meetings do
member do
get 'scores', :to => "meetings#scores"
post 'scores', :to => "meetings#create_scores"
end
end

customize rails url with username

I want to copy the twitter profile page and have a url with a username "http://www.my-app.com/username" and while I can manually type this into the address bar and navigate to the profile page I can't link to the custom URL.
I think the problem is in the routes - here's the code in my routes.rb
map.connect '/:username', :controller => 'users', :action => 'show'
Also, I have Question and Answer models and I want to link to them with the customized URL like so:
http://www.my-app.com/username/question/answer/2210
There's nothing wrong with your route. Just remember to define it at the end, after defining all other routes. I would also recommend using RESTful routes and only if you want to have better looking URLs use named routes. Don't use map.connect. Here's some good reading about Rails routes.
Here's how this could look:
map.resources :questions, :path_prefix => '/:username' do |question|
question.resources :answers
end
map.resources :users
map.user '/:username', :controller => 'users', :action => 'show'
Just a draft you can extend.
To create urls you need to define to_param method for your user model (read here).
class User < ActiveRecord::Base
def to_param
username
end
end
I know this questions is old but it will help someone.
You could try the below. I've used it in a rails 4 project and all seems to be working great. The reason for the as: :admin is I also had a resources posts outside of this scope. It will add a admin to the helper calls e.g. admin_posts_path
scope ":username", module: 'admin', as: :admin do
get '', to: 'profiles#show'
resources :posts
end
I have used like this
In View part
portfolio.user.name,:id =>portfolio) %>
and in rout.rb
map.show_portfolio "portfolios/:username", :action => 'show_portfolio', :controller => 'portfolios'

Resources