简体   繁体   中英

Best practice for per-user strong parameters?

I have an application with an Order model, connected to a Purchaser and a Supplier . The application is designed to limit who can create/update/destroy orders depending on their affiliation with these companies. (For instance, a member of a purchaser can create an order, but a member of a supplier cannot.)

I am enforcing these authorization rules at the controller level via strong parameters. My reasoning is twofold:

  1. deferring them to a before_save callback (or other model logic) would remove parameter screening from the controller (where it belongs); and
  2. even then, I'd have to pass additional information (namely, user identity) from the controller to the models to get it done, and that would lead to more tightly coupled classes.

Currently, my strong param logic looks like this:

def create_order_params
  params.require(:order).permit(:supplier_id, :purchaser_id, :notes)
    .merge({ placed_by: current_user })
end

def update_order_params
  params.require(:order).permit().tap do |p|
    p.merge!({ accepted_by: current_user }) if params.dig(:order, :accepted)
    if current_user.belongs_to?(@order.supplier)
      p.merge!(params[:order].permit(:discount, :discount_type))
    end
    if current_user.belongs_to?(@order.purchaser) && !@order.confirmed?
      p.merge!(params[:order].permit(:notes))
    end
  end
end

I think it's terribly unreadable. Is there a cleaner (or widely accepted) pattern for applying some authorization logic to strong parameters? Alternately, is this the wrong abstraction? Should I defer this authorization to the model after all?

Since each type [Purchasers or Suppliers] has some authorities [or functions to do] and it is the only one who is authorized for such actions, then I suggest you place each type of tasks as a method in either the [Purchasers or Suppliers] classes depending on which one has to do this method or task.

For example :

Since the Purchasers are only the ones who creates an Order so it would be reasonable to put a create order method in the Purchaser class, so that each object has its responsibilities it needs to carry, and these methods can not be carried or accessed by any other entities since they do not have these methods encapsulated in them.

Thinking in an object oriented approach, and considering the 'single responsibility principle' , will lead you to having a better organizing and making the code more clean.

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