RESTful routing in Rails 3 app - some advice / pointers - ruby-on-rails

I have an app, locally in development without a subfolder, and in production i have it deployed under /myappname/
So, locally I have http://myapp.dev and in production http://mydomain.com/myappname
which my root route does:
root :to => 'products#list'
which works great, even in production.
Now, i have a default match action:
match '/:controller(/:action(/:id))'
which breaks in production, so i started trying to build a restful route, but i need some help... I can't wrap my head around the routing. I think i have the proper start (with scope, below)
#PRODUCTION ROUTES
scope '/myappname' do
#WHAT WOULD GO HERE?
end
format would be /myappname/products/show/15

Hm. I would expect all the routes to work relative to the "home page", so why don't you just go with
resources :users
or any other route definition from the examples in config/routes.rb?

#PRODUCTION ROUTES
scope "/mothers" do
#ROOT
root :to => 'rings#list'
match '/rings/:id' => "rings#show", :as => :ring
end
#DEVELOPMENT ROUTES
root :to => 'rings#list'
match '/rings/:id' => "rings#show", :as => :ring

Related

Prefixed route path gives error in Rails 4

After upgrading to Rails 4 a route with a prefixed name and slash is throwing an error.
actionpack-4.0.1.rc1/lib/action_dispatch/routing/mapper.rb:239:in `default_controller_and_action':
'MyEngine/dashboard'
is not a supported controller name. This can lead to potential routing problems.
In routes.rb I have
Rails.application.routes.draw do
mount MyEngine::Engine => "/foo", :as => 'my_engine'
match 'dashboard' => 'MyEngine/dashboard', via: :get
And in the mounted engine MyEngine:
MyEngine::Engine.routes.draw do
match 'dashboard' => 'dashboard#index', via: :get
This works well in Rails 3.2, but in Rails 4 the slash in 'MyEngine/dashboard' throws the error.
Using an engine, you can directly create routes to the engine's controllers and actions in your routes file like this:
Rails.application.routes.draw do
mount MyEngine::Engine => "/foo", :as => 'my_engine'
get 'dashboard' => 'dashboard#index'
end
I think it's not possible to set a route in the host application to a controller in a mounted engine (mounted on "/foo") at the top level, e.g. /foo/dashboard calls the mounted engine's 'dashboard#index' action, and I want /dashboard to do the same.
I'm adding a controller of the same name in the host application and doing a redirect to the mounted engine controller action.
Simply, change this line
match 'dashboard' => 'dashboard#index', via: :get
as
get 'dashboard' => 'dashboard#index'

How can I redirect multiple devise model to multiple specific urls?

I got three independent devise models, ergo I got three different sign_in screen. And all three have got a dashboard:
devise_for :md1
devise_for :md2
devise_for :md3
match 'md1/dashboard' => 'md1#dashboard', :via => :get
match 'md2/dashboard' => 'md2#dashboard', :via => :get
match 'md3/dashboard' => 'md3#dashboard', :via => :get
I want when there is a mdX succesfully sign in, it will redirect to mdX#dashboard, and if it is possible by GET. I tried:
devise_scope :md1 do
root :to => 'md1#dashboard'
end
devise_scope :md2 do
root :to => 'md2#dashboard'
end
devise_scope :md3 do
root :to => 'md3#dashboard'
end
Then when I succesfully sign in with md1 I got redirected to md1 dashboard, but when I succesfully sign in with md2 I got redirected to md1's sign_in screen.
Then I tried:
def after_sign_in_path_for resource
dashboard_path resource
end
But there isn't such method. Is there an easy way to do this or it has to be with the if statements for each model?
UPDATE
Some routes to make a better understanding and more information to get a better solution
md1_dashboard GET /md1/dashboard(.:format) md1#dashboard
md2_dashboard GET /md2/dashboard(.:format) md2#dashboard
md3_dashboard GET /md3/dashboard(.:format) md3#dashboard
Thanks in advance
When you are writing this:
devise_scope :md1 do
root :to => 'md1#dashboard'
end
devise_scope :md2 do
root :to => 'md2#dashboard'
end
devise_scope :md3 do
root :to => 'md3#dashboard'
end
You are defining three root routes, with the same name. Since they conflict, only the first will be used. That's why only md1 worked. You probably meant to write this:
scope :md1 do
root :to => 'md1#dashboard'
end
scope :md2 do
root :to => 'md2#dashboard'
end
scope :md3 do
root :to => 'md3#dashboard'
end
On this case, you will define three different root routes, at three different scopes (check rake routes again). Note scope is a router method that scopes your routes, devise_scope does not scope any route, it simply tells which devise scope you want to use, which you don't need to tell unless Devise explicitly asks you so (you will know when it does).
After this change, everything should work as expected. Note that Devise by default uses #{scope}_root_path to redirect after successful sign in, that's why the code above works (check rake routes and you will see you md1_root, md2_root, etc are now defined).

Rails 3.1 load controller from different path based on subdomain

Is it possible to dynamically change the path from which controllers are used? Ryan Bates showed how to change the view_paths here: http://railscasts.com/episodes/269-template-inheritance
I'm making a CMS where a user can create a site and enter their own subdomain. I'd like "/" to point to "public#welcome" if there's no subdomain, but if there is a subdomain, I want it to point to "sites/public#welcome".
I'm using Rails 3.1 if that makes any difference.
You should be able to solve this situation using constraints if I'm not mistaken (which I might, since I haven't actually tried the following yet):
constraints(:subdomain => /.+/) do
root :to => 'sites/public#welcome'
end
root :to => 'public#welcome'
I figured it out:
constraints(:subdomain => /.+/) do
scope :module => "sites" do
root :to => 'public#welcome'
end
end
root :to => 'public#welcome'
Now when a user visits "/" Sites::PublicController will be used if a subdomain exists, but just PublicController if no subdomain exits. Adding scope :module => "sites" do...end keeps my routes file simplistic and manageable.

Rails 3: How do I route a controllers index and show actions to root while sending new/edit/destroy to /admin?

First off, I'm using rails 3.0.8 with friendly_id 3.2.1.1.
I'd like to be able to view the posts at website.com/:title, so drop the "/posts".
But I'd also like to have an /admin view. From there, a user should be able to create/edit/destroy posts. I already have a admin.html.erb view with links to various actions.
Right now my routes file look like:
MyApp::Application.routes.draw do
root :to => 'posts#index'
resources :posts
match "/:id" => "posts#show"
match "/admin" => "posts#admin"
end
This works for website.com/:title, but for website.com/admin I get an error:
Couldn't find Post with ID=admin
.... which makes sense. But I'm not sure how to solve this problem.
The rules are run through top to bottom. So put your admin rule on top of the resource definition.
If you put /admin first then it will work (as noted by cellcortex). You can also use :constraints if you can neatly separate your :id from 'admin'; for example, if your :id values are numeric, then something like this should work:
match '/:id' => 'posts#show', :constraints => { :id => /\d+/ }
match '/admin' => 'posts#admin'
In a simple case like yours, putting things in the right order will work fine. However, if your routing is more complicated, then the :constraints approach might work better and avoid a some confusion and chaos.
Use this
resource :posts, :path => '/'
with this all of your article will be directly under root
So in Posts Class you may add this:
def to_param
"#{id}-#{title.parameterize}"
end

Ruby on Rails: subdomain too powerful? how do I set this up the right way

routes:
match '/' => 'site_admin/admin#index'
resources :link_pages
resources :services
resource :user_session
resource :account, :controller => "users"
resources :password_resets
resources :users
resources :addresses
resources :info
match "/home", :to => 'info#home'
match "/register", :to => 'users#new'
root :to => 'info#home'
match ':controller(/:action(/:id(.:format)))'
so when I got to admin.lvh.me:3000/ it goes to site_admin/admin#index... which is great...
but when I take off the subdomain, and just have lvh.me:3000/ it goes to the same route....
how do I get admin to stay where it is. and no subdomain to go to my root page, as in my routes file?
Routes are parsed in order, so when you request / from any domain it finds "match '/'..." first and sends you to the specified page. Your subdomain isn't coming into play at all. You can use Request-based constraints to route based on subdomain:
http://guides.rubyonrails.org/routing.html#request-based-constraints
Not sure how subdomain factors into this at all. Perhaps you're confusing subdomain with route namespacing (http://edgeguides.rubyonrails.org/routing.html#controller-namespaces-and-routing)?
match '/' => 'site_admin/admin#index'
Is being selected over
root :to => 'info#home'
Because it's defined first in the routes file. They're ostensibly the same thing.
Yes #Cory is right. Above both statements are similar and first defined route is considered every time. If you change admin route to
match '/admin' => 'site_admin/admin#index'
then it does make sense... What say??
or else, using the following code you can determine your URL conditionally:
request.subdomains(0).first will give you the subdomain value- either admin or blank. But it will go to any one controller action only which is defined first in route.rb file.
Then from that action using subdomain, you can decide where to re-direct it- either to admin panel or home page...

Resources