I have user model that has many reviews, and each review has many replies.
I want to allow the user to reply under a review.
In a profile page (coming from a profile controller and show action), I want to be able to create replies.
<div class="reply-box d-none" id="reply-box">
<%= form_with(model: Reply, url: new_user_review_reply_path(#user, #review)) do |reply| %>
<%= reply.hidden_field :user_id, value: #user %>
<%= reply.hidden_field :review_id, value: #review %>
<%= reply.text_field :reply_content%>
<div class="comment-box-btns mb-5">
<%= reply.submit "submit", class: 'submit-btn d-inline-block ml-2 float-right'%>
<div class="cancel-btn d-inline-block float-right">cancel</div>
</div>
<% end %>
</div>
Here is the route.rb
resources :users do
resources :reviews do
resources :replies
end
end
Here is the reply controller:
class RepliesController < ApplicationController
def new
#user = User.find(params[:user_id])
#reivew = #user.reviews.find(params[:review_id])
#reply = #reivew.replies.new
end
def create
#user = User.find(params[:user_id])
#reivew = #user.reviews.find(params[:review_id])
#reply = #reivew.replies.create!(reply_params)
respond_to do |format|
format.html {redirect_to(profile_path(param[:user_id]))}
format.js
end
end
private
def reply_params
params.require(:reply).permit(
:reply_content,
:user_id,
:review_id
)
end
end
I don't know how to set up the "form_with". So far it just says
undefined method `reply_content' for #<Class:0x007f8c7396aaa8>
reply_content is the field in reply I want to create using the text_area.
I am very confused. Any help would be greatly appreciated.
As you have already intitilize #reply = #reivew.replies.new in new action so you should use this #reply object with reply form, also i don't think that you need not to explicitly provide value: user_id and value: review_id
<div class="reply-box d-none" id="reply-box">
<%= form_for #reply, url: new_user_review_reply_path(#user, #review) do |reply| %>
<%= reply.hidden_field :user_id %>
<%= reply.hidden_field :review_id %>
<%= reply.text_field :reply_content%>
<div class="comment-box-btns mb-5">
<%= reply.submit "submit", class: 'submit-btn d-inline-block ml-2 float-right'%>
<div class="cancel-btn d-inline-block float-right">cancel</div>
</div>
<% end %>
</div>
I managed to link comments to their posts in rails but the remaining thing is displaying them and here is my view(simplified) :
the thing is that iam iterating through post.all and each post has_many :comments and each comment has comment.description comment.image so how can I get to show the comment for each of the iterated posts is it by another iteration ?
_profile.html.erb :
#posts.each do |x|
<div class="eachpost-wrapper">
<%= x.text %>
<%= x.picture %>
<div class="comments-for-each-post">
<<<<<<<<< the post comments are supposed to be here <<<<<<
</div>
</div>
<% end %>
accounts controller :
def profile
#posts = User.find(params[:id]).posts
#comment = Comment.new
end
comments controller :
def new
#comment = Comment.new
end
def create
#post = Post.find(params[:id])
#comment = #post.comments.new
if #comment.save
redirect_to "success/success"
else
redirect_to 'error/error404'
end
Yes, it is by another iteration. Something along the lines of:
<div class="posts-wrapper">
<% #posts.each do |post| %>
<div class="post-wrapper">
<%= post.text %>
<%= post.picture %>
<div class="comments-wrapper">
<% post.comments.each do |comment| %>
<div class="comment-wrapper">
# do stuff with comment here...
</div>
<% end %>
</div>
<div class="new-comment-wrapper">
# put a new comment form in here...
</div>
</div>
<% end %>
</div>
Keeping in mind what MrYoshiji said about eager loading...
when I attempt to run my code, I got the error above.
As you can see on the following image, the page posts/index leaves appear some information before the footer of the page :
I don't understand where it may come, because it's the only page where it appeared.
Here's my view :
<%= #post.each do |post| %>
<h1 class="Blog_post_title"><%= link_to post.title, post %></h1>
<p class="date"><%= post.created_at.strftime("%B, %d, %Y") %></p>
<p><%= image_tag post.landing_image.url , class: "landing_image_blog" %></p>
<p><%= post.body %></p>
<%= link_to post do %>
<div class="button12">Continuer la lecture</div>
<% end %>
<div class="border_grey_blog"></div>
<% end %>
</div>
<%= render "footer" %>
my posts_controller.rb:
class PostsController < ApplicationController
def index
#post = Post.all.order('created_at DESC')
end
def new
#post = Post.new
end
def show
#post = Post.find(params[:id])
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:title,:title2,:title3,:title4,:title5,:title6,:title7,:title8,:title9, :body, :image,:image1,:image2,:image3,:image4,:image5,:image6,:image7,:image8, :landing_image, :some_text1, :some_text2, :some_text3, :some_text4, :some_text5, :some_text6, :some_text7, :some_text8, :some_text9, :some_text0))
redirect_to #post
else
render 'edit'
end
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to "/posts"
end
private
def post_params
params.require(:post).permit(:title, :body, :image,:image1,:image2,:image3,:image4,:image5,:image6,:image7,:image8, :landing_image, :some_text1, :some_text2, :some_text3, :some_text4, :some_text5, :some_text6, :some_text7, :some_text8, :some_text9, :some_text0, :title2,:title3,:title4,:title5,:title6,:title7,:title8,:title9)
end
end
Any idea ?
Your mistake is in the very first line of the view:
<%= #post.each do |post| %>
should be
<% #post.each do |post| %>
since <%= opens an expression tag that will display its content.
It looks like your outputting the result of #posts.each. Notice how you did this in your view:
<%= #post.each do |post| %>
# other code
<% end %>
This will actually output all the data in the array as a ruby object. If you want to change this to not output everything, you need to change it to
<% #post.each do |post| %>
# other code
<% end %>
This will now not return the #post.each in the html.
I'm a Rails newbie and this seems like a trivial thing, but I can't figure out how to render this.
I have a form that takes in a string input:
<%= form_for #idea do |f| %>
<div>
<%= f.label :idea_list %>
<%= f.text_field :idea_list %>
</div>
<%= f.submit %>
<% end %>
And a controller:
class IdeasController < ApplicationController
def index
end
def new
#idea = Idea.new
end
def create
#idea = Idea.new(idea_params)
if #idea.save
render :index
else
render 'new'
end
end
private
def idea_params
params.require(:idea).permit(:idea_list)
end
end
I then want to render the idea_list parameter in index.html.erb, but cannot figure out how to do so. I've tried:
<p><%= #idea %></p>
but I get an output of #<Idea:0x007f8b16d98638>.
<% #idea do |idea| %>
<p><%= idea.idea_list %></p>
<% end %>
I've tried many variations of this but keep getting various errors.
Please help.
So #idea is an instance of an object. idea_list is an attribute. So you need to call #idea.idea_list. Any time you want to reference an instance of an object / model from a controller it's going to #instance.attribute.
In your case, it's going to be
<p><%= #idea.idea_list %></p>
If you want to show them from a list of the all, in your view it's
<%#ideas.each do |idea| %>
<p><% idea.idea_list%></p>
<% end%>
And in your controller it's
def index
#ideas = Idea.all
end
I have comments as a subresource of articles, as below:
resources :articles do
resources :comments
end
I want each Article's show page to display all of its corresponding comments, as well as have a form where a user (if signed in) can create a new comment that corresponds with the article.
Here's the show action for ArticlesController:
def show
#comment = #article.comments.build
if user_signed_in?
#comment.user_id = current_user.id
end
respond_with(#article)
end
Here's relevant code from the CommentsController:
before_action :set_article
...
def create
#comment = #article.comments.create(comment_params)
#comment.user_id = current_user.id
if #comment.save
flash[:notice] = "Comment successfully created!"
end
redirect_to #article
end
...
private
def set_article
#article = Article.find(params[:article_id])
end
end
And here's the Article show view:
<b>Post comments:</b><br />
<table>
<thead>
<tr>
<th>User email</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
<% #article.comments.each do |comment| %>
<tr>
<td><%= comment.user.email %></td>
<td><%= comment.body %></td>
</tr>
<% end %>
</tbody>
</table>
<br />
<%= form_for ([#article, #comment]) do |f| %>
<div class="field">
<%= f.text_area :body, placeholder: "Compose new comment..." %>
</div>
<%= f.submit "Post" %>
<% end %>
Here's the two situations I need to fix:
When no user is signed in, the view fails to render because comment.user returns nil
When a user is signed in, a phantom comment for each article appears, because the show action in the ArticlesController is building a new (empty) comment with #comment = #article.comments.build
What is the best way to simultaneously solve both of these problems?
If you don't want to do that in the view, you can do this sort of thing in the controller.
def show
#comment = Comment.new(:article => #article)
respond_with(#article)
end
This won't add the comment to the article.comments array and won't try to render a blank comment.
Do you need to set the user_id on the comment in the form on the show action? If not, you can do this in create
def create
#comment = Comment.new(comment_params)
#comment.article = #article
#comment.user = current_user
if #comment.save
flash[:notice] = "Comment successfully created!"
redirect_to #article
else
render :show
end
end
The benefit to this - you can now handle errors in the form (like if they submit a blank comment, or minimum characters). Even if you handle it in the view with javascript/disabled buttons, it's nice to have the server also support validations and errors.
Just kidding, got it.
Put the build call into the form rather than the ArticleController:
<%= form_for ([#article, #article.comments.build]) do |f| %>
<div class="field">
<%= f.text_area :body, placeholder: "Compose new comment..." %>
</div>
<%= f.submit "Post" %>
<% end %>
and delete everything out of the show action:
def show
respond_with(#article)
end