I would like to be able to display the username of the person who commented on a post. I am having some difficulty displaying it. As the code stands right now I am getting an undefined method `user' for nil:NilClass on the view for line: <%= #comment.user.name %>. Thank you in advance again.
Comments Controller
class CommentsController < ApplicationController
before_filter :authenticate_user!
def new
#post = Post.find(params[:post_id])
#comment = Comment.new
end
def create
#post = Post.find_by_id(params[:post_id])
#comment = #post.comments.create(params.require(:comment).permit(:commenter, :body))
#comment.user = current_user
respond_to do |format|
if #comment.save
format.html { redirect_to #post, notice: 'Comment was successfully created.' }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
def show
#comment = Comment.new
end
private
def comment_params
params.require(:comments).permit(:commenter, :body)
end
end*
View / _comments
<%= div_for(comment) do %>
<p>
<strong>Posted <%= time_ago_in_words(comment.created_at) %> ago</strong></br>
<%= h(comment.body) %>
<%= #comment.user.name %>
<%= link_to 'Delete', [#post, comment], :method => :delete, :confirm => "Are you sure?" %>
</p>
<% end %>
User Model
has_many :comments
Comment Model
class Comment < ActiveRecord::Base
belongs_to :post
belongs_to :user
end
In your comments controller your should your create method should look like this:
def create
#comment = current_user.comments.new(comment_params)
respond_to do |format|
if #comment.save
format.html { redirect_to #comment, notice: 'Comment was successfully created.' }
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
Then in your view/_comments file you should have something like this:
Added:<%= time_ago_in_words(comment.created_at) %> ago<br>
Added by: <%= current_user.email %>
Let me know if this helps
With the Rails / REST convention, the show action is responsible for rendering a representation of a specific resource instance. To do that it takes an id from params, looks up resource instance by the id, and renders a response. Your show action should load an existing comment, rather than creating a new comment. A new comment won't have a user assigned, which is why you are getting an error for calling a method on a nil object - the user for the new comment has not been set.
In your show action try the following:
#commment = Comment.find params[:id]
<%= #comment.user.name %> should be <%= comment.user.name %> (no # before comment), because that view/partial is using a local variable at that point, not an instance variable.
Just a tip for your question: you should give a little more context for the view snippet. Is it a full view, a part of a view, or a partial? What's its filename/which controller action does it map to? If it's a partial, which view is it being rendered from?
I was able to resolve this. <%= current_user.name %> needed to be in my _comment view and I removed #comment.user = current_user from my Comments Controller. Thank you all for your help.
View / _comments.html
<%= div_for(comment) do %>
<p>
<strong>Posted <%= time_ago_in_words(comment.created_at) %> ago</strong></br>
<%= h(comment.body) %>
<%= current_user.name %>
<%= link_to 'Delete', [#post, comment], :method => :delete, :confirm => "Are you sure?" %>
</p>
<% end %>
Comment Controller
class CommentsController < ApplicationController
before_filter :authenticate_user!
def new
#post = Post.find(params[:post_id])
#comment = Comment.new
end
def create
#post = Post.find_by_id(params[:post_id])
#comment = #post.comments.create(params.require(:comment).permit(:commenter, :body))
respond_to do |format|
if #comment.save
format.html { redirect_to #post, notice: 'Comment was successfully created.' }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
def show
#commment = Comment.find params[:id]
end
Related
I am trying to make an app with Rails 4.
I have installed the public_activity gem.
I followed the Ryan Bates Railscast and took the controller based approach, and also the lighter Common option (as opposed to tracking the Model).
In my activities_controller I have:
class ActivitiesController < ApplicationController
def index
#activities = PublicActivity::Activity.order("created_at desc")
end
end
In my project.rb, I have:
include PublicActivity::Common
In my projects controller, create action, I have:
def create
logger.debug "xxx create project"
#authorise #project
#project = Project.new(project_params)
#project.creator_id = current_user.id
#project.users << current_user
#project.create_activity :create, owner: current_user
respond_to do |format|
if #project.save
format.html { redirect_to #project }
format.json { render action: 'show', status: :created, location: #project }
else
format.html { render action: 'new' }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
In my activity view - index, I have:
<% #activities.each do |activity| %>
<div class="col-md-4">
<div class="indexdisplay">
<span class="indexheading">
<%= link_to activity.owner.name, activity.owner if activity.owner %>
</span>
<span class="indexsubtext">
<%= render_activity activity %>
</span>
In my public activity (view folder)/project/_create.html.erb, I have:
<% if activity.trackable %>
<%= link_to activity.trackable.name, activity.trackable %>
<% else %>
which has since been removed
<% end %>
When I try this, it gives me a blank page (no new activities have been created). When I try to create a new project, I get stuck on submitting the form because I get this error:
ActiveRecord::RecordNotSaved at /projects
You cannot call create unless the parent is saved
The problem is this line in the create action of my projects controller.
#project.create_activity :create, owner: current_user
Is there somewhere else I can put this in the controller to make it run after the project is saved? I have read about call backs but they need to be in the model and I'd like to keep this process running from the controller.
As the error state, you are trying to create an activity to an unsaved Project. Move the creation of the activity after saving the #project:
def create
logger.debug "xxx create project"
#authorise #project
#project = Project.new(project_params)
#project.creator_id = current_user.id
respond_to do |format|
if #project.save
#project.users << current_user
#project.create_activity :create, owner: current_user
format.html { redirect_to #project }
format.json { render action: 'show', status: :created, location: #project }
else
format.html { render action: 'new' }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
I am trying to get a post and comment system working, for this however i want only one comment to be made per post. Only as i am trying to create a system as where content will be displayed followed by a comment 7 times in one post... Example...
program model 1 body content 1
Commentmodel1
program model 1 body content 2
Commentmodel2
program model 1 body content 3
Commentmodel3
.etc.etc.
For Me this is the simplest way of being able todo this by creating 7 different comment models, i know there is probably an easier way but as im new this seems the simplest. However i am struggling getting the one comment model to only allow just one comment to be made.
In this application coach is the user.
Here are the files involved, For the Models, program is the basic Post model, and comments is comments.
programs/Show.html.erb
<p id="notice"><%= notice %></p>
<p>
<b>Title:</b><br />
<%= #program.title %>
</p>
<p>
<b>Body:</b><br />
<%= #program.cweekcomments %>
</p>
<%= link_to 'Edit', edit_program_path(#program) %> |
<%= link_to 'Back', programs_path %>
<br /><br /><br />
<i>Comments</i>
<% #program.comments.each do |comment| %>
<p>
<b>Comment:</b>
<% if comment %>
<%= comment.body %>
<br />
<%= link_to 'Edit', edit_program_comment_path(#program, comment) %> | <%= link_to 'Destroy', [#program, comment] , method: :delete, data: { confirm: 'Are you sure?' } %>
<% else %>
<%= form_for([#program, #program.comments.build]) do |f| %>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
</p>
<% end %>
Programs_controller.rb
class ProgramsController < ApplicationController
before_filter :authenticate_coach!, :except => [:show]
# GET /programs
# GET /programs.json
def index
#programs = Program.find_all_by_coach_id(current_coach[:id])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #programs }
end
end
# GET /programs/1
# GET /programs/1.json
def show
#program = Program.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #program }
end
end
# GET /programs/new
# GET /programs/new.json
def new
#program = Program.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #program }
end
end
# GET /programs/1/edit
def edit
#program = Program.find(params[:id])
end
# POST /programs
# POST /programs.json
def create
#program = Program.new(params[:program])
respond_to do |format|
if #program.save
format.html { redirect_to #program, notice: 'Program was successfully created.' }
format.json { render json: #program, status: :created, location: #program }
else
format.html { render action: "new" }
format.json { render json: #program.errors, status: :unprocessable_entity }
end
end
end
# PUT /programs/1
# PUT /programs/1.json
def update
#program = Program.find(params[:id])
respond_to do |format|
if #program.update_attributes(params[:program])
format.html { redirect_to #program, notice: 'Program was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #program.errors, status: :unprocessable_entity }
end
end
end
# DELETE /programs/1
# DELETE /programs/1.json
def destroy
#program = Program.find(params[:id])
#program.destroy
respond_to do |format|
format.html { redirect_to programs_url }
format.json { head :no_content }
end
end
end
Comments_controller.rb
class CommentsController < ApplicationController
def new
#comment = #program.comments.build
end
def create
#program = Program.find(params[:program_id])
#comment = #program.comments.create(params[:comment])
redirect_to program_path(#program)
end
def destroy
#program = Program.find(params[:program_id])
#comment = #program.comments.find(params[:id])
#comment.destroy
redirect_to program_path(#program)
end
def edit
#program = Program.find(params[:program_id])
#comment = #program.comments.find(params[:id])
end
def update
#program = Program.find(params[:program_id])
#comment = #program.comments.find(params[:id])
respond_to do |format|
#if #program.comments.update_attributes(params[:comment])
if #comment.update_attributes(params[:comment])
format.html { redirect_to program_path(#program), notice: 'Comment was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
end
In advance, thanks for your help, much appreciated!
Change your program comment relation to has_one.(has_one :comment in your program.rb)
def create
#program = Program.find(params[:program_id])
if #program.comment
flash[:error] = "Cannot comment more than once"
else
#comment = #program.comments.create(params[:comment])
flash[:notice] = "Comment created"
end
redirect_to program_path(#program)
end
I am making a rails app, this is the error I get.
> NoMethodError in Posts#index
Showing C:/Users/Corey/Dev/statlog/app/views/posts/_form.html.erb where line #1 raised:
undefined method `post_post_post_path' for #<#<Class:0x38109f0>:0x2c54c58>
Extracted source (around line #1):
1: <%= form_for(#posts) do |f| %>
2: <div class="field">
3: <h2><%= f.label 'So, hows it going?', :class => 'nuvo' %></h2><br />
4: <%= f.text_area :status, :class => 'status-update' %>
Trace of template inclusion: app/views/posts/index.html.erb
Rails.root: C:/Users/Corey/Dev/statlog
Application Trace | Framework Trace | Full Trace
app/views/posts/_form.html.erb:1:in `_app_views_posts__form_html_erb___639176493_28084632'
app/views/posts/index.html.erb:10:in `_app_views_posts_index_html_erb___134739565_23263596'
app/controllers/posts_controller.rb:7:in `index'
Request
Parameters:
None
Show session dump
Show env dump
Response
Headers:
None
My posts_controller is :
class PostsController < ApplicationController
# GET /posts
# GET /posts.json
def index
#posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #posts }
end
end
# GET /posts/1
# GET /posts/1.json
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
# GET /posts/new
# GET /posts/new.json
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PUT /posts/1
# PUT /posts/1.json
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
end
AND finally, my _form.html.erb is:
<%= form_for(#posts) do |f| %>
<div class="field">
<h2><%= f.label 'So, hows it going?', :class => 'nuvo' %></h2><br />
<%= f.text_area :status, :class => 'status-update' %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
REALLY! Hope someone can help! Also this was working fine, then I used the console, and added a new post :status and then it started messing up! Please gimme some help!
~CoreyPizzle
Is your form trying to create a new post? You are giving her a variable with all the posts that exist instead of a new post.
Add this to your controller#index action:
#post = Post.new
And your form should handle the new post(#post) instead of all the posts (#posts):
<%= form_for(#post) do |f| %>
<%= f.label 'So, hows it going?', :class => 'nuvo' %>
<%= f.text_area :status, :class => 'status-update' %>
<%= f.submit "Create new status update"%>
<% end %>
Hi I'm currently receiving an error in my controller on submitting a form for creating an album. This is my first project and I am pretty shaky on controllers and what params to put and what to set the instance variables as... please help!!
on submission of my new.html.erb form, I receive
ActiveRecord::RecordNotFound in AlbumsController#create
Couldn't find User without an ID
here is my albums_controller
class AlbumsController < ApplicationController
def index
#albums = Albums.all
respond_to do |format|
format.html
format.json { render json: #albums }
end
end
def show
#albums = Album.all
#album = Album.find(params[:id])
#photo = Photo.new
end
def update
end
def edit
end
def create
#user = User.find(params[:user_id])
#user.album = Album.new(params[:album])
respond_to do |format|
if #user.album.save
format.html { redirect_to #user, notice: 'Album was successfully created.' }
format.json { render json: #album, status: :created, location: #album}
else
format.html { render action: "new" }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def new
#user = User.find(params[:user_id])
#album = Album.new
end
def destroy
end
end
here is the form I'm submitting
<%= form_for (#album), :html => { :id => "uploadform", :multipart => true } do |f| %>
<div>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description %>
<br>
<%=f.submit %>
Let me know if you need any more files.
In your createmethod you're trying to fetch a user from the database, based on params[:user_id], and params doesn't contain any user_id.
In this case I believe that it should come from the URL
So one solution if an album belongs to the user would be to set your routes like that :
resources :users do
resources :albums
end
Then you'll have to tell your form that the album is nested under a user byt explicitly giving the url. user_albums_path matches /users/:user_id/albums(.:format)
<%= form_for (#album), url: user_albums_path :html => { :id => "uploadform", :multipart => true } do |f| %>
<div>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description %>
<br>
<%=f.submit %>
The your create method you receive the user_id it need in the params.
Let me know if'm not clear enough or if you need more explanations
You should use the build method defined here
#user = User.find(params[:user_id])
#user.album = Album.new(params[:album])
to create the album, you should
#user = User.find(params[:user_id])
#user.albums.build params[:album])
this will automatically set the user_id attribute of the album to #user.id, you won't have anything to do
so your create method should be
def create
#user = User.find(params[:user_id])
#album = #user.albums.build params[:album]
respond_to do |format|
if #album.save
format.html { redirect_to user_path(#user), notice: 'Album was successfully created.' }
format.json { render json: #album, status: :created, location: #album} # I don't know what this location is
else
format.html { render action: "new" }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
Hi I'm trying to use a form as a partial for both the new/edit views of my albums controller/model. However, it's giving me the error when I try to edit the album:
No route matches [PUT] "/users/22/albums"
I think this might have to do with my form's :url. My form works fine when I submit it to create an album, but gets that error when I try to edit it.
I tried taking out the url: user_albums_path in my form, but it would just give me an error when I try to create a new album.
No route matches [POST] "/albums"
Is there any way to make it so that the form works for both actions? I feel like the :url can't coexist properly in both actions.
_form.html.erb
<%= form_for (#album), url: user_albums_path, :html => { :id => "uploadform", :multipart => true } do |f| %>
<div class="formholder">
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description %>
<br>
<%=f.submit %>
</div>
<% end %>
albums controller
class AlbumsController < ApplicationController
def index
#user = User.find(params[:user_id])
#albums = #user.albums.all
respond_to do |format|
format.html
format.json { render json: #albums }
end
end
def show
#user = User.find(params[:user_id])
#album = #user.albums.find(params[:id])
end
def update
#user = User.find(params[:user_id])
#album = #user.albums.find(params[:id])
respond_to do |format|
if #album.update_attributes(params[:album])
format.html { redirect_to user_album_path(#user, #album), notice: 'Album successfully updated' }
else
format.html { render 'edit' }
end
end
end
def edit
#user = User.find(params[:user_id])
#album = #user.albums.find(params[:id])
end
def create
#user = User.find(params[:user_id])
#album = #user.albums.build(params[:album])
respond_to do |format|
if #user.save
format.html { redirect_to user_album_path(#user, #album), notice: 'Album was successfully created.' }
format.json { render json: #album, status: :created, location: #album}
else
format.html { render action: "new" }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def new
#user = User.find(params[:user_id])
#album = Album.new
end
def destroy
end
end
please help!
update:
FIXED IT! on my own! the form just needed to be <%= form_for([#user, #album])...
Try
<%= form_for [#user, #album] %>
# other arguments can be inserted before the closing brace
That syntax properly scopes the resource routes
Remember to have an #album instance variable if you need one. You can build an empty album using #user.album.build