如何在使用Devise注册时创建新用户时添加或更新关联的属性?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在使用Devise注册时创建新用户时添加或更新关联的属性?相关的知识,希望对你有一定的参考价值。

我有三种型号:

  • 用户可以拥有多个兴趣点和多个位置。
  • 用户可以共享相同的兴趣,但兴趣表不应包含重复项,用户也不应该有重复的兴趣。
  • 一个地方可以拥有多个用户,并且可以通过其用户拥有兴趣。

我希望能够在注册时创建用户并将其兴趣和地点添加为关联属性。

用户可以共享相同的兴趣,因此如果注册时已经存在兴趣,我想简单地为新用户添加链接。

到目前为止我可以获得的是在与用户注册时添加兴趣,但如果已经存在兴趣,那么我会收到错误并且用户根本没有注册。这是因为我对利益进行了索引,并对利益进行了独特性验证。没有它,它会在兴趣表中添加重复的兴趣。

这是我使用的类:

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

设计形式:

<%= 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

答案

基于Shiko答案,我尝试了一些东西,最后得到了以下结果:

  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

有了这个,我能够将几个相同的兴趣归因于几个人而没有在Interest表中重复。谢谢你的帮助!

另一答案

您可以在保存之前快速检查兴趣,或者如果不存在则使用.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

以上是关于如何在使用Devise注册时创建新用户时添加或更新关联的属性?的主要内容,如果未能解决你的问题,请参考以下文章

当角色名称需要与role_id匹配时(使用devise)添加要选择的角色来设计注册表单

Rails - 如何覆盖设计SessionsController以在用户登录时执行特定任务?

每次使用 Rails 3 中的 Devise 登录时,如何检查用户帐户?

使用 Devise 和 Paypal 进行用户注册

Rails 4.2 / Devise - 如果禁用cookie,则向用户显示特定消息

扩展设备注册控制器