Objective is to edit an article comment.
However I can only figure out how to show a new comment field using <%= render 'form', comment: @comment %>
or the comment text that is already there using <%= render 'comment', comment: @comment %>
within edit.html.erb
Also tried changing <%= form_with model: [@article, @article.comments.build] do |form| %>
to <%= form_with model: @article.comment do |form| %>
but results in NoMethodError in Comments#edit
views/comments/edit.html.erb
<h1>Edit comment</h1>
<%= render 'comment', comment: @comment %>
comments/_form.html.erb
<%= form_with model: [@article, @article.comments.build] do |form| %>
<p>
<%= form.label :commenter %><br>
<%= form.text_area :commenter %>
</p>
<p>
<%= form.label :body %>
<%= form.text_area :body %>
</p>
<p>
<%= form.label :status %>
<%= form.select :status, ['public', 'private', 'archived'], selected: 'public' %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
comments/_comment.html.erb
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>
<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
<%= link_to "Edit comment", edit_article_comment_path(comment.article, comment) %>
<p>
<%= link_to "Destroy comment", [comment.article, comment], data: {
turbo_method: :delete,
turbo_confirm: "Are you sure?"
} %>
</p>
comments_controller.rb
class CommentsController < ApplicationController
http_basic_authenticate_with name: "dhh", password: "secret", except: [:index, :show]
def create
@article = Article.find(params[:article_id])
@comments = @article.comments.create(comment_params)
redirect_to article_path(@article)
end
def destroy
@article = Article.find(params[:article_id])
@comment = @article.comments.find(params[:id])
@comment.destroy
redirect_to article_path(@article), status: :see_other
end
def edit
@article = Article.find(params[:article_id])
@comment = @article.comments.find(params[:id])
end
def update
@article = Article.find(params[:article_id])
@comment = @article.comments.find(params[:id])
# redirect_to article_path(@comment)
if @comment.update(comment_params)
redirect_to @comment
else
render :edit, status: :unprocessable_entity
end
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
articles_controller.rb
class ArticlesController < ApplicationController
http_basic_authenticate_with name: "dhh", password: "secret", except: [:index, :show]
def index
@articles = Article.all
end
def show
@article = Article.find(params[:id])
end
def new
@article = Article.new
end
def create
@article = Article.new(article_params)
if @article.save
redirect_to @article
else
render :new, status: :unprocessable_entity
end
end
def edit
@article = Article.find(params[:id])
end
def update
@article = Article.find(params[:id])
if @article.update(article_params)
redirect_to @article
else
render :edit, status: :unprocessable_entity
end
end
def destroy
@article = Article.find(params[:id])
@article.destroy
redirect_to root_path, status: :see_other
end
private
def article_params
params.require(:article).permit(:title, :body, :status)
end
end
views/articles/show.html.erb
<h1><%= @article.title %></h1>
<p><%= @article.body %></p>
<ul>
<li> <%= link_to "Edit", edit_article_path(@article) %></li>
<li>
<%= link_to "Destroy", article_path(@article),
data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %>
</li>
</ul>
<h2>Comments</h2>
<%= render @article.comments %>
<h2>Add a comment</h2>
<%= render 'comments/form' %>
new comment/_form.html.erb
<%= form_with model: @comment do |form| %>
<p>
<%= form.label :commenter %><br>
<%= form.text_area :commenter %>
</p>
<p>
<%= form.label :body %>
<%= form.text_area :body %>
</p>
<p>
<%= form.label :status %>
<%= form.select :status, ['public', 'private', 'archived'], selected: 'public' %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
new articles_controller.rb
class ArticlesController < ApplicationController
http_basic_authenticate_with name: "dhh", password: "secret", except: [:index, :show]
def index
@articles = Article.all
end
def show
@article = Article.find(params[:id])
@comment = @article.comments.new
end
def new
@article = Article.new
end
def create
@article = Article.new(article_params)
if @article.save
redirect_to @article
else
render :new, status: :unprocessable_entity
end
end
def edit
@article = Article.find(params[:id])
end
def update
@article = Article.find(params[:id])
if @article.update(article_params)
redirect_to @article
else
render :edit, status: :unprocessable_entity
end
end
def destroy
@article = Article.find(params[:id])
@article.destroy
redirect_to root_path, status: :see_other
end
private
def article_params
params.require(:article).permit(:title, :body, :status)
end
end
With the inclusion of @comment = @article.comments.new
results in ActionController::UrlGenerationError in Articles#show
No route matches {:action=>"edit", :article_id=>"11", :controller=>"comments", :id=>nil}, missing required keys: [:id]
on 'show.html.erb' for an article. Without that and with the changes to form_with I am not able to create a comment - no errors are shown.
I found this post beacuse I had the same problem, and thanks to @Chiperific's response I found a solution for this. I have a similar situation, with object Shopping that has many Items objects.
These are my new and edit views for Items
<h2>Aggiungi articoli</h2>
<div id="divform">
<%= render 'items/form' %>
</div>
<h2>Modifica Articolo</h2>
<div id="divform">
<%= render 'items/form' %>
</div>
This is my _form.html.erb for Items
<%= form_with model: [ @shopping, @item ], remote: true do |form| %>
<div class="form-group">
<%= form.label :name %><br>
<%= form.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= form.label :quantity %><br>
<%= form.number_field :quantity, class: 'form-control' %>
</div>
<div class="form-group">
<%= form.label :unit_price %><br>
<%= form.number_field :unit_price, step: :any, class: 'form-control' %>
</div>
<div class="form-group">
<%= form.submit class: 'btn btn-primary' %>
</div>
<% end %>
These are my actions in the Items_controller
def new
@shopping = Shopping.find(params[:shopping_id])
@item = @shopping.items.new
end
def create
@shopping = Shopping.find(params[:shopping_id])
@item = @shopping.items.create(item_params)
@item.update(item_params)
redirect_to edit_shopping_path(@shopping)
end
def edit
@item = Item.find(params[:id])
@shopping = Shopping.find(@item.shopping_id)
end
def update
@item = Item.find(params[:id])
@shopping = Shopping.find(params[:shopping_id])
if @item.update(item_params)
redirect_to edit_shopping_path(@shopping)
else
render :edit, status: :unprocessable_entity
end
end
With this link I click to edit an Item object:
<%= link_to "Modifica", edit_shopping_item_path(item.shopping_id, item), class: 'btn btn-success btn-xs' %>
And in my form I can create an Item object for the New action, and if I click on the link to edit an Item, I see the form fields populated with the item properties' values, and if I submit the form, the Item object is updated. Thanks @Chiperific for your explanation