简体   繁体   中英

Calling a Rails 5 action from one controller to another

I am creating an application that has users and accounts. My issue is that I created the users model and authentication function first but then realized I need to have users belong to accounts.

If I signup a user at route http://lvh.me:3000/signup it will create a new user, send an activation email and activate a user. Works great except it doesn't create the Account . But now, I need to add an account in the mix. If I sign up at my new route http://lvh.me:3000/accounts/new it will create the account and the user, but I need to send the activation email so I can actually activate the user. I can't seem to get my Account controller to trigger the @user.send_activation_email in the create action inside my UserController -- see code below. I know the way I have it below is not the right way, but I've hit a brick wall and not sure where to go from here.

user.rb

class User < ApplicationRecord
  has_many :memberships
  has_many :accounts, through: :memberships
  accepts_nested_attributes_for :accounts
  ...
   # Sends activation email.
  def send_activation_email
    UserMailer.account_activation(self).deliver_now
  end
  ...

account.rb

class Account < ActiveRecord::Base
  belongs_to :owner, class_name: 'User'
  accepts_nested_attributes_for :owner

  has_many :memberships
  has_many :users, through: :memberships
end

accounts_controller.rb

class AccountsController < ApplicationController

  def new
    @account = Account.new
    @account.build_owner
  end

  def create
    @account = Account.new(account_params)
    if @account.save
      @user.send_activation_email
      flash[:info] = 'Please check your email to activate your account.' # Use this for registered users
      # flash[:info] = 'Please have user check their email to activate their account.' # Use this for admin created users
      redirect_to root_url
    else
      flash.now[:alert] = 'Sorry, your account could not be created.'
      render :new
    end
  end

  private

  def account_params
    params.require(:account).permit(:organization, owner_attributes: [:name, :email, :password, :password_confirmation])
  end
end

users_controller.rb

class UsersController < ApplicationController
   ...
    def create
    @user = User.new(user_params)
    if @user.save
      @user.send_activation_email
      flash[:info] = 'Please check your email to activate your account.' # Use this for registered users
      # flash[:info] = 'Please have user check their email to activate their account.' # Use this for admin created users
      redirect_to root_url
    else
      render 'new'
    end
  end
  ...
  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation, accounts_attributes: [:organization])
  end
  ...

If you need both models created as part of the signup flow, then have a single action in a single controller that triggers your signup flow and creates both records.

You can implement this in a number of ways, such as having the Users#signup action create the user and the account inside a transaction, or you can move that logic out of your controller and into your model layer and provide a User.signup method that creates the account explicitly or in an after_create callback.

Either way, the fix here is to simplify and unify your signup flow, not to split it up across several controllers. You only ever need to do that if you have some kind of multi-step signup that requires the user to perform some action between steps.

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