My routes are getting out of hand due to the fact that this isn't possible (correct me if I'm wrong):
map.resources :english_pages, :as => :english, :spanish_pages, :as => :spanish do |article|
Due to nested routes things are spiralling out of control (tidiness).
map.resources :english_pages, :as => :english, :member => {:manage => :get} do |article|
article.resources :topics do |topic|
topic.resources :posts
end
end
map.resources :spanish_pages, :as => :spanish do |article|
article.resources :topics do |topic|
topic.resources :posts
end
end
How can I avoid duplication of this:
article.resources :topics do |topic|
topic.resources :posts
end
Is there some way to store routes as a block somewhere, or perhaps define, in my case, english_pages and spanish pages aliases seperately?
Thanks very much in advance.
All you need is a little bit of meta-programming.
resources is just a method call, and the symbols end up being evaluated as strings anyway, so this becomes pretty easy.
[:english, :spanish].each do |language|
map.resource "#{language}_pages", :as => language, :member => {:manage => :get} do |article|
article.resources :topics do |topic|
topic.resources :posts
end
end
Related
I need to figure out how to properly use routes to create a url structure like so:
items/page/2
items/expired/page/2
I have items/page/2 working and then I have this which I want to to correct:
items/expired?page=2
I am using Kaminari to provide pretty url structure for rails 4.2 with a concern.
https://github.com/amatsuda/kaminari/#creating-friendly-urls-and-caching
My controller has two actions: index and expired
My views under items are index.html.haml and expired.html.haml
routes.rb
concern :paginatable do
get '(page/:page)', :action => :index, :on => :collection, :as => ''
end
concern :expired_paginatable do
get '(page/:page)', :action => :expired, :on => :collection, :as => ''
end
get 'items/expired', to: "items#expired", :concerns => :expired_paginatable
resources :items, :concerns => :paginatable
my views both have:
= paginate #items
I know I do not need two concerns but thought I would try it.
I ended up changing my resources block to this:
resources :items do
collection do
get 'expired/page/:page', :action => :expired
get :expired
end
concerns :paginatable
end
dropping:
concern :expired_paginatable do
get '(page/:page)', :action => :expired, :on => :collection, :as => ''
end
get 'items/expired', to: "items#expired", :concerns => :expired_paginatable
resources :items, :concerns => :paginatable
I have a school page that has tabs when clicked upon are suppose to bring up microposts. The issue is I don't think I am routing it correctly and I feel like an idiot trying to figure this out and not succeeding. If anyone has suggestions please feel free to help me out! Thank you so much!
Routes.rb
get "/schools/:id/mostrecent_schools" => "users#microposts", :as => "mostrecent_schools"
School Controller
def mostrecent
#school = School.find_by_slug(request.referer.gsub('http://localhost:3000/','')).id
#microposts = #user.microposts.paginate(:per_page => 10, :page => params[:page])
respond_to do |format|
format.html
format.js
end
end
Tab HTML
li class='StreamTab StreamTabRecent active'>
<%= link_to 'Most Recent', mostrecent_schools_path, :remote => true, :class => 'TabText' %>
</li>
<div id='ContentBody'>
<div id='ajax'></div>
<%= render 'users/microposts', :microposts => #microposts %>
</div>
mostrecent.js
$("#ajax").hide();
$("#ContentBody").html('<%= escape_javascript(render :partial => "users/microposts" )%>');
EDIT
*Routes.rb*
Projects::Application.routes.draw do
resources :pages
resources :application
resources :schools
resources :microposts
resources :comments
resources :users
resources :sessions
resources :password_resets
resources :relationships, only: [:create, :destroy]
resources :users do
member do
get :following, :followers
end
end
resources :microposts do
member do
post :vote_up, :unvote
end
end
resources :microposts do
member do
post :upview
end
end
resources :microposts do
resources :comments
end
get "schools/:page/mostrecent" => "schools#mostrecent", :as => "mostrecent_schools"
root to: "pages#index"
From what I can understand, Your routes.rb should look something like this
My final try
Change your routes.rb to this
get "schools/mostrecent/new/:page" => "schools#mostrecent", :as => "mostrecent_schools"
and in your controller edit this line. If this dosen't work then i give up
#school = School.find_by_slug(request.referer.gsub('http://localhost:3000/','')).params[:page]
Although this is not the restful way of doing stuff and as far as I know since users belong to schools and microposts belong to users you shouldn't define schools microposts and users as simple :resources.
Refer to [Rails Routing Guide ](Refer to http://guides.rubyonrails.org/routing.html)for more details.
I'm new to testing, and I'm having some difficulties trying to run a functional test.
I've a messages_controller, and a user_controller here.
in the routes, I've defined that the users resources has_many message resources.
Now I'm trying to run a simple test in the messages controller:
def test_index
get :index, { :user_id => 1 }
assert_template 'index'
end
But get a routing error from rails, that he cant find a route to messages. I don't want to include a route to messages only because of the tests. How can I tell the test that he must access from the /users/messages url?
the full routes.rb:
ActionController::Routing::Routes.draw do |map|
map.login 'login', :controller => :user_sessions, :action => :new
map.logout 'logout', :controller => :user_sessions, :action => :destroy
map.signin 'signin', :controller => :users, :action => :new
map.connect 'search/:action/:word', :controller => :search
map.connect 'search/:word', :controller => :search, :action => :index
map.resources :forums do |forums|
forums.resources :forum_posts, :collection => {:preview => :post }, :as => :posts do |post|
post.resources :forum_posts, :as => :reply
post.resources :reports
end
end
map.resources :newsitems, :as => :news do |news|
news.resources :comments do |comment|
comment.resources :reports
end
end
map.resource :user_sessions
map.resources :users,
:as => :profiles,
:controller => :profiles,
:has_many => [ :messages ]
map.resource :profiles
map.resource :me,
:controller => :me,
:has_many => [ :messages ]
map.resources :comments, :has_many => [ :reports ]
map.resources :forum_posts, :has_many => [ :reports ]
map.resources :reports
map.home '/', :controller => :home
map.root :controller => :home
map.namespace :admin do |admin|
admin.namespace :forum do |forum|
forum.resources :categories
forum.resources :posts
forum.resources :forums
forum.root :controller => :home
end
admin.resources :notices
admin.resources :users
admin.workflow 'workflow/:action', :controller => :workflow
admin.resources :newsitems
admin.resources :reports
admin.resources :comments
admin.root :controller => :home
end
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
UPDATE
I've noticed that every functional test get a routing error. Even the simpliests ones like newsitem. I've no idea why.
I recreated your scenario in a blank rails app with the routing code and and test you specified, and it worked without a problem, as it should. I'll paste my controller code here since that's the only part you left out:
class MessagesController < ApplicationController
def index
#messages = User.find(params[:user_id]).messages
end
end
If yours is doing basically the same thing, then a routing issue could be caused by a conflict in your routing file, which is what I suspect might be the case. Can you post it? FYI, I wrote an article on testing your routes, and that would be a very good idea because it would catch routing errors early, before they interfere with controllers.
Anyway, if you can post your routes I can take a look.
UPDATE: After looking at your routes, there are a couple conflicts. You can have messages as a sub-resource of more than one other resource, but in your messages controller you're going to have to account for the possibility of either a params[:me_id] or params[:profile_id]. It looks like they're both really the user model underneath, so it can be as simple as:
#user = User.find(params[:me_id] || params[:profile_id])
and you'll probably want to abstract that out into a method you call with before_filter.
The other issue is that you have two overlapping profiles routes, and I'm not sure why. I don't think it's a routing error in the test, because tests bypass the routing engine anyway. I think it's an error in the index view, because it probably contains links to messages with improperly formatted urls. If you have a link to a message, for instance, and you have a #profile object, then you'll need to call them like this:
<%= link_to message.name, profile_message_path(#profile, #message) %>
However, if you're using non-nested paths like message_path(#message), it will fail because there are no non-nested message routes.
It was a problem in my "journey" gem. They made routes more stricter in journey 1.0.4 which only show up on "test" environment. It is good for "developement" and "production".
** Ensure you are using exactly the same parameters as declared in routes **
Either add:
get :index, :locale => "en"
or in your Gemfile update:
gem 'journey', '1.0.3'
The second solution is a workaround for time being. Ideally you should be testing your routes will all exact params. Journey 1.0.4 is a lot stricter
I have a controller which has a method called history
class UsersController < ApplicationController
def history
User.return_history(params[:id])
end
end
I have the following in my routes.rb file
map.resources :users, :shallow => true do |user|
user.resources :friends, :shallow => false
user.resources :posts, :collection=>{:no_access => :get}
user.resources :photos
end
How do I try to Ajax call the history method of the users_controller.rb? Using link_to_remote in the following way
link_to_remote 'History', :url=>history_user_path(#user), :update=>"history", :method=>'get'
throws me an error saying history_user_path() not found. How can this be? edit_user_path() shows no error and edit is not even explicitly defined in the User.rb file. Thanks.
mapresources :users creates a bunch of url/path helper methods, including edit_users_path. If you need others. you've got to add it as either a :member, or :collection option for map.resources.
This will let you do what you want:
map.resources :users, :shallow => true, :member => {:history => :get} do |user|
user.resources :friends, :shallow => false
user.resources :posts, :collection=>{:no_access => :get}
user.resources :photos
end
Projects have many tasks and a task has a custom RESTful action called 'approve'.
I'm expecting the helper to look something like this approve_project_task_url
This isn't working for me:
map.resources :projects,
:has_many => :tasks,
:member => { :approve => :post }
I once had the same problem but I never searched long and hard for a fix. Instead I just opted for the older style which since then I've always used:
map.resources :projects do |project|
project.resources :tasks, :member => {:approve => :post}
end
That will give you your required approve_project_task_url(#project, #task) routes/helpers.
I guess you may already know this approach? If so and you don't like it hopefully I'll learn something from your other responses :)
**This is syntax correction to above solution**
map.resources :projects do |project|
project.resources :tasks, :member => {:approve => :post}
end