Comment created on articles page not saving to database - ruby-on-rails

Not sure why comments created on _comment_form.html.erb is not being rendered on articles/:id
I'm referencing this youtube tutorial: https://www.youtube.com/watch?v=IUUThhcGtzc
Comments controller:
class CommentsController < ApplicationController
before_action :authenticate_user!
before_action :set_article
def create
#comment = #article.comments.create(params[:comment].permit(:content, :article_id, :user_id))
#comment.user = current_user
#comment.save
if #comment.save
redirect_to #article
else
redirect_to #article
end
end
private
def set_article
#article = Article.find(params[:article_id])
end
end
Articles controller:
class ArticlesController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
before_action :set_article, only: [:show, :edit, :update, :destroy]
def show
#comments = Comment.where(article_id: #article).order("created_at DESC")
end
private
def set_article
#article = Article.find(params[:id])
end
end
_comment.html.erb (from articles/show.html.erb)
<%= render 'comments/comment_form' %>
<% #comments.each do |comment| %>
<%= comment.content %>
<% end %>
_comment_form.html.erb
<% if user_signed_in? %>
<%= form_for ([#article, #article.comments.build]) do |f| %>
<div class="form-group">
<%= f.label :content %>
<%= f.text_area :content, class: 'form-control' %>
</div>
<%= f.submit 'Post Comment', class: 'btn btn-primary' %>
<% end %>
<% end %>
routes.rb
resources :articles do
resources :comments
end

Some considerations I would like to do:
#comment.save
if #comment.save
When you do that, you're saving twice. Calling #comment.save on if condition already saves the article and return true or false if it was successful. Also, replace .save for .save!, so it will raise an exception in case it doesn't save, so you can check the reason on rails server log.
Also, think it's unnecessary to do this:
#comments = Comment.where(article_id: #article).order("created_at DESC")
Since you already set the #article, you can access #article.comments, once you put has_many :comments on article model.
You can also check on rails console if the Article was created correctly. Create a new one, and get it like article = Article.last, then you can check article.comments.
Hope this helps!

Related

Clicking on a Username of another user links to my profile instead of the user's profile

I need help with this my code,that displays list of posts of users along with their username.What i want is, when i click on a username of a particular post, it should send me to that user's profile. instead, it send's to my own profile or the current user's profile whiles i want it to link me to the username i have clicked profile. (e.g like when you click on a username on Instagram, it links you to the user's profile so you can follow or unfollow and see their post)
Please i need help. what i'm i not doing right in my code.
i'm on rails 5.2.3 & ruby 2.3.3
Home
<div class="posts">
<% #posts.each do |post| %>
<section class="post">
<div class="user">
<div class="avatar">
<img src="assets/avater.jpg">
</div>
<%= link_to post.user.username, user_path(post.user), class: 'username' %>
</div>
<%= image_tag post.image, class: 'main-image' %>
<div class="description">
<% post.description.to_s.split(' ').each do |word| %>
<% if word.start_with?('#') %>
<%= link_to word, search_index_path(query: word) %>
<% else %>
<%= word %>
<% end %>
<% end %>
</div>
</section>
<% end %>
<%= paginate #posts %>
</div>
routes
Rails.application.routes.draw do
get 'search/index'
devise_for :users
get 'home/index'
resources :posts
root 'home#index'
resources :users, only: [:show, :edit, :update]
resources :posts, only: [:new, :create, :show, :destroy]
end
users controller
class UsersController < ApplicationController
before_action :find_user
def show
#user = User.find(params[:id])
#posts = current_user.posts.order(created_at: :desc)
end
def edit
end
def update
current_user.update(user_params)
redirect_to current_user
end
private
def find_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:username, :name, :website,:bio, :email, :phone, :gender, :avatar)
end
end
post controller
class PostsController < ApplicationController
def new
#post = current_user.posts.build
end
def create
#post = Post.create(post_params)
redirect_to root_path
end
def show
#post = Post.find(params[:id])
end
def destroy
#post = current_user.posts.find(params[:id])
#post.destroy
redirect_to user_path(current_user)
end
private
def post_params
params.require(:post).permit(:description, :image, :user_id)
end
end
home controller
class HomeController < ApplicationController
before_action :authenticate_user!
def index
#posts = Post.order(created_at: :desc).page(params[:page]).per(5)
end
end
I guess the problem is that on the show method from users_controller, you are getting the posts from current_user instead of the user, it should be #posts = #user.posts.order(created_at: :desc)

Parameter is missing or the value is empty?

