代码之家  ›  专栏  ›  技术社区  ›  KillianKemps

如何在注册设备时添加或更新相关属性,同时创建新用户?

  •  2
  • KillianKemps  · 技术社区  · 8 年前

    我有三个模型:

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

    我希望能够在注册时创建一个用户,并将其兴趣和位置添加为相关属性。

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

    到目前为止,我能得到的是在与用户注册时添加兴趣,但如果兴趣已经存在,那么我会得到一个错误,并且用户根本没有注册。 这是因为我在兴趣上建立了一个索引,并在兴趣上添加了唯一性验证。没有它,它就在利息表中添加了重复的利息。

    以下是我使用的类:

    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和Desive 4.4.0

    2 回复  |  直到 8 年前
        1
  •  0
  •   KillianKemps    8 年前

    根据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
    

    有了这个,我可以多次将相同的兴趣赋予几个人,而不会在兴趣表中出现重复的兴趣。 感谢您的帮助!

        2
  •  0
  •   Shiko    8 年前

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