I use devise for authentication, I want to associate user_id to the comment model. It works when I send user_id as a parameter, But I want to set the current logined user's user_id automatically to the each comment. How can I do that?
#model/post.rb
class Post < ActiveRecord::Base
has_many :comments
belongs_to :category
end
#model/comment.rb
class Comment < ActiveRecord::Base
belongs_to :post
end
#model/category.rb
has_many :posts
#controllers/comments_controller
class CommentsController < ApplicationController
before_action :set_comment, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /comments
# GET /comments.json
def index
#comments = Comment.all
end
# GET /comments/1
# GET /comments/1.json
def show
end
# GET /comments/new
def new
#comment = Comment.new
end
# GET /comments/1/edit
def edit
end
# POST /comments
# POST /comments.json
def create
#comment = Comment.new(comment_params)
respond_to do |format|
if #comment.save
format.html { redirect_to #comment, notice: 'comment was successfully created.' }
format.json { render :show, status: :created, location: #comment }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /comments/1
# PATCH/PUT /comments/1.json
def update
respond_to do |format|
if #comment.update(comment_params)
format.html { redirect_to #comment, notice: 'comment was successfully updated.' }
format.json { render :show, status: :ok, location: #comment }
else
format.html { render :edit }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url, notice: 'comment was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_comment
#comment = Comment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
params.require(:comment).permit(:rating, :comment, :post_id, :user_id)
end
end
use associations user has_many comments and
comments belongs_to user
def new
#comment = current_user.comments.build
end
def create
#comment = current_user.comments.build(comment_params)
end
Provided you have taken the correct steps to setup Devise:
#comment.user = current_user
Related
I've been around for this problem for 1 hour and not figuring out why it doesn't work.
I don't use gem devise.
I have user model, post model, UsersController.rb, PostsController.rb and 1 helper like below
PostsController.rb :
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = current_user.posts.build(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
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
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, 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(:caption, :user_id)
end
end
ApplicationHelper.rb
module ApplicationHelper
def current_user
session[:user_id] && User.find(session[:user_id])
end
end
The current_user helper method works fine for all the views.
As I understand, PostsController inherits from ApplicationController, so it takes all the helpers from ApplicationHelper. I still dont figure out why this doesn't work.
Thanks for any help.
Try with adding this into ApplicationController.rb
helper_method :current_user
call helper methods in Rails 5 :
# sample :
module UsersHelper
def full_name(user)
user.first_name + user.last_name
end
end
class UsersController < ApplicationController
def update
#user = User.find params[:id]
if #user.update_attributes(user_params)
notice = "#{helpers.full_name(#user) is successfully updated}"
redirect_to user_path(#user), notice: notice
else
render :edit
end
end
end
Before Rails 5 :
# sample :
module UsersHelper
def full_name(user)
user.first_name + user.last_name
end
end
class UsersController < ApplicationController
include UsersHelper
def update
#user = User.find params[:id]
if #user.update_attributes(user_params)
redirect_to user_path(#user), notice: "#{full_name(#user) is successfully updated}"
else
render :edit
end
end
end
am using devise for authentication in a rails app everything is working fine, but i have a post model and after signing up when i try to create a new post it shows up an error:
1 error prohibited this post from being saved:
User must exist
I looked into the terminal and got this:
Unpermitted parameter: user_id
(0.0ms) begin transaction
(0.0ms) rollback transaction
i tried adding a user controller
users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!
before_action :set_user
before_action :check_ownership, only: [:edit, :update]
respond_to :html, :js
# GET /users
# GET /users.json
def index
#users = User.all
end
# GET /users/1
# GET /users/1.json
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :email)
end
end
my posts_controler.rb
class PostsController < ApplicationController
before_action :authenticate_user!, :except => [:show, :index]
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
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
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, 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(:tittle, :body)
end
end
My user model
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :posts
end
My post model
class Post < ApplicationRecord
belongs_to :user
end
i have also added user_id to user through this migration:
class AddUseridToPost < ActiveRecord::Migration[5.0]
def change
add_column :posts, :user_id, :integer
end
end
as the error says, permit the user_id as follows
def post_params
params.require(:post).permit(:tittle, :body, :user_id)
end
Or, better approach is you generate a new post for the logged_in user as in post create:
def create
#post = current_user.posts.new(post_params)
# ...other logic
end
This way, you don't need to allow user_id also, it will ensure that the params are not tampered with..
If you add column in your model, you should add it to your permitted params. So add :user_id in your permitted params in posts_controller:
def post_params
params.require(:post).permit(:tittle, :body, :user_id)
end
im trying to have a put a voting system (likes and dislikes) using the Ruby gem "act_as_votable" but i want to use that in my reviews model. keep in mind that the Reviews are nested inside the Post Model in my app. i tried to add that in my routes.rb file but its not working. does anyone know how to add a voting system for a nested model ? here's my code
Routes.rb
Rails.application.routes.draw do
devise_for :users
resources :posts do
resources :reviews , except: [:show,:index]
member do
get "like" , to: "reviews#upvote"
get "dislike" , to: "reviews#downvote"
end
end
get 'pages/help'
get 'pages/blog'
get 'pages/contact'
get 'pages/tour'
resources :posts
root 'posts#index'
end
reviewsController.rb
class ReviewsController < ApplicationController
before_action :set_review, only: [ :edit, :update, :destroy, :upvote,:downvote]
before_action :set_post
before_action :authenticate_user!
respond_to :html
def new
#review = Review.new
respond_with(#review)
end
def edit
#review = Review.find(params[:id])
#post = Post.find(params[:post_id])
end
def create
#review = Review.new(review_params)
#review.user_id = current_user.id
#review.post_id = #post.id
#review.save
redirect_to post_path(#post)
end
def update
#review.update(review_params)
respond_with(#review)
end
def destroy
#review.destroy
respond_with(#review)
end
def upvote
#review.upvote_bu current_user
redirect_to :back
end
def downvote
#review.downvote_bu current_user
redirect_to :back
end
private
def set_review
#review = Review.find(params[:id])
end
def set_post
unless #post = Post.where(id: params[:post_id]).first
redirect_to posts_path, flash: {alert: "Post doesn't exists"}
end
end
def review_params
params.require(:review).permit(:comment)
end
end
PostsController.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user! , only: [:edit,:update,:destroy,:new]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
#reviews = Review.where(post_id: #post.id)
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
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
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to root_path, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, 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(:title, :description)
end
end
I am new to rails I created post model and posts_controller which has Name:string, EMail:string, Message:text, topic_id:integer columns using scaffold.
I also created a topic model and topics_controller which has Topic_Name:string in it.
I provided the relationship among the models as follows:
class Topic < ActiveRecord::Base
has_many :posts, foreign_key: 'topic_id'
end
class Post < ActiveRecord::Base
belongs_to :topic
end
In routes.db I created the nested resources as:
resources :topics do
resources :posts
end
topics_controller.rb code:
class TopicsController < ApplicationController
before_action :set_topic, only: [:show, :edit, :update, :destroy]
# GET /topics
# GET /topics.json
def index
#topics = Topic.all
end
# GET /topics/1
# GET /topics/1.json
def show
end
# GET /topics/new
def new
#topic = Topic.new
end
# GET /topics/1/edit
def edit
end
# POST /topics
# POST /topics.json
def create
#topic = Topic.new(topic_params)
respond_to do |format|
if #topic.save
format.html { redirect_to #topic, notice: 'Topic was successfully created.' }
format.json { render :show, status: :created, location: #topic }
else
format.html { render :new }
format.json { render json: #topic.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /topics/1
# PATCH/PUT /topics/1.json
def update
respond_to do |format|
if #topic.update(topic_params)
format.html { redirect_to #topic, notice: 'Topic was successfully updated.' }
format.json { render :show, status: :ok, location: #topic }
else
format.html { render :edit }
format.json { render json: #topic.errors, status: :unprocessable_entity }
end
end
end
# DELETE /topics/1
# DELETE /topics/1.json
def destroy
#topic.destroy
respond_to do |format|
format.html { redirect_to topics_url, notice: 'Topic was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_topic
#topic = Topic.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def topic_params
params.require(:topic).permit(:Name)
end
end
posts_controller code:
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
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
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, 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(:Name, :Email, :Message, :topic_id)
end
end
I need to group posts using the topic. i.e., On clicking show on a particular topic it should go to the URL /topics/<topic_id>/posts where it should lists all posts related to that topic and I can create/delete posts belongs to that topic.
Can anyone help doing this..
Thank you..
Your question should be more direct, there's a lot of information that aren't related to the problem (the attributes names, for example), and your goal isn't clear enough.
It seems that you just want to setup the routes, right? You already have all posts related to that topic though the association: topic.posts. You just need to setup nested resource routes for posts:
resources :topics do
resources :posts
end
Also, you don't need the foreign_key option since you're using the naming conventions. It seems as well that you named some attributes in upper case, they should be name, email and message.
UPDATE:
In the index action, since you want posts belonging to one topic, you need to scope the #posts instance variable. Since you're using nested resources, you have the parameter params[:topic_id], so just fetch the topic with #topic = Topic.find(params[:topic_id]), then scope the association with #posts = #topic.posts. You'll need to do the same for every other action. I recommend that you read a little about associations in Rails, you'll probably need to use methods like #topic.posts.build and #topic.posts.find(params[:id]).
I found the solution for this problem in this link: Nested resources
Download the source code and find the solution...
Based on this tutorial, I've created a slug url but when I click show or add post it showing error as :
ActiveRecord::RecordNotFound
Couldn't find Post with id=testing-seo-url
Instead of taking slug it is taking as id. where I have to make changes make this work.
Here is my controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render action: 'show', status: :created, location: #post }
else
format.html { render action: 'new' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
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(:title, :content)
end
end
And here is my model:
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
end
This is just a scaffold. I didn't create any other controller.
This solved
def set_post
#post = Post.friendly.find(params[:id])
end