简体   繁体   中英

Not Showing Public Posts To Logged In Users - Rails

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM