Rails and rendering nested resources - ruby-on-rails

For example: can I render '/tags/:id/posts'?
If I try to render tag_posts_path(#tag) or some other ways, I get this or similar error:
Missing partial /tags/1/posts...
In my routes.rb I have this:
resources :tags do
resources :posts
end

I've stucked a bit with thing like yours
I achieved rendering correct page
def create
#project = Project.find(params[:project_id])
#comment = #project.comments.build(comment_params)
if #comment.save
flash[:success] = "Chingon!"
redirect_to #project
else
render 'projects/show'
end
end
My routes looks like:
resources :projects do
resources :comments, only: [:create, :destroy]
end
Rails expecting you to render not path but some page(like 'new' or 'show')
I got trouble only with my ELSE where I'm rendering 'projects/show'. It seem to be not quite right template, coz it renders in raw, without any CSS but with errors I expect to appear. It's the only way for now that I can render error messages for empty comment.
I walk over that issue simply by bypassing default way to display errors and place it in simple flash like this:
def create
#project = Project.find(params[:project_id])
#comment = #project.comments.build(comment_params)
if #comment.save
flash[:success] = "New comment here, bro"
redirect_to #project
else
redirect_to #project
flash[:error] = flash_error_message(#comment)
end
end
def flash_error_message(arg)
"The form contains #{arg.errors.count} error: #{arg.errors.full_messages.join(', ')}"
end

If I'm correct, I think what you are looking for is something like this
resources :tags do
resources :posts
end
You can see what kind of urls or routes this generates by typing in rake routes
I'm not really sure but, re-reading your question I think you mean rendering by saying
render 'some nested route'
The above routes I provided would allow you to do something like this...
render tag_posts_path(#tag) that will in term look for a index action since its the posts path. Again, rake routes shows all this.
A quick search on google for nested routes would've led you to this.
Nested Routes

Related

How do I create an instance of a class that is namespace within another model

resources :recipes do
resource :like, module: :recipes
resources :comments, only: [:new, :create, :show, :index], module: :recipes
end
recipe_comments GET /recipes/:recipe_id/comments(.:format) recipes/comments#index
POST /recipes/:recipe_id/comments(.:format) recipes/comments#create
Comments are in /recipes/:id
Recipe Controller
def show
#recipe = Recipe.find(params[:id])
#comment = #recipe.comments.new
#clean_recipe = Sanitizer.new(#recipe)
end
Recipes::CommentsController
Theres a before action that finds recipe.
def create
#comment = #recipe.comments.new(comment_params)
#comment.user_id = current_user.id
if #comment.save
redirect_to recipes_path
end
end
I've done
form_for([#article,#comment]) and form_for [#article,Comment.new]
and still the comment isn't persisted. I am wondering because of the module namespace, do I have to do something different?
Add logger.info 'I am inside create action in comments controller' inside the create action. If you see this logger message in the rails console, then the create action gets called. It means your routes are defined correctly, your form is using the right form helper.
the correct format is form_for([#recipe, #comment]) however, I had a length validation in my comment model which was failing to pass. I set too_short and too_long messages, however they didn't show up, which further confused me

Rails 3 multi nested resource form

I have got such routes:
resources :projects do
resources :chats
resources :lists do
resources :issues
end
end
Now I am trying to setup proper form to add issue to list, but I do not know how... Currently it looks like this:
Controller:
def show
#project = Project.find(params[:id])
#list = List.new
#issue = #list.issues.build
#chats = #project.chats
#lists = #project.lists.includes(:issues)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #project }
end
end
Form
form_for [#list, #issue], remote: true do |f|
And I get error like this:
undefined method `list_issues_path' for #<#<Class:0x00000003996f30>:0x000000038ad678>
How should I solve it? Thanks in advance!
I believe that is because it would need to be nested under the project. If you run rake:routes I imaging you have something like projects/:id/lists/:id/issues/? You can see what the name of the route is next to that. Otherwise you can add the shallow option to the lists route.

Redirect works but render fails on the same path for my comment system

Hello guys~ I'm kind of new to rails here. And I have a controler like this in my create action, but my failed creation for a comment always direct to "Template Missing". I wonder how to solve that since my success is working alright with the same path ... thank you very much~
def create
#book = Book.find(params[:book_id])
#comment = #book.comments.build(params[:comment]) if signed_in?
#comment.user = current_user
if #comment.save
flash[:success] = "Comment posted"
redirect_to book_path(#book)
else
render book_path(#book)
end
end
Routes
resources :books do
resources :comments, only: [:create, :destroy]
end
Use render :show.
render does not accept a URL like this. It accepts the name of the template that you are rendering, among other things. Check out the documentation for more examples of what you can pass to render.

Creating a form for a different controller

I have several books that users can create and then create pages for them.
routes.rb:
resources :books do
member do
get 'pages'
end
end
This gives a link to create a new page through /books/:book_id/pages
In that page I render a partial:
<%= render '/pages/new' %>
book controller:
def page
#book = Book.find(params[:id])
#page = #book.pages.new
end
But when params are passed to a page controller the book_id is lost:
pages controller:
def create
#page = Page.new(params[:page])
if #page.save
redirect_to #page
else
render 'new'
end
end
Also error handling becomes difficult as after the redirect the id also disappears.
I believe rest of the application seems fine as when I create the page through console the book_id is preserved.
It is my first app so I'm not even sure if this is even the right way to approach it... How can I get this to work?
Thanks guys!
Nested resources can be handled in such a way.
# config/routes.rb
resources :books do
resources :pages
end
You can also restrict the actions being created by using only: [:index, :new] or except: [:destroy] on the resources call.
In your PagesController you would have the following params available.
GET /books/:book_id/pages/:id => creates a params[:book_id] and params[:id]
# app/controllers/pages_controller.rb
def create
#book = Book.find(params[:book_id])
#page = #book.pages.build(params[:page])
if #page.save
# ...
else
# ..
end
end
Note that the method call for building a new object through the association is #book.pages.build instead of .new. You'll find out all about Rails associations and how to build and create the objects through association in the Rails Guides on ActiveRecord associations. Hope these pointers help.
If you want to debug incoming parameters, you can just raise them as C404 suggested above.
# in any controller
def any_method
raise params.inspect
# or in yaml format
raise params.to_yaml
end
One way to debug this is to use "puts" in your controller for params to see what actually exists. "puts" are like println's in java or echo's in PHP
Please post the contents of params when ran with this code
def create
puts "params = #{params}"
#page = Page.new(params[:page])
if #page.save
redirect_to #page
else
render 'new'
end
end

rails Redirect to action incorrect URL

I have a scenario being:
resources :magazines do
resources :articles do
resources :comments
end
end
So as to avoid nesting more than 2 levels deep I have re-factored this to be:
resources :magazines do
resources :articles
end
resources :articles do
resources :comments
end
My article show action URL is:
/magazines/3/articles/11
In this view I have a form for creating a new comment.
When a comment is saved successfully the form redirects which all works well.
When the form submission is not successful I wish to redisplay the view with validations errors displayed. I understand the correct way to do this is to render the 'articles/show' view. This also works and the view is redisplayed with the validation errors shown.
The problem is when the save fails and articles/show is rendered the URL is no longer correct and is shown as:
/articles/11/comments
class ArticlesController < ApplicationController
def show
#article = Article.find(params[:id])
#comments = #article.comments.order(created_at: :asc).page(params[:page]).per_page(5)
#comment = Comment.new
end
end
class CommentsController < ApplicationController
def create
#article = Article.find(params[:id])
#comment = #article.comments.new(discussion_params)
#comment.user_id = current_user.id
if #comment.save
redirect_to #article
else
render 'articles/show'
end
end
private
def discussion_params
params.require(:comment).permit(:content)
end
end
I solved this by changing my routes back to the way it originally was and now the article show action includes the magazine in the url.
I understand this breaks the "no more than 2 levels deep" routing rule but it's the only way I can get it to work.

Resources