One Resource belongs to two parent resources - ruby-on-rails

in routes.rb
resources :restaurants do
collection do
get 'nearby'
end
resources :tickets
end
resources :users do
resources :tickets
end
If my controller, I can differentiate the parent resources
if params[:user_id].present?
#collection = User.find(params[:user_id])
else
#collection = Restaurant.find(params[:restaurant_id])
end
#ticket = #collection.tickets.new
but how can I differentiate, for example, path helper?
Thanks.

See polymorphic_path.

Related

Rails change path of resource

I have this routes.rb:
Rails.application.routes.draw do
resources :students do
collection do
get :posters
get :stories
end
end
root "department#index"
get "department/about"
end
Initially, students is a database where I store students information. So for each student the URL should be students/:id. Now I want to move it to students/stories/:id.
How can I do it? Thank you!
You basically need to define a students namespace and a stories resource inside it like below:
Rails.application.routes.draw do
namespace :students do
resources :stories, only: %i[index show update destroy create] do
end
end
end
I have added all the default actions in the only list. You can remove the routes you don't need.

Routing for sub ressources in rails

So this is in routes file :
resources :users do
resources :lamps
end
I want to be able to display a user's "lamps" with something like :
http://localhost:3000/users/2/lamps
and show all the existing lamps whichever user owns it using :
http://localhost:3000/lamps
both are very different as the first one is more of a management view and the later is more what a user browsing would see.
The thing is they both go to the index action of the lamp_controller
How can I manage this in a clean way without having to use if statements in my action/view?
You can use the module option to route the nested routes to a namespaced controller:
Rails.application.routes.draw do
resources :users do
resources :lamps, only: [:index], module: 'users'
end
resources :lamps, only: [:index]
end
Another way to do this for a group of resources is:
Rails.application.routes.draw do
resources :users do
scope module: 'users' do
resources :lamps, only: [:index]
resources :chairs
resources :rugs
end
end
resources :lamps, only: [:index]
end
This would let you handle the different contexts in separate controllers:
# app/controllers/lamps_controller.rb
class LampsController < ApplicationController
# GET /lamps
def index
#lamps = Lamp.all
end
end
# app/controllers/users/lamps_controller.rb
class Users::LampsController < ApplicationController
before_action :set_user
# GET /users/:user_id/lamps
def index
#lamps = #user.lamps
# renders /views/users/lamps/index.html.erb
end
private
def set_user
#user = User.find(params[:user_id])
end
end

Display all comments and order them

I want to display all comments (total number) on 'all' page. So, not all comments for a specific Post, but all comments in the entire app. I've tried with Comment.all, but it says it can't find post without an ID...
.../comments/all
routes
resources :posts do
resources :comments do
member do
put "like", to: "comments#upvote"
put "dislike", to: "comments#downvote"
end
end
end
comments_controller
def all
?
end
def index
#post = Post.find(params[:post_id])
#comments = #auto.comments.order("cached_votes_score DESC")
end
def show
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
end
...
You need a not nested route to comments:
routes
resources :posts do
resources :comments do
member do
put "like", to: "comments#upvote"
put "dislike", to: "comments#downvote"
end
end
end
get "comments#all"
comments_controller
def all
#comments=Comment.all
end
The problem is in your PostsController because what you want is not actually directly relevant to a post.
Try adding a collection route for comment
resources :comments do
member do
..
end
collection do
get :all # actually that is index
end
end
or simpler
#config/routes.rb
resources :comments, only: :index
and then a
#app/controllers/comments_controller.rb
def index
Comment.all
end
on your CommentsController will do.

How to share a controller action for nested routes in Rails?

In Rails, when I need:
/comments
and
/posts/1/comments
How do I best organize CommentsController? E.g. let the routes share the index actions, or work with 2 controllers?
You can work with only one controller.
I would go with a before_filter to check if the post_id param is present:
class CommentsController < ApplicationController
before_filter :find_post, only: [:index]
def index
if #post.present?
## Some stuff
else
## Other stuff
end
end
private
def find_post
#post = Post.find(params[:post_id]) unless params[:post_id].nil?
end
end
And have in your routes (with the constraints of your choice) :
resources :posts do
resources :comments
end
resources :comments
I believe you want /comments only for show and index actions, right? Otherwise the post params will be lost when creating or updating a comment.
In your routes.rb you can have something like:
resources : posts do
resources :comments
end
resources :comments, :only => [:index, :show]
In your form:
form_for([#post, #comment]) do |f|
And in your controller, make sure you find the post before dealing with the comments (for new, edit, create and update, such as:
#post = Post.find(params[:post_id])
#comment = #post...
You can do almost anything you want with rails routes.
routes.rb
match 'posts/:id/comments', :controller => 'posts', :action => 'comments'}
resources :posts do
member do
get "comments"
end
end

Rails 3 Resource: Share Custom Actions with Nested Resources

I have 2 resources events and patients
resources :events do
collection do
get :upcoming
get :missed
end
end
resources :patients do
resources :events # does not have upcoming or missed
end
Is there a way to have the events nested resource within the patients definition share the custom collection members from the primary events resource without having to define them again?
You can define a method in your routes file and can call it each time, as such keep DRY.
def events_actions
collection do
get :upcoming
get :missed
end
end
resources :events do
events_actions
end
resources :patients do
resources :events do
events_actions
end
end
Or take things even further:
def resources_events
resources :events do
collection do
get :upcoming
get :missed
end
end
end
resources_events
resources :patients do
resources_events
end

Resources