У меня три модели:

  • У пользователей может быть несколько интересов и несколько мест.
  • Пользователи могут иметь одни и те же интересы, но таблица интересов не должна содержать дубликатов, и у пользователя не должно быть дубликатов интересов.
  • У места может быть несколько пользователей, и они могут иметь интересы через своих пользователей.

Я хотел бы иметь возможность создавать пользователя при регистрации и добавлять его интересы и места в качестве связанных атрибутов.

Пользователи могут иметь одинаковые интересы, поэтому, если они уже существуют при регистрации, я хотел бы просто добавить ссылку для нового пользователя.

Что я мог получить до сих пор, так это добавить интересы при регистрации с пользователем, но если интерес уже существует, я получаю сообщение об ошибке, и пользователь вообще не зарегистрирован. Это потому, что я составил указатель интересов и добавил проверку уникальности интересов. Без этого в таблицу интересов добавлялись повторяющиеся интересы.

Вот классы, которые я использую:

models/user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :confirmable, :trackable, :validatable

  has_and_belongs_to_many :interests
  has_and_belongs_to_many :places

  validates :username, uniqueness: { case_sensitive: false }
  validates_associated :interests

  accepts_nested_attributes_for :interests

  def interests_list=value
    value.split(',').each do |interest|
      self.interests.build(:name => interest).save
    end
  end

  def interests_list
    self.interests.join(',')
  end
end

models/place.rb

class Place < ApplicationRecord
  has_and_belongs_to_many :users
  has_many :interests, through: :users
end

models/interest.rb

class Interest < ApplicationRecord
  has_and_belongs_to_many :users

  validates :name, uniqueness: { case_sensitive: false }
end

Форма для Devise:

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <h3>Add interests</h3>

  <div class="field">
    <%= f.label :interests %><br />
    <%= f.text_field :interests_list %>
  </div>

  <% if !user_signed_in? %>
    <h3>Sign up</h3>

      <%= devise_error_messages! %>

      <div class="field">
        <%= f.label :email %><br />
        <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
      </div>

      <div class="field">
        <%= f.label :username %><br />
        <%= f.text_field :username %>
      </div>

      <div class="field">
        <%= f.label :password %>
        <% if @minimum_password_length %>
        <em>(<%= @minimum_password_length %> characters minimum)</em>
        <% end %><br />
        <%= f.password_field :password, autocomplete: "off" %>
      </div>

      <div class="field">
        <%= f.label :password_confirmation %><br />
        <%= f.password_field :password_confirmation, autocomplete: "off" %>
      </div>
  <% end %>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>

<% end %>

Я использую Rails 5.1.4 и Devise 4.4.0

2
KillianKemps 31 Дек 2017 в 23:19

2 ответа

Лучший ответ

Основываясь на ответе Шико, я пробовал разные вещи и в итоге получил следующее:

  def interests_list=value
    current_interest = value.split(',').collect{|interest| interest.strip.downcase}.uniq
    current_interest.each do |interest|
      self.interests << Interest.find_or_create_by(name: interest)
    end
  end

Благодаря этому я могу несколько раз приписывать одинаковый интерес нескольким людям, не имея дубликатов в таблице интересов. Спасибо за помощь!

0
KillianKemps 1 Янв 2018 в 15:15

Вы можете быстро проверить интересы перед их сохранением или использовать .first_or_create, чтобы создать интерес, если он не существует, как показано ниже:

 def interests_list=value
    current_interest = value.split(',')
    unique_interest = current_interest - Interest.where(name: current_interest).pluck(:name)
    unique_interest.each do |interest|
      self.interests.build(:name => interest).save
    end
 end
0
Shiko 1 Янв 2018 в 19:22