saving comments object with relationship to a status update .build ruby - ruby-on-rails

I have a status update, and comment db table.
A user has many status updates, and a status update has many comments. Similar to facebook, When a users friend goes to the users feed page (show page), they should be able to comment on the users status updates.
I'm having issues saving a users friends comment.. my code is below.. I think it has something to do with the Comments Controller, Create method, "#comment = #statusupdate.comments.build(params[:comment])"
any guidance is much appreciated! thanks!
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#statusupdates = #user.statusupdates.paginate(:page => params[:page], :per_page => 25)
#statusupdate = Statusupdate.new
#comment = Comment.new
end
end
show.html.erb
<% form_for #statusupdate do |f| %>
<%= f.error_messages %>
<div class="field">
<%= f.text_field :content %>
</div>
<% #statusupdates.each do |s| %>
<%= s.content %><br />
<% form_for #comment do |f| %>
<%= f.error_messages %>
<div class="field">
<%= f.text_field :comment %>
</div>
<div class="field">
<%= f.hidden_field :user_id, :value => current_user.id %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<br><br>
<% end %>
<% end %>
class CommentsController < ApplicationController
def create
#comment = #statusupdate.comments.build(params[:comment])
if #comment.save
flash[:success] = "Comment created!"
redirect_to root_path
else
#feed_items = []
render 'pages/home'
end
end
end

Check the html of the form to make sure its right. Also see what parameters are getting sent to the create action.
The main thing I see is that the forms for the status update and the comments are nested, and both use the block parameter f. This could cause things to get very strange (especially since the scoping of block parameters differs between ruby 1.8 and 1.9). It also seems like you don't actually want the forms nested. You should also probably fix the indentation in your html.

show.html.erb- I changed the top line of the status update comment form to:
<% form_for (s, s.comments.build) do |f| %>
...
class CommentsController < ApplicationController
def create
#statusupdate = statusupdate.find(params[:statusupdate_id])
#comment = #statusupdate.comments.create(params[:comment])
...
I don't exactly know what's going on here but it worked for me~ hope it helps someone out~

Related

ruby on rails nested form create

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>

Wrong number of arguments error (0 for 1) in Ruby on Rails 4 when creating a form for user submission

