问题
So I have OrdersController#Create
, that I would like the user to be redirected to right after they register (so it can do some post-registration stuff).
Before I implemented the registration part of this workflow, this is what the link_to
for that resource looked like:
<%= link_to 'Submit to Scheduling', orders_path(cart_id: @cart), method: :post, data: { confirm: "Are you sure?" }, class: "primary button btn" %>
So basically, I would like to achieve the above functionality (including passing the @cart
object as a param), but automatically from within the Devise::RegistrationsController#Create
.
I am using Devise, and so I have created a /users/registrations_controller.rb
and in that controller I am doing this:
def after_sign_up_path_for(resource)
orders_path(cart_id: @cart)
super(resource)
end
When I did the above, it successfully created the user and redirected me to Orders#Index
which is not what I want, see the logs below:
User Create (1.3ms) INSERT INTO "users" ("email", "encrypted_password", "first_name", "last_name", "created_at", "updated_at", "company_name", "company_title", "phone") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id" [["email", "abc3@test.com"], ["encrypted_password", "$2a$11$ZC2X2vCXd5JwVO"], ["first_name", "Test"], ["last_name", "User 3"], ["created_at", "2020-01-22 06:16:11.358863"], ["updated_at", "2020-01-22 06:16:11.358863"], ["company_name", "Acme Inc"], ["company_title", "CFO"], ["phone", "9876543210"]]
↳ app/controllers/users/registrations_controller.rb:14:in `create'
(0.6ms) COMMIT
↳ app/controllers/users/registrations_controller.rb:14:in `create'
Redirected to http://localhost:3000/orders
Completed 302 Found in 162ms (ActiveRecord: 5.3ms | Allocations: 6383)
Started GET "/orders" for ::1 at 2020-01-22 01:16:11 -0500
Processing by OrdersController#index as HTML
I even tried orders_path(cart_id: @cart, method: :post)
and that didn't work.
How do I achieve what I am trying to do?
Edit 1
So I discovered url_for
and it ALMOST gets me there, but doesn't quite work.
This is what I have:
url_for(controller: '/orders', action: 'create', method: :post, cart_id: @cart.id, only_path: true)
This is what happens:
↳ app/controllers/users/registrations_controller.rb:14:in `create'
User Create (5.5ms) INSERT INTO "users" ("email", "encrypted_password", "first_name", "last_name", "created_at", "updated_at", "company_name", "company_title", "phone") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id" [["email", "abc2@test.com"], ["encrypted_password", "$2a$ezj6"], ["first_name", "Test"], ["last_name", "User 2"], ["created_at", "2020-01-22 07:26:09.589560"], ["updated_at", "2020-01-22 07:26:09.589560"], ["company_name", "Acme Inc"], ["company_title", "CEO"], ["phone", "9876543210"]]
↳ app/controllers/users/registrations_controller.rb:14:in `create'
(1.1ms) COMMIT
↳ app/controllers/users/registrations_controller.rb:14:in `create'
/.rvm/gems/ruby-2.7.0@myapp/gems/devise-4.7.1/app/controllers/devise_controller.rb:187: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
.rvm/gems/ruby-2.7.0@myapp/gems/i18n-1.8.1/lib/i18n.rb:195: warning: The called method `t' is defined here
Redirected to http://localhost:3000/orders?cart_id=10&method=post
Completed 302 Found in 307ms (ActiveRecord: 13.2ms | Allocations: 8600)
Started GET "/orders?cart_id=10&method=post" for ::1 at 2020-01-22 02:26:09 -0500
Processing by OrdersController#index as HTML
So it still doesn't work. It is still sending me to OrdersController#Index
.
回答1:
You don't need super(resource)
.
In my understanding, you want to redirect to orders_path(cart_id: @cart) with post
method. It's so weird. after_sign_up_path_for
should return a some_path, which accessed by get
method.
You can try another way, perform another action from another controller. I think this will helpful to you.
回答2:
request.params.merge!(cart_id: @cart.id)
controller_you_want = OrdersController.new
controller_you_want.request = request
controller_you_want.response = response
controller_you_want.create
Did you try this ?
回答3:
The problem you have is that your code is returning the original value of the method, not the new path:
def after_sign_up_path_for(resource)
orders_path(cart_id: @cart)
super(resource)
end
Returns the overridden method, since you are calling super(resource)
as the final expression in the method, and its result gets returned by your defined method.
If it is necessary to call super at all, because the overridden method does something more than just return a string, then either return the order of the calls, or return the value of orders_path
with a variable.
def after_sign_up_path_for(resource)
res = orders_path(cart_id: @cart)
super(resource)
res
end
You should check the method being called by super though, as it is possible you can just remove this completely.
Without seeing the rest of your code it is impossible to say whether @cart
actually has a value, or is in fact just nil
. You should check that it has been set in the controller prior to the after_sign_up_path_for
method being called.
回答4:
You could use Devise::Controllers::StoreLocation#store_location_for which is used to redirect back after signing in.
store_location_for(current_user, new_order_path(cart_id: @cart))
This stores the location is the session. You can fetch the value with stored_location_for
.
def after_sign_up_path_for(resource)
stored_location_for(resource) || super
end
However you can't/should not redirect to the create action. Create responds to POST requests. Redirects are always GET requests. Before you go adding a GET /posts/create
route remember that GET should not be used for non-idempotent actions. Meaning that a GET request should not create or alter any resources.
If you break this rule your users could have a really bad day when they hit the back button.
And no you don't want to store and repeat the post action. Have the user submit the form - save the record and then redirect. Add a flag to the record if needed to mark it as "not finshed". Redirect the user back to the edit
action and then "finish the order" by performing a PUT or PATCH request (update).
来源:https://stackoverflow.com/questions/59853763/how-do-i-redirect-after-sign-up-path-for-to-a-create-action-of-another-controlle