Using Polymorphic Paths with Nested Associations

Using polymorphic paths with nested associations

A possible way could be to use routes like this:

map.resources :works do |works|
works.resources :lines
end

map.resources :educations do |edu|
edu.resources :lines
end

Your LinesController remains the same, and you'll get routes like these:

work_lines GET    /works/:work_id/lines
....
education_lines GET /educations/:education_id/lines
...

The most annoying part is to manage the first id passed, because you'll have a params[:id] referred to a Line, but you'll also have params[:work_id] or params[:education_id]. Here you must choose between checking which param is passed, or at least parse the requested url to determine in which you are (Works, Educations, etc...).

Hope this helped ;)

EDIT:

According to what emerged in comments, you can use polymorphic_url/polymorphic_path (http://api.rubyonrails.org/classes/ActionDispatch/Routing/PolymorphicRoutes.html):

It makes sense if you use them like this way:

link_to "New Line", polymorphic_url(@line.item,@line)
# => /<educations_or_works>/item_id/lines/line_id

At least, you can even use it for collections:

link_to "New Line", polymorphic_url(@line.item,Line.new)
# => /<educations_or_works>/item_id/lines/

Cheers,

a.

Rails 3 - Nested resources and polymorphic paths: OK to two levels, but break at three

Your code example that limited your nesting to 2 levels is quite near the answer. To avoid duplicate routes for fams->kids and kids, you can use the :only option with a blank array so that the 1st-level kids will not generate routes except in the context of kids->pictures, like so:

resources :posts do
resources :pictures
end

resources :fams do
resources :pictures
resources :kids
end

resources :kids, only: [] do # this will not generate kids routes
resources :pictures
end

For the above code, you can use the following to construct your polymorphic edit url:

polymorphic_url([fam, picture], action: :edit) # using Ruby 1.9 hash syntax
polymorphic_url([kid, picture], action: :edit)

Rails link_to polymorphic parent, which can have a nested route

You could use a bit of polymophic routing magic.

module CommentsHelper
def path_to_commentable(commentable)
resources = [commentable]
resources.unshift(commentable.parent) if commentable.respond_to?(:parent)
polymorpic_path(resources)
end

def link_to_commentable(commentable)
link_to(
"Show # {commentable.class.model_name.human}",
path_to_commentable(commentable)
)
end
end

class Project < ActiveRecord::Base
# ...
def parent
user
end
end

link_to_commentable(c.commentable)

But it feels dirty. Your model should not be aware of routing concerns.

But a better way to solve this may be to de-nest the routes.

Unless a resource is purely nested and does not make sense outside its parent context it is often better to employ a minimum of nesting and consider that resources may have different representations.

/users/:id/projects may show the projects belonging to a user. While /projects would display all the projects in the app.

Since each project has a unique identifier on its own we can route the individual routes without nesting:

GET /projects/:id - projects#show
PATCH /projects/:id - projects#update
DELETE /projects/:id - projects#destroy

This lets us use polymorphic routing without any knowledge of the "parent" resource and ofter leads to better API design.

Consider this example:

Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

resources :projects

resources :users do
# will route to User::ProjectsController#index
resources :projects, module: 'user', only: [:index]
end

end

class ProjectsController < ApplicationController
def index
@projects = Project.all
end
# show, edit, etc
end

class User::ProjectsController < ApplicationController
def index
@user = User.joins(:projects).find(params[:user_id])
@projects = @user.comments
end
end

This would let us link to any project from a comment by:

link_to 'show on page', c.commentable

And any users projects by:

link_to "#{@user.name}'s projects", polymorpic_path(@user, :projects)

Rails polymorphic link for nested index action

I was finally able to find the answer.

polymorphic_path([@targetable, Design])

Instead of using a variable as the second object in the polymorphic path, you are supposed to use the model name. This path links to

targetable/:targetable_id/designs

Maybe this will help someone for future use.

Nested routes with polymorphic association

Are you looking for nesting the :comments resource inside :blogs? Otherwise your routes should look like:

resources :blogs do
member do
put 'like', to: 'blogs#upvote'
put 'dislike', to: 'blogs#downvote'
end
end
resources :comments do
member do
put 'like', to: 'comments#upvote'
put 'dislike', to: 'comments#downvote'
end
end

(note you had a missing do at beginning of the :comments block which resulted in a weird block ending/nesting)

Polymorphic Comments in both nested resource and simple resource ruby on rails 4

If I understand the problem correctly, there is nothing special about deeply nested resources. So you might need something like this

# routes.rb
concern :commentable do
resources :comments
end

resources :courses, only: [:index, :show] do
resources :enrols, only: [:new, :create]
resources :lectures, only: [:show], concerns: [:commentable]
end

resources :code_casts, :path => 'casts', :as => 'casts', only: [:index, :show]
resources :blogs, :path => 'blog', :as => 'blog', only: [:index, :show], concerns: [:commentable] do
resources :blog_votes, only: [:create, :destroy]
end

This will create nested comments resources for lectures and blogs.
Than you need to differentiate the path in a comments controller

# comments_controller
def create
Comment.create(commentable: commentable, other_params...) # assuming you have `commentable` polymorphic belongs_to
end

# a little more ugly than Ryan suggests
def commentable
if request.path.include?('blog') # be careful. any path with 'blog' in it will match
Blog.find(params[:id])
elsif params[:course_id] && request.path.include?('lecture')
Course.find(params[:course_id).leactures.find(params[:id]) # assuming Course has_many lectures
else
fail 'unnable to determine commentable type'
end
end

All 'magic' is in commentable method, where youare checking the path and determine which commentable object to pick. I use similar approach, but this exact code is written by memory without testing. Hopefully you've got the idea.

Rails Polymorphic Redirect Nested Resources

You can't reference a route for a nested object without the id of the object it is nested into.

Rails 4 - Polymorphic Associations - nested attributes

Try:

def create
@comment = Comment.new(comment_params)
@comment.user = current_user
@comment.commentable = @commentable

respond_to do |format|
if @comment.save
format.html { redirect_to @comment }
format.json { render :show, status: :created, location: @comment }
else
format.html { render :new }
format.json { render json: @comment.errors, status: :unprocessable_entity }
end
end
end


Related Topics



Leave a reply



Submit