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
Is There a Good Admin Generator for Ruby on Rails
How to Update Gems on Production Server
Using Ruby's Optionparser to Parse Sub-Commands
Why Are Symbols Not Frozen Strings
Accessing Ruby Class Variables with Class_Eval and Instance_Eval
Best Place to Store Model Specific Constants in Rails 3.1
Rails, Ruby, How to Sort an Array
How to Force Activerecord to Reload a Class
Building a Hash in a Conditional Way
Rails Collection_Select VS. Select
How to Use Capybara in Pure Ruby (Without Rails)
How to Recompile a Ruby with Rvm
Adding an Instance Variable to a Class in Ruby
Rails: Serializing Objects in a Database