at the moment I am attempting to create a form for my website that will allow for users to input information and then the information with be POST'ed to my database for storage. I am a new ruby on rails developer so keep that in mind.
I was able to get to the point where the user could see the form and type in information but once they hit the submit button I recieve an error, and that error is
ArgumentError in StudentsController#create
wrong number of arguments (0 for 1) in app/controllers/students_controller.rb:13:in `create'
The parameters that were sent were the following
{"utf8"=>"✓",
"authenticity_token"=>"bLalQ9Ek5ziaGiGHj03AGPCTIABAgcT+o4eTgN44qv44dxNDlrGA0h2u5BSTQVTMh+YgA/mLPQee05lT7mxCsw==",
"student"=>{"first_name"=>"Andrew",
"last_name"=>"Terra"},
"commit"=>"Submit"}
Below is my students_controller.rb file.
class StudentsController < ApplicationController
def index
#students = Student.all
end
def new
#student = Student.new
end
def create
#student = Student.new(params.require[:student])
if #student.save
redirect_to students_path
end
end
def destroy
#student = Student.find_by_id(params[:id])
if #student.destroy
redirect_to students_path
end
end
end
Below is my views/students/_form.html.erb file
<%= form_for #student do |f| %>
<p>
<%= f.label :first_name %>
<%= f.text_field :first_name %>
</p>
<p>
<%= f.label :last_name %>
<%= f.text_field :last_name %>
</p>
<%= f.submit "Submit" %>
<% end %>
Below is my /views/students/index.html.erb file
<%= link_to "Create new information", new_student_path %> <br /> <hr>
<% #students.each do |fo| %>
Firstname: <%= fo.first_name %> <br />
Lastname: <%= fo.last_name %> <br />
<%= link_to "Delete info?", student_path(student), :data=>{:confirm=>"Are you sure ?"}, :method=> :delete %>
<br />
<hr>
<% end %>
Finally, here is my /views/students/new.html.erb file
Enter new info
<hr>
<%= render :partial => "form" %>
And I did remember to put resources :students in my routes file. I searched around and found other people who had previously had this problem but none of the solutions worked on the code that I have written. So I was wondering if anyone could point me in the direction of where the bug is and how exactly I can fix it. Thank you.
You need to add a new private method:
private
def student_params
params.require(:student).permit(:first_name, :last_name)
end
And then as said before change your create method to:
def create
#student = Student.new(student_params)
if #student.save
redirect_to students_path
end
end
I recommend reading the documentation on Strong Parameters - to better understand how they work. https://github.com/rails/strong_parameters
You have to change
params.require[:students] to params.require(:students)
But this is still not good way to handle your params for create action, you should add private method student_params to your controller where you would whitelist your params. Like this:
def student_params
params.require(:student).permit(:first_name, :last_name)
end
Here you can find more about it,
http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html

Form resulting in blank post with no ID

I am new to Rails and working on creating a generic "facebook" type of app as practice with users and posts associated with each user. However, I'm currently having an issue where I think the form that I am using to create the posts is also being rendered out as a blank post with no post ID where I display all of the posts in a section below. I think that this post is being shown even before it is being saved to the database.
Here is my code in my view:
<div class="newpostcontainer">
<div class="newposttext">
<%= form_for([#user, #user.posts.build]) do |f| %>
<%= f.text_area :post, size: "69x1" %>
</div>
<div class="newpostsubmitbutton">
<%= f.submit %>
</div>
<% end %>
</div>
<% #user.posts.reverse_each do |p| %>
<div class="postedcontainer">
<div class="minipostpic">
<%= image_tag #user.photo.url, width: 32, height: 32 %>
</div>
<div class="nameofposter"><%= #user.name %></div>
<div class="dateofpost"><%= p.created_at%></div>
<div class="postcontent"><%= p.id%></div> <br>
<div class="postcontent"><%= p.post%></div> <br>
<div class="likecommentdelete">
<%= link_to "Delete", [p.user, p], method: :delete %> | Like | Comment
</div>
</div>
<%end%>
</div>
Here is my controller:
def index
#user = User.find(params[:user_id])
#posts = #user.posts.all
end
def create
#user = User.find(params[:user_id])
#post = #user.posts.create!(post_params)
redirect_to user_path(#user)
end
def show
#user = User.find(params[:user_id])
#post = #user.posts.find(params[:id])
redirect_to user_path(#user)
end
def destroy
#user = User.find(params[:user_id])
#post = #user.posts.find(params[:id])
#post.destroy
if #post.destroy
redirect_to user_path(#user)
else
redirect_to users_path
end
end
private
def post_params
params.require(:post).permit!
end
end
And here is my model:
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments
validates_presence_of :post
end
I'm pretty sure the issue has something to do with my form to create the new post because when I remove it or comment it out, the extra blank post with no post ID goes away.
Any thoughts or suggestions?
Thank you!!
I think you need to permit the field values to be posted:
i.e.,
params.require(:post).permit!
should be
params.require(:post).permit(:name, :post)
then only it will POST I think.
Hope it helps :)
This is because of rails 4 strong parameter feature. You need to whitelist your active models parameters. For more details refer to here.
In your case you need to do something like this:
params.require(:post).permit(:post)
where the ":post" inside require is your model and the other one is your permitted field that is your textarea.
Several issues -
Form
<%= form_for([#user, #user.posts.build]) do |f| %>
Why are you building an associative object? #user.posts.build will not persist your data, and will cause all sorts of non-conventional issues I would highly recommending building the posts associative object in your controller's new action before using in the view, so you can do this:
#app/controllers/users_controller.rb
def new
#user = current_user
#user.posts.build
end
<%= form_for #user do |f| %>
Association
You're trying to edit the post attribute with this statement:
<%= f.text_area :post, size: "69x1" %>
This won't work in any circumstance, as :post is an association, not an object. Rails only allows you to change / add attributes to specific objects, which means you'll be better doing something like this:
<%= f.fields_for :posts do |p| %>
<%= p.text_area :title %>
<%= p.text_area :body %>
<% end %>
Strong Params
You're currently permitting all your params? You'll be better doing this:
def post_params
params.require(:user).permit(posts_attributes: [:title, :body])
end
Use Posts Controller
A better way will be to just use the posts_controller, like this:
#app/controllers/posts_controller.rb
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.save
end
#app/views/posts/new.html.erb
<%= form_for #post do |f| %>
<%= f.text_field :title %>
<%= f.text_field :body %>
<% end %>

Rails Linked Models undefined method for nil:NilClass

I've been following this, making modifications where necessary.
I have equivalents of #post and #comment. My comments are 'questions'. I've tried following this procedure again but to the comments (rather than posts). Comments on comments if you like, these are answers/responses to the questions.
I've not been successful in getting this to work.
undefined method 'answers' for nil:NilClass`
is the error in answers/_form.html.erb which is rendered as part of a comment, which is in turn rendered as part of my post equivalent.
<%= form_for([#question, #question.answers.build]) do |f| %> is the line that raises the exception. I'm thinking the problem is that #question isn't being given a value for some reason?
Either that or my routes file isn't right (would be my guess at least).
resources :posts-equivalent do
...
resources :questions
end
resources :questions do
resources :answers
end
This has had me stumped all day - any ideas would be appreciated. If you'd like to see any more code drop a comment and I'll update it here.
Additional Code:
Error Message:
Showing .../app/views/answers/_form.html.erb where line #1 raised:
undefined method `answers' for nil:NilClass
Extracted source (around line #1):
1: <%= form_for([#question, #question.answers.build]) do |f| %>
Answers Controller:
class AnswersController < ApplicationController
def create
#question = Question.find(params[:question_id])
#answer = #question.answers.create(params[:answer])
redirect_to concept_path(#question.concept)
end
end
It looks like your AnswersController is not assigning a value to the #question instance variable. It's not clear what action you are running, but I'm assuming it's either new or edit based on the fact that you have a form. You should have something like this in those actions:
class AnswersController < ApplicationController
def new
#question = Question.find(params[:question_id])
#answer = #question.answers.new
end
def edit
#question = Question.find(params[:question_id])
#answer = #question.answers.find(params[:id])
end
end
Then you can have a single form shared between new and edit:
<%= form_for([#question, #answer]) %>
In the end I sorted this in a different manner. Each question was only ever going to have one answer and so I just gave question an answer attribute and assigned that.
On the post page:
...
<%= render #questions %>
<%= render "questions/form" %>
...
In _form.html.erb
<%= form_for([#concept, #concept.question.build]) do |f| %>
<%= f.hidden_field :contributor_id, :value => session[:contributor_id] %>
<div class="field">
<%= f.text_field :question, :placeholder => "Follow-up Question" %>
</div>
<% end %>
In the _question.html.erb
<%= form_for(question) do |f| %>
<div id="question">
"<%= question.question %>" asked by <%= question.contributor.email %> | <%= question.created_at %>.
<div id="answer">
- Answer: <%= question.answer %>
<%= f.text_field :answer, :placeholder => "Respond..." %>
</div>
</div>
<% end %>
Add this to the questions controller:
def update
#question = Question.find(params[:id])
#question.update_attributes(params[:question])
#concept = Concept.find(#question.concept.id)
redirect_to concept_path(#concept)
end
And that worked for me, I know it's not what I originally asked but that fixed my problem. Thanks to those who did try to help.

Rails 3 & Devise: Keeping track of who-owns-profile for user posts

My app has a user model and a post model, where user has_many posts and posts belong_to users. Posts are displayed on a user's profile page. I'd like for any user to be able to post on his own, or any other user's profile page. However, the problem I'm having is that while I know who is posting (current_user), I don't know whose profile current_user is on. I need to know this in order to assign the new post to that user's posts. How do I extract user id information from the profile currently being viewed, so I know where to assign the new post?
My micropost controller looks like:
class MicropostsController < ApplicationController
before_filter :authenticate_user!
def create
#user_of_page = User.find_by_name(params[:id])
#micropost = #user_of_page.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to :back
else
redirect_to about_path
end
end
def destroy
end
end
But I'm getting a NoMethodError: undefined method `microposts' for nil:NilClass. I assume this is because I'm making some mistake with the creation of the user_of_page variable, but I don't know what that is!
SOLUTION
Thanks Sam. I took your advice and ended up doing it like this:
I added a column to my Micropost table called belongs_to_id.
I then passed the id of the user whose profile is being shown from the user show view to the micropost controller using a hidden field in the micropost form, like so:
<%= form_for #micropost do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.label :content, "Why that mood?" %>
<%= f.text_area :content %>
</div>
<div class="field">
<%= f.hidden_field :author, :value => current_user.name %>
<%= f.hidden_field :belongs_to_id, :value => #user.id %>
<%= f.hidden_field :agree, :value => "0" %>
<%= f.hidden_field :disagree, :value => "0" %>
<%= f.hidden_field :amused, :value => "0" %>
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
I then used this id value to search for the user to assign the post to, in the micropost controller, like so:
class MicropostsController < ApplicationController
before_filter :authenticate_user!
def create
#user_of_page = User.find(params[:micropost][:belongs_to_id])
#micropost = #user_of_page.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to :back
else
redirect_to about_path
end
end
def destroy
end
end
Magic! Thanks again, you helped me to see it in the right way.
I would do it like this:
class profiles_controller < AC
...
def show
#profile = User.find(params[:id]).profile || current_user.profile
#post = Post.new
end
..
end
/profiles/show.html.erb
...
Name: <%= #profile.full_name %>
...
<%= form_for #post do |f| %>
<%= hidden_field_tag #profile.user %>
...
<% end %>
class microposts_controller < AC
def create
profile_user = User.find(params[:user_id]) # Owner of the profile current_user is on
..
end
end
Not tested. Hope this helps.

Resources