Polymorphic event notification model in Rails
Here's a really basic refactor of notification_redirection_path:

def notification_redirection_path(notifiable_type:, notifiable_id:, notification_action:, **)
  case notification_action
  when "commented"
    case notifiable_type
    when "Post"
      posts_path(anchor: "post_#{notifiable_id}")
    when "Product"
      product_path(notifiable_id, anchor: "comment-panel")
    when "ProductLead"
      product_lead = ProductLead.find(notifiable_id)
      product_product_lead_path(product_lead.product_id, notifiable_id, anchor: "comment-panel")
    when "ProductCustomer"
      product_customer = ProductCustomer.find(notifiable_id)
      product_product_customer_path(product_customer.product_id, notifiable_id, anchor: "comment-panel")
    end
  when "invited"
    product_path(notifiable_id, anchor: "product-invitation-well")
  when "accepted"
    product_product_users_path(notifiable_id)
  end
end


A few things to notice:


I changed the method arguments to keyword arguments. This way instead of doing this:

redirect_to notification_redirection_path(
  params[:notifiable_type], 
  params[:notifiable_id], 
  params[:notification_action]
)


...we can do this:

redirect_to notification_redirection_path(params)

I turned the outer if expression into a case expression. I also changed the indentation so the whens line up with their case. Usually I prefer the other style (like you wrote it) but I find with nested cases this is a bit easier to read.
I removed your initial if notifier_type == ... expression and moved that logic into the when "ProductLead" and when "ProductCustomer" blocks below. No need to have those in two separate places.


This is still pretty messy, though. A quick win for readability, maintainability, and testability would be to split it into separate methods:

def notification_redirection_path(notifiable_type:, notifiable_id:, notification_action: nil, **)
  case notifiable_type
  when "commented"
    commented_notification_redirection_path(notifiable_type, notifiable_id)
  when "invited"
    product_path(notifiable_id, anchor: "product-invitation-well")
  when "accepted"
    product_product_users_path(notifiable_id)
  end
end

private
def commented_notification_redirection_path(type, id)
  case type
  when "Post"
    posts_path(anchor: "post_#{id}")
  when "Product"
    product_path(id, anchor: "comment-panel")
  when "ProductLead"
    product_lead = ProductLead.find(id)
    product_product_lead_path(product_lead.product_id, id, anchor: "comment-panel")
  when "ProductCustomer"
    product_customer = ProductCustomer.find(id)
    product_product_customer_path(product_customer.product_id, id, anchor: "comment-panel")
  end
end


You could employ polymorphic_path to take this to its extreme conclusion, which might look something like this:

ACTION_ANCHORS = {
  "commented" =&gt; "comment-panel",
  "invited" =&gt; "product-invitation-well"
}

def notification_redirection_path(notifiable_type:, notifiable_id:, notification_action:, **)
  if notification_action == "commented" &amp;&amp; notifiable_type == "Product"
    return posts_path(anchor: "post_#{notifiable_id}")
  end

  notifiable = notifiable_type.constantize.find(notifiable_id)

  path =
    if notification_action == "commented" &amp;&amp;
        (ProductLead === notifiable || ProductCustomer === notifiable)
      [ notifiable.product, notifiable ]
    elsif notification_action == "accepted"
      [ notifiable, :product_user ]
    else
      [ notifiable ]
    end

  polymorphic_path(path,
    anchor: ACTION_ANCHORS[notification_action])
end


...but it's probably not worth it, since you lose a lot in readability and maintainability.