I'm having issues associating a users status post to them, I also can't get it to show on their account.
This is in my users_controller
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
after_action :signed_in_after_register, only: :create
def index
#users = User.all
end
def profile
#user = User.find(session[:user_id]) unless session[:user_id] == ""
redirect_to login_path, notice: "You're not logged in" unless #user
#posts = #user.posts
end
def _nav
#user = User.find(session[:user_id])
end
def destroy
#user = User.find(session[:user_id])
end
def welcome
#user = User.find(session[:user_id])
end
def show
#user = Post.first.update_attributes(user_id: 1)
#post = Post.first.update_attributes(#signed_in_user)
end
def new
#post = Post.new(params[:post_id])
#user = User.new
end
def edit
end
def create
#post.user = current.user
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to profile_path, notice: 'User was successfully created.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_user
#user = User.find(params[:id])
end
def signed_in_after_register
session[:user_id] = #user.id
end
def user_params
params.require(:user).permit(:name, :password, :password_confirmation, :email, :age, :profile_picture, :post)
end
end
This is in my posts_controller
class PostsController < ApplicationController
def index
#posts = Post.all.order('created_at DESC')
end
def new
#post = Post.new
end
def create
#post = #signed_in_user
#post = Post.new(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
def show
#post = Post.find(params[:id])
#signed_in_user = session[:user_id]
end
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(params[:post].permit(:body))
redirect_to #post
else
render 'edit'
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:body)
end
end
This is the profile.html.erb page that I want the signed_in_users most recent post to be returned to
<%- #posts.each do |post| %>
<div class="post_wrapper">
<h2 class="title"><%= link_to post.body, post %></h2>
<p class="date"><%= post.created_at.strftime("%B, %d, %Y") %> </p>
</div>
<% end %>
This is in my routes
Rails.application.routes.draw do
root 'welcome#welcome'
get 'login' => 'sessions#login', :as => :login
get 'profile' => 'users#profile', :as => :profile
post 'logging/user' => 'sessions#create'
get 'logout' => 'sessions#destroy', :as => :logout
get 'about' => 'about'
resources :users
resources :posts
get 'index' => 'posts#index'
get 'register' => 'users#new', :as => :register
Just to clear the question up a bit more and be very specific, I want it to be exactly like a status post that Facebook offers, You write it, It post, It shows on your profile. That's it, I have no problems with Writing, Posting and it saving. It just doesn't show on the profile page of the user that created it.
run this command in your terminal:
rails generate migration AddUserRefToPosts user:references
in your user model:
class User < ActiveRecord::Base
has_many :posts
...
end
3.in post controller
def create
#post = Post.new(post_params)
#post.user_id = #signed_in_user.id
if #post.save
redirect_to #post
else
render 'new'
end
end
Try this
def create
#post = #signed_in_user.posts.build(post_params)
if #post.save
redirect_to #post
else
render 'new'
end
end
Your create action should look like this
def create
#post = Post.new(post_params)
#post.user_id = #signed_in_user.id
if #post.save
redirect_to #post
else
render 'new'
end
end
Related
I am working on user_profile_reviews and have got stuck. I have 3 models for now, and I know, that doing a separate model for a profile wasn't really a great idea, but since all my routes depend on this structure, meaning the links in all the views also, I decided not to change it.
To give you a clearer understanding:
Rails.application.routes.draw do
devise_for :user, controllers: { omniauth_callbacks: 'users/omniauth_callbacks', registrations: "users/registrations" }
resources :users do
resources :profiles do
resources :reviews, only: [:new, :create]
end
end
root 'home#index'
end
Here are my controllers:
class ProfilesController < ApplicationController
before_action :set_profile, only: [:show, :edit, :update, :destroy]
def index
#profiles = Profile.all
end
def show
#user = User.find(params[:user_id])
#profile = Profile.find(params[:id])
#reviews = Review.where("profile_id = ?", params[:id])
end
def new
#user = User.find(params[:user_id])
end
def edit
#profile = Profile.find(params[:id])
end
def create
#profile = current_user.build_profile(profile_params)
respond_to do |format|
if #profile.save
format.html { redirect_to user_profile_path(current_user.id, current_user.profile.id), notice: 'Profile was successfully created.' }
format.json { render :show, status: :created, location: #profile }
else
format.html { render :new }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #profile.update(profile_params)
format.html { redirect_to user_profile_path(current_user.id, current_user.profile.id), notice: 'Profile was successfully updated.' }
format.json { render :show, status: :ok, location: #profile }
else
format.html { render :edit }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
def destroy
#profile.destroy
respond_to do |format|
format.html { redirect_to profiles_url, notice: 'Profile was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_profile
#profile = Profile.find(params[:id])
end
def profile_params
params.permit(:about, :rating, :avatar)
end
end
Reviews
class ReviewsController < ApplicationController
before_filter :set_profile
before_filter :set_review, only: [:new, :create]
def new
#review = Review.new
end
def create
#profile = Profile.find(params[:profile_id])
#review = #profile.reviews.build(review_params)
#review.user_id = current_user.id
if #review.save
redirect_to #profile
else
redirect_to #profile, notice: "Error saving"
end
end
private
def review_params
params.permit(:content, :rating)
end
def set_pfofile
#profile = Profile.find(params[:profile_id])
end
def set_review
#profile = Profile.find(params[:id])
end
end
So now, I am trying to create a form for reviews, which I am then rendering in Profiles#show, and getting the mistake above.
<div class="submit-review">
<%= form_for [#review, :url => user_profile_reviews_path(#profile)] do |f| %>
<label for="review">How was your experience?</label><br>
<%= f.label :rating %>
<%= f.select :rating, options_for_select([["Please select one", ""], 5, 4, 3, 2, 1]) %>
<%= f.input :content, placeholder:"Please enter your feedback here" %>
<%= f.submit "Submit your review", class: "btn btn-default" %> <br><br>
<% end %>
Showing ... /_form.html.erb where line #2 raised:
No route matches {:action=>"create", :controller=>"reviews", :id=>"2", :user_id=>#<Profile id: 2, about: "lena", rating: 3, created_at: "2019-11-22 21:27:03", updated_at: "2019-11-22 21:27:03", user_id: 2>}, missing required keys: [:profile_id]
But, as I see, it gets to the profile, I am onto, so I don't understand what's the issue here.
Something wrong with the syntax, try this
= form_for([#profile.user, #profile, #review], :url => user_profile_reviews_path(#profile.user, #profile)) do |f|
Since your resources are nested, you need to pass user, profile and then review as the first argument in form_for
Suggestion: Looking at your code, you don't even need user_id, you can avoid nesting profile and review under user in routes.
Hope that helps!
Ok, this worked perfectly for solving the described problem with missing id.
form_for([#profile.user, #profile, #review], :url => user_profile_reviews_path(#profile.user, #profile)) do |f|
I was getting another error though:
First argument in form cannot contain nil or be empty
I saw then, that in my Profile#show I wasn't defining #review. Only reviews. So I did it this way:
def show
#user = User.find(params[:user_id])
#profile = Profile.find(params[:id])
#review = Review.new
#reviews = Review.where("profile_id = ?", params[:id])
end
I can now finally go to profile and there is a review window, which is great! I can't save the reviews though, as another error is showing up. But that's different case. Thank you so much!
ive been having a problem now for 2 days, i followed many videos and tutorials on how to add comments to a post, and for everyone else it seemed to work smoothly.
I got 4 controllers, Users,Posts,Comments and Walls , basically this site is gonna be a facebook clone. So im displaying everything on the Wall index.html.erb
The error im getting is:
No route matches {:action=>"index", :controller=>"comments", :post_id=>nil} missing required keys: [:post_id]
Routes:
Rails.application.routes.draw do
devise_for :users
resources :uploads
resources :users
resources :posts do
resources :comments
end
resources :walls
root 'walls#index'
end
Comments-controller:
class CommentsController < ApplicationController
before_action :find_post
def index
#comments = Comment.all
end
def new
#post = Post.find(params[:post_id])
end
def create
#comment = #post.comments.create(params[:comment].permit(:content))
#comment.post_id = #post.id
#comment.user_id = current_user.id
#comment.save
# #comment = #post.comments.create(params[:comment].permit[:content])
# #comment.post_id = #post.id
respond_to do |format|
if #comment.save
format.html { redirect_to root_path }
# format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
# def comment_params
# params.require(:comment).permit(:content)
# end
def find_post
#post = Post.find(params[:post_id])
end
end
Posts-controller:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def new
#post = Post.new
#comment = Comment.new
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
#post.user_id = current_user.id
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
#post.user = current_user
respond_to do |format|
if #post.save
format.html { redirect_to root_path }
# format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
#post.user_id = current_user.id
#post.save
respond_to do |format|
if #post.update(params[:post].permit(:image,:content,:youtube_url))
format.html { redirect_to root_path, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
format.json { respond_with_bip(#post) }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
format.json { respond_with_bip(#post) }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to root_path, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:content, :image, :username, :avatar, :youtube_url,:image_cache)
end
end
I am rendering the form in the index.html.erb for the wall controller index
<%= render "form" %>
And the form loop
views/walls/_form.html.erb
<div class="comments">
<%= form_for ([#post, #post.comments.build]) do |f| %>
byebug
<%= f.text_area :content, class: 'comments js-auto-size', id: 'alex2' ,:rows => 1 %>
<%= f.submit "Submit", class: "btn btn-default" %>
<% end %>
</div>
I dont understand why it cant find the post_id though :/
Since your comments is nested inside posts in routes, you have to pass post_id to the index in CommentsController
class CommentsController < ApplicationController
before_action :find_post
def index
#comments = #post.comments
end
end
# in view
<%= link_to "Comments", post_comments_path(#post) %>
Otherwise, you can define comments to be independent resources so you can do it without passing post_id
Rails.application.routes.draw do
resources :posts
resources :comments
end
In my Users controller, I have the following method
def show
#user = User.find(params[:id])
if current_user.id == params[:id] # im not sure if this is right
#answer = Answer.new
else
#answer = Answer.find(params[:id])
end
end
where
class User
has_many :answers
end
and
class Answer
belongs_to :user
end
When I open another user (A) by the signed in user (B), I want A's quiz questions (which also belongs_to User through a has_one association) to have the answers by B.
As is, if B answers A's questions, and then I log in with A, they will have the same answers of the original B to A.
If it helps, in my Answers controller I have the following methods.
def create
#answer = current_user.answers.build(answer_params)
if #answer.save
flash[:success] = "Updated"
redirect_to '/'
else
render 'new'
end
end
def update
respond_to do |format|
#answer = Answer.find(params[:id])
if #answer.update(answer_params)
format.html { redirect_to '/', notice: 'Answers were successfully updated.' }
format.json { render :show, status: :ok, location: #answer }
else
format.html { render :edit }
format.json { render json: #answer.errors, status: :unprocessable_entity }
end
end
end
def answer_params
params.require(:answer).permit(:r1, :r2, :r3, :r4, :r5)
end
and I also have the migration
class AddUserIdToAnswers < ActiveRecord::Migration
def change
add_column :answers, :user_id, :integer
end
end
EDIT:
Quizzes Controller (belongs_to User, User has_one :quiz)
class QuizzesController < ApplicationController
def edit
#quiz = Quiz.find(params:[id])
end
def create
#quiz = current_user.build_quiz(quiz_params)
if #quiz.save
flash[:success] = "Updated"
redirect_to '/'
else
render 'new'
end
end
def update
respond_to do |format|
#quiz = Quiz.find(params[:id])
if #quiz.update(quiz_params)
format.html { redirect_to '/', notice: 'Quiz was successfully updated.' }
format.json { render :show, status: :ok, location: #quiz }
else
format.html { render :edit }
format.json { render json: #quiz.errors, status: :unprocessable_entity }
end
end
end
def quiz_params
params.require(:quiz).permit(:q1, :q2, :q3, :q4, :q5)
end
def show
#quizzes = Quiz.all
end
end
and my Routes.rb
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users
root to: 'welcome#landing'
resources :users, :quizzes, :answers
end
I am not gone through every aspect. But one issue in your show action.
if current_user.id == params[:id] # im not sure if this is right
With this you will not get new form. Because params[:id] type is string and current_user.id type is integer. So it will always return false.
Try change like :
if current_user.id == params[:id].to_i
Or compare user object directly
if current_user == #user
Try my suggestion helpisgood
def show
#user = User.find(params[:id])
if current_user == #user
#answer = Answer.new
else
#answer = Answer.find_by(user_id: #user.id)
end
end
This is the issue I am having, Haven't been able to get around it. Now this happens while logging into the account. I haven't had this issue before til last night.
Here is my users_controller.rb,
class UsersController < ApplicationController
before_action :set_user, only: [:edit, :update, :destroy]
before_action :correct_user, only: [:edit ]
after_action :signed_in_after_register, only: :create
def index
#users = User.all
#user = User.find(session[:user_id])
if params[:search]
#users = User.search(params[:search]).order("created_at DESC")
else
#users = User.all.order('created_at DESC')
end
end
def dashboard
#user = User.find(session[:user_id]) unless session[:user_id] == ""
redirect_to login_path, notice: "You're not logged in" unless #user
#posts = #user.posts.order("created_at DESC").limit(3)
#comment = Comment.new
#post = Post.new
end
def newsfeed
#user = User.find(session[:user_id]) unless session[:user_id] == nil
redirect_to login_path, notice: "You're not logged in" unless #user
#posts = #user.posts.order("created_at DESC").limit(3)
end
def nav
#user = User.find(session[:user_id])
end
def posts
#user = User.find(session[:user_id])
#posts = #user.posts
end
def destroy
#user = User.find(session[:user_id]) unless session[:user_id] == ""
redirect_to login_path, notice: "You're not logged in" unless #user
end
def welcome
#user = User.find(params[:user_id]) unless session[:user_id] == ""
redirect_to login_path, notice: "You're not logged in" unless #user
#user = User.find(session[:user_id])
end
def show
#user = User.find(params[:user_id]) unless session[:user_id] == ""
redirect_to login_path, notice: "You're not logged in" unless #user
#posts = #user.posts.order("created_at DESC").limit(3)
#comment = Comment.new
#post = Post.new
end
def new
#user = User.new
#post = Post.new(params[:post_id])
end
def edit
#user = User.find(params[:user_id]) if params[:user_id]
redirect_to #dashboard_path unless #user
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to dashboard_path, notice: 'User was successfully created!' }
format.json { render :profile, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def update
if #user == current_user
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to dashboard_path, notice: 'User was successfully updated.' }
format.json { render :profile, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
else
redirect_to dashboard_path, notice: 'You do not have permission to edit the profile of another user.'
end
end
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_user
#user = User.find(params[:id])
end
def correct_user
#user = User.find(params[:id]) unless session[:user_id] == ""
end
def signed_in_after_register
session[:user_id] = #user.id
end
def user_params
params.require(:user).permit(:first_name, :last_name, :bio, :comments, :password, :password_confirmation, :email, :age, :profile_picture, :post, :body)
end
end
Heres my comments _form.html.erb,
<%= form_for([#post, #comment]) do |f| %>
<p>
<%= f.text_area :body, placeholder: "Write a comment!" %>
</p>
<br>
<p> <%= f.submit %> </p>
<% end %>
And here is my routes.rb,
Rails.application.routes.draw do
root 'welcome#welcome'
get 'login' => 'sessions#login', :as => :login
get 'dashboard' => 'users#dashboard', :as => :dashboard
post 'logging/user' => 'sessions#create'
get 'logout' => 'sessions#destroy', :as => :logout
get 'about' => 'about'
get 'newsfeed' => 'users#newsfeed'
resources :users, except: :show
get 'profile/:user_id' => 'users#show', as: :profile
get 'location' => 'location#location'
resources :posts do
resources :comments
end
get 'index' => 'posts#index'
get 'register' => 'users#new', :as => :register
end
If you guys do need to see anymore code then just let me know, I will post it! Thank you so much in advance!
The problem is you're trying to create a URL that looks like this: /posts/:post_id/comments by passing form_for([#post, #comment]). It's OK that #comment isn't saved to the database, but the #post you use must already be saved to the database because you can't create that URL without #post having an ID.
Once #post is saved, it'll have an ID, so you can generate the route: for example, /posts/32/comments.
Check your dashboard.html.erb file for where you're using #posts and rendering comments/_form.html.erb. You may have a post object available, and you should use it in your form instead: form_for([post, #comment]).
You'll probably also want to remove the #post = Post.new line from your #dashboard controller action.
I want my visitors to be able to edit or delete their comment up too 5-10 min after they created it.
How should I authenticate this with a session or cookie?
My comment controller:
class CommentsController < ApplicationController
# GET /comments
# GET /comments.xml
# GET /comments/new
# GET /comments/new.xml
def new
#comment = Comment.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #comment }
end
end
# GET /comments/1/edit
def edit
#comment = Comment.find(params[:id])
end
# POST /comments
# POST /comments.xml
def create
#blog = Blog.find(params[:blog_id])
params[:comment][:ip] = request.remote_ip
#comment = #blog.comments.create!(params[:comment])
redirect_to #blog
end
# PUT /comments/1
# PUT /comments/1.xml
def update
#comment = Comment.find(params[:id])
respond_to do |format|
if #comment.update_attributes(params[:comment])
format.html { redirect_to(admin_comments_path, :notice => 'Comment was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #comment.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.xml
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to(admin_comments_url, :notice => 'Indlæg slettet') }
format.xml { head :ok }
end
end
end
store the saved comment's id in the session and then at the time of delete or update, check the session for the comment's id and compare the current-time with the comment's created_at... this can go in a filter method.
Also, you can move the code of finding the comment with id in a filter and can follow DRY.
Here it goes:
class CommentsController < ApplicationController
before_filter :get_blog
before_filter :get_comment, :only => [:edit, :update, :destroy]
before_filter :authorize_comment, :only => [:edit, :update, :destroy]
private
def get_blog
#blog = Blog.find(params[:blog_id])
end
def get_comment
#comment = Comment.find(params[:id])
end
def authorize_comment
unless #comment
flash[:error] = "Comment Not Found"
redirect_to #blog and return
else
# checks whether the comment is there in sessions' recent_comments
# if true, it means, this comment was created by the same visitor who is now attempting to delete/update it again
if session[:recent_comments].include?(#comment.id)
# now check if the comment is editable w.r.t time or not
if #comment.created_at < 10.minutes.ago
# if true, it means comment can no longer be updated/deleted
# if you wish you can now remove this from the session's recent_comments
session[:recent_comments].delete(#comment.id)
flash[:error] = "Sorry, you can not change this comment now"
redirect_to #blog and return
else
# it means comment can be edited/updated
return true
end
else
flash[:error] = "Sorry, you can not change this comment now"
redirect_to #blog and return
end
end
end
public
def new
#comment = Comment.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #comment }
end
end
def edit
end
def create
params[:comment][:ip] = request.remote_ip
#comment = #blog.comments.create!(params[:comment])
unless session[:recent_comments].is_a?(Array)
session[:recent_comments] = []
end
session[:recent_comments] << #comment.id
redirect_to #blog
end
def update
respond_to do |format|
if #comment.update_attributes(params[:comment])
format.html { redirect_to(admin_comments_path, :notice => 'Comment was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #comment.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to(admin_comments_url, :notice => 'Indlæg slettet') }
format.xml { head :ok }
end
end
end