0

Rails3アプリで使用devise_invitableしています。devise招待者がサインアップする前に、他のユーザーを招待し、それらの招待されたユーザーをグループ化する機能をユーザーに提供したいと思います。

私の問題は、招待者が来てサインアップすると(ただし、招待URLは使用しない)、destroy_if_previously_invitedaround_filterが来て、元のユーザーレコードを破棄し、ユーザーの新しいレコードを再作成して、招待データを保持しますが、 user_groupsはそれと一緒に記録します。

最初に招待されたuser_idに一致するuser_groupsを検索し、新しく作成されたuser_idと一緒に保存することで、このaround_filterを単純にオーバーライドしたいと思います。

エラーが発生し続けます:

LocalJumpError in Users::RegistrationsController#create

no block given (yield)

私のルートは次のようになります:

devise_for :users, :controllers => { :registrations => "users/registrations" }

これをapp/controllers / users/registrations_controller.rbのオーバーライドとして設定しました。

class Users::RegistrationsController < Devise::RegistrationsController

  around_filter :destroy_if_previously_invited, :only => :create


  private    

  def destroy_if_previously_invited
    invitation_info = {}

    user_hash = params[:user]
    if user_hash && user_hash[:email]
      @user = User.find_by_email_and_encrypted_password(user_hash[:email], '')
      if @user
        invitation_info[:invitation_sent_at] = @user[:invitation_sent_at]
        invitation_info[:invited_by_id] = @user[:invited_by_id]
        invitation_info[:invited_by_type] = @user[:invited_by_type]
        invitation_info[:user_id] = @user[:id]
        @user.destroy
      end
    end

    # execute the action (create)
    yield
    # Note that the after_filter is executed at THIS position !

    # Restore info about the last invitation (for later reference)
    # Reset the invitation_info only, if invited_by_id is still nil at this stage:
    @user = User.find_by_email_and_invited_by_id(user_hash[:email], nil)
    if @user
      @user[:invitation_sent_at] = invitation_info[:invitation_sent_at]
      @user[:invited_by_id] = invitation_info[:invited_by_id]
      @user[:invited_by_type] = invitation_info[:invited_by_type]
      user_groups = UserGroup.find_all_by_user_id(invitation_info[:user_id])
      for user_group in user_groups do
        user_group.user_id = @user.id
        user_group.save!
      end
      @user.save!
    end
  end
end

私もこれについてすべて間違っているかもしれません。任意のアイデアをいただければ幸いです。

4

1 に答える 1

0

まず、devise_invitableがすでにこれを設定しているため、around_filterを再度設定する必要はありません。あなたがする必要があるのはあなたのUsersControllerのメソッドを再定義することであり、それらはdevise_invitableのものの代わりに呼び出されます。

次に、2つの方法を組み合わせて、それらを分離してオーバーライドする必要があるようです(これは、最新バージョンのdevise_invitatable 1.1.1に基づいています)。

次のようなものを試してください。

class Users::RegistrationsController < Devise::RegistrationsController
  protected

  def destroy_if_previously_invited
    hash = params[resource_name]
    if hash && hash[:email]
      resource = resource_class.where(:email => hash[:email], :encrypted_password => '').first
      if resource
        @old_id = resource.id #saving the old id for use in reset_invitation_info
        @invitation_info = Hash[resource.invitation_fields.map {|field|
          [field, resource.send(field)]
        }]
        resource.destroy
      end
    end
  end

  def reset_invitation_info
    # Restore info about the last invitation (for later reference)
    # Reset the invitation_info only, if invited_by_id is still nil at this stage:
    resource = resource_class.where(:email => params[resource_name][:email], :invited_by_id => nil).first
    if resource && @invitation_info
      resource.invitation_fields.each do |field|
        resource.send("#{field}=", @invitation_info[field])
      end
      ### Adding your code here
      if @old_id
        user_groups = UserGroup.find_all_by_user_id(@old_id)
        for user_group in user_groups do
          user_group.user_id = resource.id
          user_group.save!
        end
      end
      ### End of your code
      resource.save!
    end
  end
于 2012-10-22T01:21:38.413 に答える