0
votes

Comment rediriger after_sign_up_path_for vers une action de création d'un autre contrôleur?

J'ai donc OrdersController # Create , vers lequel je voudrais que l'utilisateur soit redirigé juste après son inscription (afin qu'il puisse faire des choses après l'enregistrement).

Avant de mettre en œuvre le partie enregistrement de ce flux de travail, voici à quoi ressemblait le link_to pour cette ressource:

↳ 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

Donc, fondamentalement, j'aimerais obtenir la fonctionnalité ci-dessus (y compris en passant l'objet @cart en tant que paramètre), mais automatiquement à partir de Devise::RegistrationsController#Create.

J'utilise Devise, et donc j'ai créé un /users/registrations_controller.rb et dans ce contrôleur je fais ceci:

url_for(controller: '/orders', action: 'create', method: :post, cart_id: @cart.id, only_path: true)

Quand j'ai fait ce qui précède, il a créé l'utilisateur avec succès et m'a redirigé vers Orders # Index , ce qui n'est pas ce que je veux, voir les journaux ci-dessous:

 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

J'ai même essayé orders_path (cart_id: @cart, method:: post) et cela n'a pas fonctionné.

Comment puis-je réaliser ce que j'essaie de faire?

Modifier 1

J'ai donc découvert url_for et cela m'y mène PRESQUE, mais ne fonctionne pas tout à fait.

Ceci est ce que j'ai:

  def after_sign_up_path_for(resource)
    orders_path(cart_id: @cart)
    super(resource)
  end

Voici ce qui se passe:

<%= link_to 'Submit to Scheduling', orders_path(cart_id: @cart), method: :post, data: { confirm: "Are you sure?" }, class: "primary button btn" %>

Donc ça ne marche toujours pas. Il m'envoie toujours à OrdersController#Index.


1 commentaires

Quel était le comportement avant votre changement? Vous a-t-il redirigé vers un autre chemin ou a-t-il créé une nouvelle ressource?


4 Réponses :


1
votes

Vous n'avez pas besoin de super (ressource) .

Si je comprends bien, vous souhaitez rediriger vers orders_path (cart_id: @cart) avec la méthode post . Il est tellement bizarre. after_sign_up_path_for doit renvoyer un some_path, accessible par la méthode get .

Vous pouvez essayer une autre manière, effectuer une autre action à partir d'un autre contrôleur. Je pense que cela vous sera utile.


3 commentaires

La méthode url_for est donc très proche de ce que je souhaite. Le problème est que je dois également transmettre la variable d'instance @cart . Comment je fais ça?


Vous ne pouvez pas transmettre une variable d'instance telle que @cart , mais vous pouvez transmettre l'ID de @cart et effectuer une recherche avec l'ID.


Comment passer la méthode? Je veux que l'action create de la route orders_path soit exécutée, pas l ' index . Même si j'ai spécifié create dans l'action, il va toujours à orders # index . En d'autres termes, je souhaite envoyer la même ressource avec une method:: post à orders_path et la faire envoyer à Order # Create et pas Order # Index . Les pensées?



0
votes
  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 ?

0 commentaires

0
votes

Le problème que vous avez est que votre code renvoie la valeur d'origine de la méthode, pas le nouveau chemin:

def after_sign_up_path_for(resource)
  res = orders_path(cart_id: @cart)
  super(resource)
  res
end

Renvoie la méthode remplacée, puisque vous appelez super ( resource) comme expression finale de la méthode, et son résultat est renvoyé par la méthode que vous avez définie.

S'il est nécessaire d'appeler super, car la méthode surchargée fait plus que simplement retourne une chaîne, puis retourne l'ordre des appels, ou renvoie la valeur de orders_path avec une variable.

def after_sign_up_path_for(resource)
  orders_path(cart_id: @cart)
  super(resource)
end

Vous devriez vérifier la méthode étant appelé par super cependant, car il est possible que vous puissiez simplement le supprimer complètement.

Sans voir le reste de votre code, il est impossible de dire si @cart a réellement une valeur , ou est en fait juste nul . Vous devez vérifier qu'il a été défini dans le contrôleur avant que la méthode after_sign_up_path_for ne soit appelée.


0 commentaires

0
votes

Vous pouvez utiliser Devise :: Controllers: : StoreLocation # store_location_for qui est utilisé pour rediriger après la connexion.

def after_sign_up_path_for(resource)
  stored_location_for(resource) || super
end

Cela stocke l'emplacement est la session. Vous pouvez récupérer la valeur avec stored_location_for .

store_location_for(current_user, new_order_path(cart_id: @cart))

Cependant, vous ne pouvez / ne devez pas rediriger vers l'action de création. Create répond aux requêtes POST. Les redirections sont toujours des requêtes GET. Avant d'ajouter une route GET / posts / create , rappelez-vous que GET ne doit pas être utilisé pour des actions non idempotentes. Cela signifie qu'une requête GET ne doit pas créer ni modifier de ressources.

Si vous enfreignez cette règle, vos utilisateurs pourraient passer une très mauvaise journée en appuyant sur le bouton Précédent.

Et non, vous ne voulez pas stocker et répéter l'action de publication. Demandez à l'utilisateur de soumettre le formulaire - enregistrez l'enregistrement, puis redirigez-le. Ajoutez un drapeau à l'enregistrement si nécessaire pour le marquer comme "non terminé". Redirigez l'utilisateur vers l'action edit puis "terminez la commande" en effectuant une requête PUT ou PATCH (mise à jour).


0 commentaires