I'm using this application and the only problem I'm having is that when a user is logged in, they can see public posts, even if they didn't create it.
Is there a way to have it so it doesn't show up along with other users' posts?
The point of the application is so a user can login and create posts, these are private by default which means only they can see it, if the user makes the post public, I'd like it so a non-logged in or logged in user can view but, which is exactly what I've got but that all the public posts show up with other users' posts.
Here is the application controller:
class ApplicationController < ActionController::Base
protect_from_forgery
rescue_from ActiveRecord::RecordNotFound, :with => :handle_not_found
def handle_not_found
respond_to do |type|
type.html { redirect_to root_path, :notice => 'Record not found'}
type.all { render :nothing => true, :status => 404 }
end
true
end
end
Here is the post controller:
class PostsController < ApplicationController
before_filter :authenticate_user!, :except => [:index, :show]
# GET /posts
# GET /posts.json
def index
@posts = current_user ? Post.public_or_owned_by(current_user) : nil
render :template => current_user ? 'posts/index_logged_in' : 'posts/index_not_logged_in'
end
# GET /posts/1
# GET /posts/1.json
def show
@post = current_user ? Post.public_or_owned_by(current_user).find_by_url_id!(params[:id]) : Post.public.find_by_url_id!(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @post }
end
end
# GET /posts/new
# GET /posts/new.json
def new
@post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @post }
end
end
# GET /posts/1/edit
def edit
@post = current_user.posts.find_by_url_id(params[:id])
end
# POST /posts
# POST /posts.json
def create
@post = current_user.posts.build(params[:post])
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render json: @post, status: :created, location: @post }
else
format.html { render action: "new" }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
# PUT /posts/1
# PUT /posts/1.json
def update
@post = current_user.posts.find_by_url_id(params[:id])
respond_to do |format|
if @post.update_attributes(params[:post])
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 = current_user.posts.find_by_url_id(params[:id])
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
end
Here is the post model:
class Post < ActiveRecord::Base
belongs_to :user
before_create :generate_url_id
attr_accessible :title, :body, :is_public
scope :public, where(:is_public => true)
def self.public_or_owned_by(user)
t = Post.arel_table
Post.where(t[:user_id].eq(user.id).or(t[:is_public].matches(true)))
end
def generate_url_id
self.url_id = SecureRandom.urlsafe_base64
end
def to_param
self.url_id
end
end
And here is the user model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
# attr_accessible :title, :body
has_many :posts
end
still not sure i understand well what you want, but i would use two different routes :
resources :posts # see all public posts from everyone
resources :users do
resources :posts # nested route for a user to only see his own posts
end
so in your controller, you'll have :
def index
if params[:user_id]
if current_user && current_user.id == params[:user_id].to_i
# see all posts for a user, even non-public ones
@posts = Post.where( user_id: params[:user_id] )
else
# see public posts from a user
@posts = Post.public.where( user_id: params[:user_id] )
end
else
# see all public posts
@posts = Post.public
end
end
this is not the best you can do, but it is functionnal. A better approach would be to use some authorization mechanism like CanCan .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.