Rails 3 - rendering partials - ruby-on-rails-3

I have some problems with partial rendering in Rails.
This is in my routes.rb:
namespace :blog do
resources :posts, only: [:index, :show] do
resources :comments, only: [:new, :create]
end
end
This is my Blog::PostsController:
def show
#post = Post.find(params[:id])
#comments = #post.comments
end
This is in /views/blog/posts/show.html.erb
<%= render #comments %>
The _comment.html.erb partial is in /views/blog/comments/
The error message is:
Missing partial blog/comments/comment with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in: * "/home/mar1221/ruby/my_site/app/views"

Generally you'd pass the name of the partial (sans the underscore) like:
<%= render 'comment' %>
Which will attempt to render the partial _comment.html.erb from the view paths.
The partial can be in the same directory as the parent view, in the shared directory, or in any other directory that has been included in the view path.
Check out:
http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials for a more detailed explanation, and additional options you can use when rendering partials.

Related

Rails 3: Ajax nested resource delete

I have a nested resource model in my Rails 3 app. It is the standard blog app with posts and comments. I have just started using jQuery etc to make my app more dynamic, I am now struggling to remove comments in the nested model with the link_to helper.
Comments Model
class Comment < ActiveRecord::Base
belongs_to :post
end
Post Model
class Post < ActiveRecord::Base
has_many :comments, :dependent => :destroy
accepts_nested_attributes_for :comments
end
In my Posts/show.html.erb I have the following bloc that displays all the comments with a link_to helper to delete the comments. This works with HTML but when I added :remote => true, it deleted the parent post instead of the comment! How can I set it up so it deletes only the comment?
<% #post.comments.each do |comment| %>
<%= comment.body %>
<%= link_to "Approve", [#post,comment], :method =>:put, :remote=>true %>
<%= link_to "Delete", [#post,comment], :method =>:delete, :remote=>true %>
<%end%>
Thanks,
I think you want to have this in your delete action of your Comment class:
def delete
...
respond_to do |format|
format.html
format.js
end
end
Then, in your views/comments directory, you should have a file named delete.js.erb that does your jQuery DOM manipulation (finds the particular comment that you clicked the delete link of and remove it.
Then, your link_to for the delete method in your Posts/show.html.erb file, you can specify the controller and action, and also pass in any data you might need (the parent post so you can refer to it in your jQuery). You can refer to the first examples section of this site for the syntax on specifying a particular controller and action for a link_to helper here.
Just check the corresponding action in the controller.
If there is a render or redirect_to just delete it
it works for me (Rails 4)

link_to post ID in Rails

In my feed I have this:
<span class="title"><strong><%= link_to feed_item.title, #micropost %></strong></span><br>
I cannot figure out how to make it link to the individual pages for posts.
Right now it links to: http://localhost:3000/microposts and I get an error: No route matches [GET] "/microposts"
if I manually type the URL: http://localhost:3000/microposts/25 I can see the indivual page for the post.
This works fin linking to a user profile, but I can't get the link working to a micropost's page.
<%= link_to feed_item.user.name, feed_item.user %>
I'm new to rails and I'm trying to figure this out. Any help would be appreciated.
microposts_controller.rb
class MicropostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: :destroy
def index
end
def show
#micropost = Micropost.find(params[:id])
end
def create
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
#micropost.destroy
redirect_to root_url
end
private
def correct_user
#micropost = current_user.microposts.find_by_id(params[:id])
redirect_to root_url if #micropost.nil?
end
end
config/routes.rb
SampleApp::Application.routes.draw do
resources :users do
member do
get :following, :followers
end
end
resources :sessions, only: [:new, :create, :destroy]
resources :microposts, only: [:create, :destroy, :show]
resources :relationships, only: [:create, :destroy]
root to: 'static_pages#home'
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match '/help', to: 'static_pages#help'
match '/about', to: 'static_pages#about'
match '/contact', to: 'static_pages#contact'
end
_feed_item.html.erb
<li id="<%= feed_item.id %>">
<%= link_to gravatar_for(feed_item.user), feed_item.user %>
<span class="title"><strong><%= link_to feed_item.title, micropost_path(#micropost) %></strong></span><br>
<span class="user">
<p><small>Created by: <%= link_to feed_item.user.name, feed_item.user %><br>
<%= feed_item.loc1T %><br>
<%= feed_item.startTime.strftime('%A, %B %d, %Y') %></small></p>
</span>
<span class="content"><%= feed_item.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(feed_item.created_at) %> ago.
</span>
<% if current_user?(feed_item.user) %>
<%= link_to "delete", feed_item, method: :delete,
data: { confirm: "Are you sure?" },
title: feed_item.content %>
<% end %>
</li>
feed.html.erb
<% if #feed_items.any? %>
<ol class="microposts">
<%= render partial: 'shared/feed_item', collection: #feed_items %>
</ol>
<%= will_paginate #feed_items %>
<% end %>`
static_pages_controller
class StaticPagesController < ApplicationController
def home
if signed_in?
#micropost = current_user.microposts.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
def help
end
def about
end
def contact
end
end
Long answer
Rails generates a number of handy named routes for you when you add routes to your routes.rb file. Usually when in doubt for routes I take a look at my rake routes task which shows you a list of all available routes. Try running rake routes > routes.txt and open up the corresponding routes.txt file.
The resulting file will list out a series of requests for you, in your case you should see something similar to this for your microposts controller:
POST /microposts(.:format) microposts#create
micropost GET /microposts/:id(.:format) microposts#show
DELETE /microposts/:id(.:format) microposts#destroy
Rake routes produces the following information for each of your routes (where applicable):
The route name (if any)
The HTTP verb used (if the route doesn’t respond to all verbs)
The URL pattern to match
The routing parameters for the route
With that information in mind be can simply look at the urls provided in the routes.txt file for the url we're trying to get to (/microposts/25). You'll see that the listed /microposts/:id(.:format) url pattern handles that perfectly. Lo and behold it also maps to the microposts#show action that you want so now to get the named route just look at the first column to appear and you'll see the "microposts" keyword. Simply add _path` to this and you'll have your named route usable in views to generate link urls. Since this particular route requires an id parameter (as detailed in the url pattern) you have to pass the named route helper and id argument as well.
Also in your routes.rb file when you add resources :something it generates routes for each of the default seven RESTful routes (new, create, edit, update, delete, index, show). In your case you're explicitly telling rails to generate default routes for the actions create, destroy and show so you can erase the line at the bottom
match "/microposts/:id" => "microposts#show" because that's already being handled.
Short answer
Change this:
<%= link_to feed_item.title, #micropost %>
To this:
<%= link_to feed_item.title, micropost_path(feed_item) %>
See Ruby on Rails Guides: Rails routing from the Outside In for all you need to know about routes.

Nested resources create Couldn't find Topic without an ID

I wanna make an application which User can create a topic and others can make posts after that. I nested my resources in my routes.rb:
MyPedia2::Application.routes.draw do
resources :users
resources :sessions, only: [:new, :create, :destroy]
resources :topics, only: [:show, :create, :destroy]
resources :posts
resources :topics do
resources :posts, only: [:create, :show, :new]
end
In my topic show page , I want to show topic.title and sended Posts and post.form.html.erb.
Everything works accept when i create a post , I get mistake
ActiveRecord::RecordNotFound in PostsController#create
Couldn't find Topic without an ID..
This is my posts_controller.rb:
class PostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
before_filter :correct_user, only: :destroy
def new
#topic= Topic.find_by_id(params[:id])
#post = #topic.posts.build(params[:post])
end
def show
#topic = Topic.find(params[:id])
#posts = #topic.posts.paginate(page: params[:page])
end
def create
#topic = Topic.find(params[:id])
#post = #topic.posts.build(params[:post])
#post.topic = #topic
if #post.save
flash[:success] = "Konu oluşturuldu!"
redirect_to :back
else
render 'static_pages/home'
end
end
def destroy
#post.destroy
redirect_to root_path
end
private
def correct_user
#post = current_user.posts.find_by_id(params[:id])
redirect_to root_path if #post.nil?
end
end
and _post_form.html.erb:
<%= form_for #new_post do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "yorumunuzu girin..." %>
</div>
<%= f.submit "Gönder", class: "btn btn-large btn-primary" %>
<% end %>
There are a few things that should solve things for you.
First and foremost, your create action in the posts controller is a bit wrong - it should look something like this:
def create
#topic = Topic.find(params[:topic_id])
#post = #topic.posts.build(params[:post])
# This is unnecessary as you're already adding
# the post to the topic with the build statement.
# #post.topic = #topic
if #post.save
flash[:success] = "Konu oluşturuldu!"
redirect_to :back
else
render 'static_pages/home'
end
end
This controller action assumes that you're going to use a put request to a post resource that is nested in topics, so you'll have to clean up your routes.
You have routes to posts#create both nested and unnested.
If posts are ALWAYS supposed to be nested within a topic, which your controller logic is stating, then you should add this to the unnested posts resource:
resources :posts, except: [:new, :create]
and then change that form_for tag to this:
<%= form_for [#topic, #post] do |f| %>
This tells the form builder that you're using a nested resource and will use the correct url for the http request.
Also - it looks like you're using loading all of your topics using Topic.find(params[:id]). This isn't going to work - you're in the posts controller, this is a post id. You should be loading posts with the id param like this: Post.find(params[:id]) and then the topic like this: topic = post.topic

form_for - error accessing a controller variable in the view (rails 3)

I have a very simple model/view but for some reason I can't seem to access the new record variable and therefore get the error:
undefined method `hash_for_checklists_path' for # Module:<0x00000100f8b9b0>
I've hit my head against a wall on this for several hours. Can anyone see what I'm doing wrong?
Controller
class ChecklistsController < ApplicationController
def new
#title = "New Checklist"
#checklist = Checklist.new
end
[...]
end
(incidentally my application.html.erb file has no problem getting the #title variable.)
View (new.html.erb)
<%= form_for #checklist do |f| -%>
Routes.rb
devise_for :users
resources :checklist_item_categories, :as => 'item_categories' do
resources :checklist_items
end
resources :checklist_categories do
resources :checklists
end
match 'checklists/new', :to => 'checklists#new'
#pages
get "pages/home"
get "pages/contact"
#checklist items
get "checklist_items/new"
#checklists
get "checklists/new"
get "checklists/edit"
get "checklists/show"
get "checklists/index"
#categories
get "abstract_categories/new"
You don't have a path for the post from the form.
Maybe put
resources :checklists
in place of
#checklists
get "checklists/new"
get "checklists/edit"
...

Rails 3 path for edit and new actions in a basic form view

I have the following routes:
resources :categories do
resources :articles
end
And the following views:
# edit.erb and new.erb files:
<%= render :partial => 'form' %>
# top of _form.html.erb file:
<%= form_for category_article_path(#article.category, #article) do |f| %>
But I have some troubles with the given path. I work with Rails 3. Here is an example of error that I get when testing:
undefined method `category' for
nil:NilClass
What is the basic way to write a such path? Many thanks.
Just pass a freshly newed up article (with an existing category) instance to the view.