简体   繁体   中英

Rails4 - How to add two filters for a single action properly?

I want both the user who created the micropost and the admin to be able to delete the micropost.

I have this in my controller.

class MicropostsController < ApplicationController

  before_action :logged_in_user, only: [:create, :destroy]
  before_action :correct_user,   only: :destroy

  before_action :admin_user,     only: :destroy
.
.
  private

def micropost_params
  params.require(:micropost).permit(:content, :picture)
end

def correct_user
  @micropost = current_user.microposts.find_by(id: params[:id])
  redirect_to root_url if @micropost.nil?
end


# Confirms an admin user.
def admin_user
  redirect_to(root_url) unless current_user.admin?
end

This is in my view where I delete the micropost

                <% if current_user.admin? || current_user?(@micropost.user) %>

                  <div class="btn-group" style="float:right">

                    <button class="btn btn-default btn-xs dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
                      <span class="caret"></span>
                    </button>

                    <ul class="dropdown-menu pull-right postdelete" role="menu"  style="color:#383838; background-color: #E6E6E6; padding-top: 0; padding-bottom: 0;margin-top: 0; margin-bottom:0">
                      <li role="presentation" style="padding-top: 0; padding-bottom: 0;margin-top: 0; margin-bottom:0">
                            <%= link_to " Delete ", @micropost, method: :delete,
                                                             data: { confirm: "Are you sure?" },
                                                             role: 'menuitem', tabindex: -1, :style => "color:#383838" %>
                      </li>

                    </ul>

                  </div>  

                <% end %>

I am getting the following error when an admin tries to delete the micropost.

2015-05-19T20:23:17.467004+00:00 app[web.2]: Started DELETE "/microposts/142" for 182.65.17.244 at 2015-05-19 20:23:17 +0000
2015-05-19T20:23:17.481204+00:00 app[web.2]:    (2.3ms)  SELECT COUNT(*) FROM "user_languages" WHERE "user_languages"."user_id" = $1  [["user_id", 1]]
2015-05-19T20:23:17.489765+00:00 app[web.2]:   Micropost Load (2.1ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."user_id" = $1 AND "microposts"."id" = $2  ORDER BY created_at DESC LIMIT 1  [["user_id", 1], ["id", 142]]
2015-05-19T20:23:17.472886+00:00 app[web.2]: Processing by MicropostsController#destroy as HTML
2015-05-19T20:23:17.472897+00:00 app[web.2]:   Parameters: {"authenticity_token"=>"5gLZum2IEbw+WX31H5DR1jGypHNtktiZnYnIclh8i2tY1AxejDYsiDTMIXovEo9EhxkM6xqfJmdRvD40xL/uvQ==", "id"=>"142"}
2015-05-19T20:23:17.476748+00:00 app[web.2]:   User Load (2.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]
2015-05-19T20:23:17.484168+00:00 app[web.2]:    (1.9ms)  SELECT COUNT(*) FROM "user_learnings" WHERE "user_learnings"."user_id" = $1  [["user_id", 1]]
2015-05-19T20:23:17.490353+00:00 app[web.2]: Redirected to https://www.abc123.com/
2015-05-19T20:23:17.490423+00:00 app[web.2]: Filter chain halted as :correct_user rendered or redirected
2015-05-19T20:23:17.490552+00:00 app[web.2]: Completed 302 Found in 18ms (ActiveRecord: 8.5ms)

I can see it is due to

Filter chain halted as :correct_user rendered or redirected

Can anyone kindly share the mistake I am making? Why isn't the admin_user filter not being executed?

How can I enable the admin user also to delete the micropost?

Kindly help. Thanks.

before_action :correct_user,   only: :destroy
before_action :admin_user,     only: :destroy

The above will be treated as an AND condition as both of these will be applied in sequence (order depends on the order of declaration). So with that code in place, only an admin_user will be able to delete the records they created - not the ones created by others.

What you are trying could be implemented as a OR condition as follows:

before_action :can_delete, only: :destroy

....

def can_delete
  correct_user || admin_user
end

You'redirecting the user when @micropost.nil? , but when you're logged in as admin , @micropost doesn't belongs to that him, right? It belongs to someone else.

You should do something like this:

def correct_user
    unless current_user.admin? 
      @micropost = current_user.microposts.find_by(id: params[:id])
      redirect_to root_url if @micropost.nil?
    end
end

And delete the admin_user method, as it won't be necessary anymore.

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