I am trying to access an "edit" link to edit an object, but I'm getting this error:
Param is missing or the value is empty: preview
Basically, I have 2 models that I linked through association:
Game model
Review model
I'm rendering reviews in the Game's show page. When I try to edit a review, it's saying I'm missing params or the value is empty in the Reviews controller.
The routes are also nested. How can I fix this?
Thanks in advance :)
routes.rb
Rails.application.routes.draw do
devise_for :users
root "games#index"
resources :games do
resources :news
resources :reviews, except: [:show, :index]
resources :previews, except: [:show, :index]
end
resources :platforms
resources :genres
end
show.html.erb (Linked to Games controller)
<% if #news.last.created_at > preview.updated_at %>
<p><%= link_to "edit", edit_game_preview_path(#game.id, preview.id) %></p>
<% end %>
<p><%= link_to "delete", game_preview_path(#game.id, preview.id), method: :delete %></p>
<% end %>
Reviews partial (Form)
<%= form_for [#game, #previews.new] do |r| %>
<h3 class="post_review">Preview this game</h3>
<p><%= flash[:notice_submit] %></p>
<p><%= r.text_field :title, placeholder: "Enter your tagline" %></p>
<p><%= r.text_area :content, placeholder: "Enter your review here" %></p>
<p><%= r.text_area :vote %></p>
<p><%= r.hidden_field :game_id, value: #game.id %></p>
<%= r.submit %>
<% end %>
Reviews controller
class PreviewsController < ApplicationController
before_action :authenticate_user!
before_action :set_preview, only: [:show, :edit, :update, :destroy]
before_action :set_game
def new
#preview = Preview.new
end
def create
#preview = Preview.new(preview_params)
#preview.user_id = current_user.id
#preview.game_id = #game.id
#preview.username = current_user.username
if #preview.save
redirect_to :back
flash[:notice_submit] = "Thanks for you comment!"
else
redirect_to :back
flash[:notice_submit] = "Either you've already voted, or you're not filling in all forms."
end
end
def edit
#preview.update(preview_params)
redirect_to #game
end
def destroy
#preview.destroy
redirect_to #game
end
private
def set_preview
#preview = Preview.find(params[:id])
end
def set_game
#game = Game.find(params[:game_id])
end
def set_user
#user = User.find(params[:user_id])
end
def preview_params
params.require(:preview).permit(:title, :content, :vote)
end
end
You are getting this error because in your preview_params you are requiring a preview object.
I think your controller logic for the edit action is invalid. For the edit action, you just need to set_preview and then render the edit template. The current logic in your edit action should go in an update action.
def edit
end
def update
#preview.update(preview_params)
redirect_to #game
end
Also the first line of your form should be:
<%= form_for [#game, #preview] do |r| %>

First argument in form cannot contain nil or be empty with Gamepost

Recieve this error in my Game page in Rails 4
ActionView::Template::Error (First argument in form cannot contain nil or be empty):
_Gamepost_form.html.erb
<%= form_for (#gamepost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new game sale..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
Controller
class GamepostsController < ApplicationController
before_action :signed_in_user, only: [:create, :destroy, :]
before_action :correct_user, only: :destroy
def index
#gamepost = current_user.gameposts.build
end
def create
#gamepost = current_user.gameposts.build(gamepost_params)
if #gamepost.save
flash[:success] = "Game Sale created!"
redirect_to root_url
else
#gamefeed_items = []
render 'static_pages/home'
end
end
def destroy
#gamepost.destroy
redirect_to root_url
end
private
def gamepost_params
params.require(:gamepost).permit(:content)
end
def correct_user
#gamepost = current_user.gameposts.find_by(id: params[:id])
rescue
redirect_to root_url
end
end
Have a similar example using microposts and its working fine no idea why this instance is not working
After the answer Vee provided,
ActionView::Template::Error (undefined method `any?' for nil:NilClass):
1: <% if #gamefeed_items.any? %>
2: <ol class="gameposts">
3: <%= render partial: 'shared/gamefeed_item', collection: #gamefeed_items %>
This shows up in same page
Following up in the comments in your question.
Looks like you are rendering that form from your index action.
class GamepostsController < ApplicationController
before_action :signed_in_user, only: [ :index, :create, :destroy]
...
def index
#gamepost = current_user.gameposts.build
end
...
end
Note that, you also need to add :index and not :new in before_action :signed_in_user. This is to ensure that the current_user becomes available in so that current_user.gameposts.build does not fail!

Why isn't this portion of HTML rendering and why do I get a undefined method `cardsets' for nil:NilClass in Rails?

I'm trying to add a flashcards(cardsets) feature in Rails and I'm having some problems implementing this as I'm getting an undefined methodcardsets' for nil:NilClass` error
I can get the page to render if I change: <% if #user.cardsets.any? %> to <% unless #cardsets.any? %> but the corresponding cardsets are being shown when I do this.
Here is the html.erb code that is producing this error:
<% provide(:title, "Flashcards") %>
<h1>Flashcards</h1>
<div class="row">
<aside class="span3">
<%= render "shared/cardset_form" %>
</aside>
<div class="span6">
**<% if #user.cardsets.any? %>**
<h3>Flashcard Sets (<%= #user.cardsets.count %>)</h3>
<ol class="cardsets">
<% #user.cardsets.each do |cardset| %>
<li>
<span class="topic"><%= link_to cardset.topic, show_cardset_path(cardset) %></span>
<%= link_to "edit", edit_cardset_path(cardset) %>
<%= render partial: "shared/delete_link", locals: {item: cardset} %>
</li>
<% end %>
</ol>
<% end %>
</div>
</div>
I've starred the line that is producing the undefined methodcardsets' for nil:NilClass` error.
This is what's in my cardsets_controller.rb:
class CardsetsController < ApplicationController
before_action :signed_in_user, only: [:new, :index, :create, :edit, :destroy, :update]
before_action :correct_user, only: [:edit, :update, :destroy]
def index
#cardsets = Cardset.all
end
def show
#cardset = Cardset.find(params[:id])
end
def create
#cardset = current_user.cardsets.build(cardset_params)
if #cardset.save
flash[:success] = "A new set of flashcards have been created!"
redirect_to #cardset
else
render "new"
end
end
def new
#cardset = Cardset.new
end
def edit
end
def update
#cardset = Cardset.find(params[:id])
if #cardset.update_attributes(cardset_params)
flash[:success] = "You've updated your flashcards!"
redirect_to #cardset
else
render "edit"
end
end
def destroy
#cardset = Cardset.find(params[:id])
#cardset.delete
redirect_to cardsets_path
end
private
def cardset_params
params.require(:cardset).permit(:topic, :description)
end
def correct_user
#cardset = current_user.cardsets.find_by_id(params[:id])
redirect_to root_url if #cardset.nil?
end
end
Here is the code in my cardset.rb file:
class Cardset < ActiveRecord::Base
belongs_to :user
validates :user_id, presence: true
validates :topic, presence: true
end
Here is the code in my user.rb file:
class User < ActiveRecord::Base
has_many :cardsets
(...a bunch of other code...)
end
If anyone could provide some help or suggestions on where I may be going wrong I'd greatly appreciate it!
Thanks!
As far as I can tell, you aren't setting #user in your Controller, so #user is nil.
You probably want to either define #user or maybe you meant to use #cardsets.

Hartl's rails tutorial error "Couldn't find User with id=#<User:0x00000007472a28>"

I'm working through Michael Hartl's ruby on rails tutorial without too much trouble (at least not much I haven't been able to solve with a bit of looking/thinking/searching) but I'm stuck on an error I get when trying to implement the relationships model in chapter 11.
Specifically, hitting the follow/unfollow button returns the following error:
ActiveRecord::RecordNotFound in RelationshipsController#create
Couldn't find User with id=#<User:0x007f3288020d98>
Extracted source (around line #5):
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
redirect_to #user
end
I can tell that the problem is that the userid it's searching should just be an integer, not anything like #, but I'm not sure why it's searching something that looks like a hex code instead of the userid.
The RelationshipsController is exactly the same as given in the tutorial:
class RelationshipsController < ApplicationController
before_action :signed_in_user
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
redirect_to #user
end
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
redirect_to #user
end
end
The only significant difference I can think of is that I'm using postgres instead of sqlite, but since switching to postgres was given as an exercise I can't imagine it would cause this sort of problem.
I tried searching for similar issues, but I couldn't find anything - any help would be great.
(edit)
The form that renders the follow/unfollow buttons is:
<% unless current_user?(#user) %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
And the buttons themselves:
<%= form_for (current_user.relationships.build(followed_id: #user)) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
and
<%= form_for(current_user.relationships.find_by(followed_id: #user), html: { method: :delete }) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
The show method of the UsersController is
class UsersController < ApplicationController
before_action :signed_in_user, only: [:index, :edit, :update, :destroy, :following, :followers]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def show
#user = User.find(params[:id])
#microposts = #user.microposts.paginate(page: params[:page])
if current_user?(#user)
#micropost = current_user.microposts.build
end
end
.
.
.
You want the id of the user not the user object itself so change the partial for the follow to have:
followed_id: #user.id instead of followed_id: #user

Resources