Rails Post comments nested within category - ruby-on-rails

I have a rails blog where all posts are nested under categories and now I am adding comments with are nested under posts but the form is throwing undefined method `post_comments_path' error.
I think I need to make the #posts something like #categories.post but I am unsure.
Routes
resources :categories do
resources :posts, path: 'article' do
resources :comments, :only => [:create]
end
end
Controller
def create
#post = Post.find(params[:post_id])
#comment = #posts.comments.create!(params[:comment])
redirect_to #post
end
View
<%= simple_form_for [#post, Comment.new ], :remote => true do |f| %>
<%= f.input :name %>
<%= f.input :email %>
<%= f.input :comment %>
<%= f.button :submit %>
<% end %>

I think you're forgetting categories. You need to either provide a category:
Controller
def new
...
#category = Category.find(params[:category_id])
...
end
def create
#post = Post.find(params[:post_id])
#comment = #posts.comments.create!(params[:comment])
redirect_to #post
end
View
<%= simple_form_for [#category, #post, Comment.new ], :url => category_post_comments_path, :remote => true do |f| %>
<%= f.input :name %>
<%= f.input :email %>
<%= f.input :comment %>
<%= f.button :submit %>
<% end %>
or remove categories from the routes like so:
Routes
resources :posts, path: 'article' do
resources :comments, :only => [:create]
end

Related

form_for nested resources(post, comment)

I have one question about form_for with nested resources. I create something like blog, with posts,comments, comments on comments(like replies).And I have an issue. Then I try to make comment it: "Redirected to http://localhost:3000/
Filter chain halted as :get_parent rendered or redirected
Completed 302 Found"
new.html.erb for comments:
<div class= "container" %>
<%= form_for #comment do |f| %>
<%= f.input :title %>
<%= f.text_area :body %>
<%= f.submit %>
<% end %>
</div>
My comments controller:
before_filter :get_parent
def new
#comment = #parent.comments.build
end
def create
#comment = #parent.comments.build(params[:comment])
#comment.user_id = current_user.id
if #comment.save
redirect_to posts_path(#comment.post), :notice => 'Thank you for your comment!'
else
render :new
end
end
private
def comment_params
params.require(:comment).permit(:body, :title, :user_id, :commentable_id, :commentable_type)
end
def get_parent
#parent = Post.find_by_id(params[:post_id]) if params[:post_id]
#parent = Comment.find_by_id(params[:comment_id]) if params[:comment_id]
redirect_to root_path unless defined?(#parent)
end
end
post model:
has_many :comments, as: :commentable
belongs_to :user
def post
commentable.is_a?(Post) ? commentable : commentable.post
end
comment model:
belongs_to :user
belongs_to :commentable, polymorphic: true
has_many :comments, :as => :commentable
routes:
resources :posts do
resources :comments
end
resources :comments do
resources :comments
end
post_show.html.erb
<h1><%= #post.title %></h1>
<div class="body">
<%= #post.body %>
</div>
<h2>Comments</h2>
<p><%= link_to 'Add a Comment', new_post_comment_path(#post) %></p>
<ul class="comment_list">
<%= render :partial => 'comments/comment', :collection => #post.comments %>
</ul>
github repo with app: https://github.com/Dmitry96/dasasd
Your new form does not pass neither post_id nor comment_id parameter. It should be eather in the form action url or in the form body.
I can not see all the picture, but I think you have to add parent id to the form action url. It is /comments now, has no parent id parameter in it. It must be /posts/:post_id/comments or /comments/:comment_id/comments.
Change your form to:
<%= form_for [#parent, #comment] do |f| %>
<%= f.input :title %>
<%= f.text_area :body %>
<%= f.submit %>
<% end %>

In rails, how to create forms for routes which are members of a resource?

I want to create a form for "Comments" route which is a member of Article Resources:
resources :articles do
member do
post 'comments'
end
end
I want the comment form to be in Articles#Show page. The problem i got an error:
First argument in form cannot contain nil or be empty
If the for is like this:
<div>
<%= form_for #comm do |c| %>
<%= c.label :Your_comment %>
<%= c.text_area :commBody %>
<%= c.submit 'submit' %>
<% end %>
</div>
So how to do it ?
If this is your controller,
def show
#article = Article.find(params[:id])
end
and you want to create a form for a new Comment related to #article that points to POST /articles/3/comments:
<%= form_for([#article, Comment.new], as: :article, url: comments_article_path(#article)) do |f| %>
<%= f.label :body %>
<%= f.text_area :body %>
<%= f.submit 'Submit' %>
<% end %>
Don't forget to add accepts_nested_attributes_for :comments in the Article model. And also don't forget to setup the whitelisted params in the ArticleController.
Another thing: don't use abbreviations for your variable names. Use #article and #comment, not #art and #comm.
#config/routes.rb
resources :articles do
post :comment, on: :member #-> url.com/articles/:id/comment
end
#app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def show
#article = Article.find params[:id]
#comment = #article.comments.new
end
end
#app/views/articles/show.html.erb
Comment:
<%= form_for [#article, #comment], url: article_comment_path(#article) do |c| %>
<%= c.label "Your Comment" %>
<%= c.text_area :commBody %>
<%= c.submit %>
<% end %>

Form inside a loop how to do it the Rails way?

Hi I have a working "blog module" on my page.
From the start. My routes looks like this:
root 'static_pages#home'
resources :announcements, only: [:new,:create,:update,:edit,:destroy,:show] do
resources :comments, only: [:create, :destroy]
end
My controller actions looks like this:
static_pages_controllers.rb
def home
#announcements = Announcement.page(params[:page]).order('id DESC')
end
announcements_controller.rb
def new
#announcement = Announcement.new
end
def create
#announcement = Announcement.new(announcement_params)
if #announcement.save
flash[:success] = "Post został pomyślnie dodany"
redirect_to root_path
else
render 'new'
end
end
comments_controller.rb
def create
#announcement = Announcement.find(params[:announcement_id])
#comment = #announcement.comments.new(comments_params)
if #comment.save
flash[:success] = "Komentarz dodano"
redirect_to root_path }
else
render 'staticpages#home'
end
end
Part of the home.html.erb which lists all anouncements and under each of them it adds a form to add a comment:
<% #announcements.each do |announcement| %>
.... some code ....
<% if current_user && user_signed_in? %>
<div class="create_comment" >
<%= render partial: 'shared/create_comments_form', locals: {announcement: announcement } %>
</div>
<% end %>
... some code ...
<% end %>
And _create_comment.html.erb :
<%= form_for announcement.comments.create, url: announcement_comments_path(announcement.id) do |form| %>
<%= form.label :author, "#{current_user.username}:" %>
<%= form.hidden_field :author, value: current_user.username %>
<%= form.hidden_field :user_id, value: current_user.id %>
<%= form.text_field :content, class: "form-control content_length" %>
<div class="char_counter">255</div>
<%= form.submit "Dodaj!", class: "btn btn-primary" %>
<% end %>
My question is there a better way of writing this form, because It just doesn`t look rails for me when I have to specify everywhere all those parameters. Eg. when I send parameters to _create_comment I have to pass announcement object, and in form it self I have to specify the url as it looks for create_comment_path by default.
I think you wanted just to handle nested resources, and need a form to create such a nested resource.
Then this should work:
form_for( [announcement, announcement.comments.new] ) do |form|
Do not use create in the form template, as it actually saves it to the database, you end with lots of empty comments just because somebody viewed the form.
You can use cokoon gem for this. This gem will create Dynamic nested forms using jQuery.
Also I have one more suggestion. Rather then using only you can use except. Because you have used all 6 routes without index.
root 'static_pages#home'
resources :announcements, except: [:index] do
resources :comments, only: [:create, :destroy]
end
Update:
You can use like below:
Form:
<%= form_for :comments do |form| %>
<%= form.label :author, "#{current_user.username}:" %>
<%= form.hidden_field :author, value: current_user.username %>
<%= form.hidden_field :user_id, value: current_user.id %>
<%= form.text_field :content, class: "form-control content_length" %>
<div class="char_counter">255</div>
<%= form.submit "Dodaj!", class: "btn btn-primary" %>
<% end %>
For more info: http://www.sitepoint.com/complex-rails-forms-with-nested-attributes/

