ruby on rails - How do I resolve: Pundit::NotDefinedError in PostsController#show? -
whenever run below program , try view posts (in show view) user, introduced error page:
pundit::notdefinederror in postscontroller#show unable find policy of nil
within error page:
def show @post = post.find(params[:id]) authorize @posts # <- error highlights line end
i'm not sure how around dilemma i'm learning pundit policy rules , new rails , ruby. appreciated. below policy pages , related pages:
user.rb model
class user < activerecord::base # include default devise modules. others available are: # :confirmable, :lockable, :timeoutable , :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable has_many :posts def admin? role == 'admin' end def moderator? role == 'moderator' end def member? role == 'member' end def guest? role == 'guest' end end
application controller
class applicationcontroller < actioncontroller::base # prevent csrf attacks raising exception. # apis, may want use :null_session instead. include pundit protect_from_forgery with: :exception before_action :configure_permitted_parameters, if: :devise_controller? rescue_from pundit::notauthorizederror |exception| redirect_to root_url, alert: exception.message end protected def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_up) << :name end end
posts controller
class postscontroller < applicationcontroller # before_action :flash_attack # protected # def flash_attack # flash[:notice] = "create/edit/comment on post!" # end def index @posts = post.all authorize @posts end def show @post = post.find(params[:id]) authorize @posts end def new @post = post.new authorize @post end def create @post = current_user.posts.build(params.require(:post).permit(:title, :body)) authorize @post if @post.save flash[:notice] = "post saved." redirect_to @post else flash[:error] = "there error saving post. please try again." render :new end end def edit @post = post.find(params[:id]) authorize @post end def update @post = post.find(params[:id]) authorize @post if @post.update_attributes(params.require(:post).permit(:title, :body)) flash[:notice] = "post updated." redirect_to @post else flash[:error] = "there error saving post. please try again." render :edit end end end
application policy
class applicationpolicy attr_reader :user, :record def initialize(user, record) @user = user @record = record end def index? false end def show? scope.where(:id => record.id).exists? end def create? user.present? end def new? create? end def update? user.present? && (record.user == user || user.admin?) end def edit? update? end def destroy? update? end def scope record.class end class scope attr_reader :user, :scope def initialize(user, scope) @user = user @scope = scope end def resolve scope end end end
posts policy
class postpolicy < applicationpolicy class scope < scope def resolve if user.admin? scope.all else scope.where(:published => true) end end def index? true end def show? true end def update? user.admin? or not post.published? end end end
index view
<h1>all posts</h1> <% if policy(post.new).create? %> <%= link_to "new post", new_post_path, class: 'btn btn-success' %> <% end %> <% @posts.each |post| %> <div class="media"> <div class="media-body"> <h4 class="media-heading"> <%= link_to post.title, post %> </h4> <small> submitted <%= time_ago_in_words(post.created_at) %> ago <%= post.user.name unless post.user.nil? %><br> <%= post.comments.count %> comments </small> </div> </div> <% end %>
show view
<h1> <%= @post.title %> </h1> <% if policy(@post).edit? %> <%= link_to "edit", edit_post_path(@post), class: 'btn btn-success' %> <% end %> <p> <%= @post.body %> </p>
thanks in advance everyone. let me know if more information great.
@posts
nil
in show action, should use @post
such:
authorize @post
Comments
Post a Comment