undefined method `comments_path' for #<#<Class:... > (RAILS) - ruby-on-rails

I'm trying to add comments to my photos model however when I submit my comment I am getting the following error:
undefined method `comments_path' for #<#<Class:0x007fdef11c3dd8>:0x007fdef4163f98>
My routes look like this:
resources :photos do
resources :comments
end
Models:
class Comment < ActiveRecord::Base
belongs_to :photo
end
class Photo < ActiveRecord::Base
belongs_to :user
has_many :comments, dependent: :destroy
end
views new comment:
<%= form_for [#picture, #comment] do |f| %>
<%= f.label :comments %>
<%= f.text_area :comments %>
<%= f.submit 'Leave Comment' %>
<% end %>
views index:
<% if #photos.any? %>
<% #photos.each do |photo| %>
<%= link_to photo.title, photo_path(photo) %>
<%= photo.description %>
<% if photo.comments.any? %>
<ul>
<% photo.comments.each do |comment| %>
<li>
<%= comment.comments %>
</li>
<% end %>
<% else %>
<p> No comments yet </p>
<% end %>
<% if current_user %>
<%= link_to "Comment on #{photo.title}", new_photo_comment_path(photo) %>
<% if current_user.id == photo.user_id %>
<%= link_to "Delete #{photo.title}", photo_path(photo), method: :delete %>
<% end %>
<% end %>
<br>
<% end %>
<% else %>
No photos yet
<% end %>
<br>
<%= link_to "Add a photo", new_photo_path %>
Comments Controller:
class CommentsController < ApplicationController
def new
#photo = Photo.find(params[:photo_id])
#comment = Comment.new
end
def create
#photo = Photo.find(params[:photo_id])
#photo.comments.create(comment_params)
redirect_to photos_path
end
def review_params
params.require(:comment).permit(:comments)
end
end
Please let me know if you need any further info, haven't posted much so still getting used to the format. Thanks all.
EDIT: Here is the error I am getting in full:
Error message

Problem was in the comments view:
<%= form_for [#picture, #comment] do |f| %>
<%= f.label :comments %>
<%= f.text_area :comments %>
<%= f.submit 'Leave Comment' %>
<% end %>
#picture was meant to be #photo. doh.

Related

Rails - Add multiple records in one form

I have a User model and Todo model. I want to be able to add multiple todos using a single form.
Routes:
# Users
resources(:users) do
resources(:todos)
end
User model:
class User < ApplicationRecord
has_many :todos
....
Todos controller:
class TodosController < ApplicationController
def new
#user = User.find(params[:id])
#todos = Array.new(10) {#user.todos.build}
end
....
View for todos/new:
<%= form_for([#user, :todos]) do |f| %>
<% #todos.each do |todo| %>
<%= f.text_field(:name, class: "form-control") %>
<% end %>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
What I get is:
undefined method `model_name' for :todos:Symbol
What am I doing wrong? I searched SO for doing multiple saves using one form, and I found this.
I believe you are looking for nested forms.
In your model you will add
accepts_nested_attributes_for :todos
and in your view
<%= form_for #user do |f| %>
TODO:
<ul>
<%= f.fields_for :todo do |todo| %>
<li>
<%= todo.label :todo %>
<%= todo.text_field :todo %>
</li>
<% end %>
</ul>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
in controller
def new
#user = User.find(params[:id])
10.times {#user.todos.build}
end
for refference http://guides.rubyonrails.org/form_helpers.html#nested-forms
NOTE: this code is untested
In your view, try
<%= form_for([#user, #user.todos]) do |f| %>
I'm also new to ruby but hopefully it works.

Getting "param is missing or the value is empty: post" explained below

when i click new post and try to save a new post it gives me that error, then i go to the controller :
private
def posts_params
params.require(:post).permit(:title, :description)
end
and change 'require(:post)' to 'require(:posts' then i works
but then i try to edit the new post i just created and when i click to save it it gives me the same error, then i just change it back to 'required(:post)' and it works, why this is happening ? it's like a loop, if one works the other doesn't and to work i have to change that one thing
Controller:
class PostsController < ApplicationController
def index
#posts = Post.all
end
def edit
#posts = Post.find(params[:id])
end
def update
#posts = Post.find(params[:id])
if #posts.update(posts_params)
redirect_to #posts
else
render 'edit'
end
end
def new
#posts = Post.new
end
def create
#posts = Post.new(posts_params)
if #posts.save
redirect_to #posts
else
render 'new'
end
end
def show
#posts = Post.find(params[:id])
end
private
def posts_params
params.require(:post).permit(:title, :description)
end
end
view edit:
<h1>Editing post</h1>
<%= form_for(#posts) do |f| %>
<% if #posts.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#posts.errors.count, "error") %> prohibited
this post from being saved:
</h2>
<ul>
<% #posts.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :description %><br>
<%= f.text_area :description %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Back', posts_path %>
view new:
<h1>New Article</h1>
<%= form_for :posts, url: posts_path do |f| %>
<% if #posts.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#posts.errors.count, "error") %> prohibited
this post from being saved:
</h2>
<ul>
<% #posts.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :description %><br>
<%= f.text_area :description %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Back', posts_path %>
can someone point the problem out ?
You are mixing
form_for(#posts) do |f|
and
form_for :posts, url: posts_path
In your forms.
the :posts version will generate params[:posts] and the #posts version will generate params[:post]. Hence the issue you are seeing. Make sure you posts_params is as follows.
def posts_params
params.require(:post).permit(:title, :description)
end
then just change both of your forms to be
<%= form_for(#posts) do |f| %>
rails will figure out which to call automatically for you, so you will not have to specify the paths..
On a side note, I would probably change #posts to be #post everywhere but the index action, just so that it makes more sense, Since in new,edit,etc.. you are dealing with a singular post.
Since rails is looking at the Model/class of the variable when generating the routes (When given an instance variable) the name of the variable doesn't matter to the framework, but makes it easier (in my opinion) for the programmer to understand

Rails 3: Why am I not able to see the input fields that should be generated by form_for?

What I see
The following is my Track template:
app/views/tracks/index.html.erb
<h1>Playlist</h1>
<%= form_for #track do |f| %>
<%= f.error_messages %>
<p>
<%= f.text_field :youtube_url %>
<%= f.submit 'Add' %>
</p>
<% end %>
<hr />
<% if Track.first == nil %>
<p>Database is empty!</p>
<%else%>
<% #tracks.each do |track| %>
<ul>
<li><%= track.youtube_url %></li>
</ul>
<% end %>
<% end %>
And clearly, the input fields are not being shown for some reason.
The other relevant files:
app/controllers/tracks_controllers.rb
class TracksController < ApplicationController
def index
#track = Track.new
#tracks = Track.all
end
def create
#track = Track.new(params[:track])
render :action=>"index"
end
def delete
#track = Track.find(params[:id])
#track.destroy
redirect_to(tracks_url)
end
end
routes.rb
Music::Application.routes.draw do
resources :tracks
end
track.rb
class Track < ActiveRecord::Base
attr_accessible :title, :youtube_url
end
What am I doing wrong?
You have to put <%= opening tag in your form_for instead of <%.
<%= form_for #track do |f| %>
<%= f.error_messages %>
<p>
<%= f.text_field :youtube_url %>
<%= f.submit 'Add' %>
</p>
<% end %>

Ruby on Rails. Views in polymorphic associations

I develop site which has articles and news pages and I would like to add opportunity to comment both. I use polymorphic associations.
class Article < ActiveRecord::Base
has_many :commentaries, :as => :commentable
end
class News < ActiveRecord::Base
has_many :commentaries, :as => :commentable
end
class Commentary < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
I would like to show comments below commentable object
views/articles/show.html.erb
<p>
<b>Title:</b>
<%= #article.title %>
</p>
<p>
<b>Short text:</b>
<%= #article.short_text %>
</p>
<p>
<b>Full text:</b>
<%= #article.full_text %>
</p>
<%= render 'commentaries/form' %>
views/news/show.html.erb
<p>
<b>Title:</b>
<%= #news.title %>
</p>
<p>
<b>Text:</b>
<%= #news.text %>
</p>
<p>
<b>Created:</b>
<%= #news.created %>
</p>
views/commentaries/_form.html.erb
<h1>Comments</h1>
<ul id="comments">
<% #commentaries.each do |comment| %>
<li><%= comment.content %></li>
<% end %>
</ul>
<h2>New Comment</h2>
<% form_for [#commentable, Comment.new] do |form| %>
<ol class="formList">
<li>
<%= form.label :content %>
<%= form.text_area :content, :rows => 5 %>
</li>
<li><%= submit_tag "Add comment" %></li>
</ol>
<% end %>
And my controllers:
class CommentariesController < ApplicationController
def index
#commentable = find_commentable
#commentaries = #commentable.commentaries
end
end
class ArticlesController < ApplicationController
def show
#article = Article.find(params[:id])
end
end
When I go to mysite/article/1 I get error undefined method `each' for nil:NilClass, because there isn't #commentable in my article controller and commentaries controller's code doesn't execute.
How to execute index action of commentaries controller on article/show page?
Add local variable:commentable => #article, while rendering the commentaries form
<%= render 'commentaries/form', :commentable => #article %>
Access the local variable from you partial view views/commentaries/_form.html.erb
<% commentable.commentaries.each do |comment| %>
...
<% end %>
...
<% form_for [commentable, Comment.new] do |form| %>
...
<% end %>

How to have a polymorphic model's partials associate to different things on the same page

Essentially, I have a binary voting system Like/Dislike. Thee class is called Like It has polymorphic associations to likeable:
class Like < ActiveRecord::Base
belongs_to :likeable, polymorphic: true
end
and we have the class Comment, which also has polymorphic associations to commentable and can be liked
class Comment < ActiveRecord::Base
belongs_to :commentable, polymorphic: true
has_many :likes, :as :likeable
end
We have the class Section, which can also be liked and commented on
class Section < ActiveRecord::Base
has_many :likes, as: :likeable
has_many :comments, as: commentable
end
However, on the page section#show I display the Section information, the section likes, and then the comments (from a comments/comments partial). Here is the Section#show view:
<h1><%= exercise.name %></h1>
<p><%= exercise.description %></p>
<%= render 'likes/like_button' %>
<%= render 'comments/comments' %>
<%= render 'comments/comment_form' %>
However, I want the ability to vote on each comment.
The following code is from the _comments.html.erb - What currently doesn't work is the rendering of the _like_button.html.erb because it doesn't apply to the comment at hand.
<% #comments.each do |comment| %>
<%= comment.content %>
<%= render 'likes/like_button' %>
<hr />
<% end %>
And here is the _like_button.html.erb partial
<% if #like.nil? %>
<%# No record of Like in table %>
<%= form_for [#likeable, Like.new] do |f| %>
<%= f.submit "Like" %>
<%= f.submit "Dislike" %>
<% end %>
<% else %>
<%# Marks current chosen option, if the opposite option is chosen, the record is updated to reflect the descion by the user %>
<%= form_for [#likeable, #like] do |f| %>
<% if #like.is_liked %>
Currently Liked!
<%= f.submit "Dislike" %>
<% else %>
<%= f.submit "Like" %>
Currently Disliked!
<% end %>
<% end %>
<% end %>
So ultimately, I just want to know how to make it possible to vote on a comment from within the Section#show view
Thanks!
Try this:
<% #comments.each do |comment| %>
<%= comment.content %>
<%= render 'likes/like_button', :like => comment.like, :likeable => comment %>
<hr />
<% end %>
<% if like.nil? %>
<%# No record of Like in table %>
<%= form_for [likeable, Like.new] do |f| %>
<%= f.submit "Like" %>
<%= f.submit "Dislike" %>
<% end %>
<% else %>
<%# Marks current chosen option, if the opposite option is chosen, the record is updated to reflect the descion by the user %>
<%= form_for [likeable, like] do |f| %>
<% if like.is_liked %>
Currently Liked!
<%= f.submit "Dislike" %>
<% else %>
<%= f.submit "Like" %>
Currently Disliked!
<% end %>
<% end %>
<% end %>

Resources