Как вложить devise_invitable так, чтобы пользователя можно было пригласить только в 1 отель

Цель

Я хотел бы, чтобы пользователь user.admin приглашал пользователя только в один из своих отелей с драгоценным камнем devise_invite.

=> User и Hotel связаны через таблицу соединений UserHotel.

Проблема

Я начал сомневаться в том, как я настроил devise(_invitable). С тем, как я его сейчас настроил, я не могу создать user_hotel Join_table и/или добавить определенные параметры отеля для приглашенного пользователя, см. вывод ниже для проверок:

  • контроллер >> @user.hotels => #<ActiveRecord::Associations::CollectionProxy []>

  • консоль:

pry(main)> User.invitation_not_accepted.last.hotels
  User Load (0.6ms)  SELECT  "users".* FROM "users" WHERE "users"."invitation_token" IS NOT NULL AND "users"."invitation_accepted_at" IS NULL ORDER BY "users"."id" DESC LIMIT $1  [["LIMIT", 1]]
  Hotel Load (0.4ms)  SELECT "hotels".* FROM "hotels" INNER JOIN "user_hotels" ON "hotels"."id" = "user_hotels"."hotel_id" WHERE "user_hotels"."user_id" = $1  [["user_id", 49]]
=> []

ОБНОВЛЕНИЕ

Проблема, по-видимому, заключается в отношениях «многие ко многим» между пользователем и отелем. Когда я прерываю действие «нового» контроллера после hotel.user.new и проверяю его, я получаю следующее:

  • >> @user.hotels => #<ActiveRecord::Associations::CollectionProxy []>
  • >> @hotel.users => #<ActiveRecord::Associations::CollectionProxy [#<User id: 2, email: "[email protected]", created_at: "2019-11-05 14:17:46", updated_at: "2019-11-05 15:04:22", role: "admin">, #<User id: nil, email: "", created_at: nil, updated_at: nil, role: "admin">]>

Примечание. Я настроил пользователей с помощью devise, чтобы мой контроллер пользователей был создан следующим образом:

  • пользователи/confirmations_controller.rb
  • пользователи/invitations_controller.rb
  • пользователи/omniauth_callbacks_controller.rb
  • пользователи/password_controller.rb
  • пользователи/registrations_controller.rb
  • пользователи/sessions_controller.rb
  • пользователи/unlocks_controller.rb

Код

маршруты

Rails.application.routes.draw do

  devise_for :users

  resources :hotels do
devise_for :users, :controllers => { :invitations => 'users/invitations' }
  end
end

модели

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  has_many :user_hotels, dependent: :destroy
  has_many :hotels, through: :user_hotels
  accepts_nested_attributes_for :user_hotels
  enum role: [:owner, :admin, :employee]
  after_initialize :set_default_role, :if => :new_record?

  def set_default_role
    self.role ||= :admin
  end

  devise :invitable, :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :invitable
end

class UserHotel < ApplicationRecord
  belongs_to :hotel
  belongs_to :user
end

class Hotel < ApplicationRecord
  has_many :user_hotels, dependent: :destroy
  has_many :users, through: :user_hotels
  accepts_nested_attributes_for :users, allow_destroy: true, reject_if: ->(attrs) { attrs['email'].blank? || attrs['role'].blank?}
end

виды/отели/шоу

<%= link_to "invite new user", new_user_hotel_invitation_path(@hotel)%>

контроллеры/пользователи/invitations_controller.rb

class Users::InvitationsController < Devise::InvitationsController
  def new
    @hotel = Hotel.find(params[:hotel_id])
    @user = @hotel.users.new
  end

  def create
    @hotel = Hotel.find(params[:hotel_id])
    @user = @hotel.users.new(hotel_user_params)
    @user.invite!
  end

  private
  def hotel_user_params
    params.require(:user).permit(:email, :role,
      hotel_users_attributes: [:hotel_id])
  end
end

просмотры/приглашения/new.html.erb

<h2><%= t "devise.invitations.new.header" %></h2>

<%= simple_form_for(resource, as: resource_name, url: user_hotel_invitation_path(@hotel), html: { method: :post }) do |f| %>  <%= f.error_notification %>

  <% resource.class.invite_key_fields.each do |field| -%>
    <div class="form-inputs">
      <%= f.input field %>
    </div>
  <% end -%>

      <%= f.input :role, collection: [:owner, :admin, :employee] %>
  <div class="form-actions">
    <%= f.button :submit, t("devise.invitations.new.submit_button") %>
  </div>
<% end %>

person techquestion    schedule 05.11.2019    source источник


Ответы (2)


Вы проверяли это:

invitation_limit: Количество приглашений, которое могут отправить пользователи. Значение по умолчанию, равное nil, означает, что пользователи могут отправлять столько приглашений, сколько захотят, для любого пользователя нет ограничений, столбец приглашение_limit не используется. Значение 0 означает, что они не могут отправлять приглашения. Параметр n > 0 означает, что они могут отправлять n приглашений. Вы можете изменить столбец «invitation_limit» для некоторых пользователей, чтобы они могли отправлять больше или меньше приглашений, даже если глобальный «Invitation_limit = 0».

Кроме того, было бы очень разумно проверить более подробную информацию о gem для получения дополнительных опций: https://github.com/scambra/devise_invitable

person Nezir    schedule 05.11.2019
comment
Спасибо за ваш комментарий. Я проверил это, но по-прежнему применяю значение по умолчанию nil, поэтому должна быть возможность отправлять приглашения. - person techquestion; 05.11.2019
comment
@techquestion, насколько я понимаю, для этой опции вы должны установить значение 1, чтобы ограничить приглашение только один раз. - person Nezir; 05.11.2019
comment
еще раз спасибо, я по крайней мере должен был проверить это, чтобы быть уверенным;) Только что проверил, но я все еще получаю тот же ответ. - person techquestion; 05.11.2019

У меня есть что-то работающее, даже жесткое. Я не уверен, что это лучший способ сделать это (читай: я очень в этом сомневаюсь).

class Users::InvitationsController < Devise::InvitationsController
  def new
    @hotel = Hotel.find(params[:hotel_id])
    @user = @hotel.users.new
    @user.hotels << @hotel
  end

  def create
    @hotel = Hotel.find(params[:hotel_id])
    @user = @hotel.users.new(hotel_user_params)
    @user.hotels << @hotel
    @user.invite!
  end
person techquestion    schedule 05.11.2019