How to access doubly nested models in rails?

I have a route that looks like this
resources :questions do
resources :answers do
resources :comments
end
end
However, when I try to build a comment
<%= form_for([#answer, #answer.comments.build]) do |f| %>
<p>
<%= f.label :comment %>
<%= f.text_area :comment, :cols => "50", :rows => "30"%>
</p>
<p>
I get undefined method comments. This is what my create comment looks like
def create
#answer = Answer.find(params[:answer_id])
#comment = #answer.comments.create(params[:comment])
redirect_to question_path(#question)
end
And answer has_many comments, and comments belongs to answer. Any ideas? Thanks!
You can access models from any controller in your app (just call Model.class_method)
Looking at your code, I'd recommend doing something like this:
#app/views/answers/show.html.erb
<% #answer.comments.each do |comment| %>
<%= comment.value %>
<% end %>
<%= form_for #new_comment do |f| %>
<%= f.text_area :comment, :cols => "50", :rows => "30"%>
<% end %>
#app/controllers/answers_controller.rb
def new
#answer = Answer.find(params[:id])
#new_comment = Comment.new
end
#app/controllers/comments_controller.rb
def create
#comment = Comment.new(comment_params)
#comment.save
end
private
def comment_params
params.require(:comment).permit(:your, :attributes, :here)
end

rails 4 how to pass post_id to the db

i have some problems with my app, i have posts, posts has_many responces
when i create new responce to the post, not added in the db 'responce' post_id
my routes.rb
resources :categories do
resources :posts
end
resources :posts do
resources :responces
end
controller
class ResponcesController < ApplicationController
def new
#post = Post.find(params[:post_id])
#responce = #post.responces.new(post_id:params[:post_id])
end
def create
#responce = current_user.responces.build(responce_params)
#post = Post.find(params[:post_id])
if #responce.save
flash[:success] = "Вы откликнулись на задание"
redirect_to post_path #post
else
render 'new'
end
end
def show
end
private
def responce_params
params.require(:responce).permit(:price, :comment, :post_id)
end
end
view
<%= form_for([#post, #responce]) do |f| %>
<%= f.text_area :price %>
<%= f.submit "GO", class: "btn btn-large btn-primary" %>
<% end %>
but if add to the view this
<%= f.collection_select :post_id, Post.all, :id, :name %>
rails create post_id to the db
help
You are doing several things the wrong way.
First: I don't think you need two separate resources for the same model. I'd recomend nesting all three resources upon each other like this.
resource :categories do
resource :posts do
resource :responces
end
end
This way you'll be able to find the needed category_id and post_id in the params hash.
I'd also recomend adding :shalow => true to the :categories resource to make your routes a bit prettier.
Second: you need to assign the params[:post_id] in your create action, like this.
#responce = current_user.responces.build(responce_params)
#responce.post_id = params[:post_id]
#post = #responce.post
Alternatevely you can just add a hidden field to your form like I show below, but it I don't like that approach, 'cause it can lead to security risks.
<%= form_for([#post, #responce]) do |f| %>
<%= f.text_area :price %>
<%= f.hidden_field :post_id, :value => #post.id %>
<%= f.submit "GO", class: "btn btn-large btn-primary" %>
<% end %>
In your form you aren't passing in the post_id. You probably want something like this:
<%= form_for([#post, #responce]) do |f| %>
<%= f.text_area :price %>
<%= f.hidden_field :post_id, :value => #post.id %>
<%= f.submit "GO", class: "btn btn-large btn-primary" %>
<% end %>
The hidden field will pass the id of the current post into your form as the post_id parameter.

Resources