【问题标题】:Rails - Devise - Add profile information to separate tableRails - 设计 - 将配置文件信息添加到单独的表
【发布时间】:2016-03-17 04:37:46
【问题描述】:

我正在使用 Devise 在我的应用程序中构建注册/身份验证系统。

查看了很多用于向设计模型添加信息的资源(例如用户名、传记、头像 URL 等。)[资源包括 Jaco Pretorius' websitethis (badly formed) SO questionand this SO question

这一切都很好——它有效。但我的问题是它保存到用户模型,根据database normalizations (also referencing this SO question),它实际上应该保存到通过has_onebelongs_to 连接的用户子模型。

到目前为止,我已经通过 Devise 创建了一个 User 模型。我还通过rails generate 脚本创建了UserProfile 模型。

user.rb(供参考)

class User < ActiveRecord::Base
  devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :trackable, :validatable

  has_one :user_profile, dependent: :destroy
end

user_profile.rb

class UserProfile < ActiveRecord::Base
  belongs_to :user
end

timestamp_create_user_profiles.rb

class CreateUserProfiles < ActiveRecord::Migration
  def change
    create_table :user_profiles do |t|
      t.string :username, null: false
      t.string :biography, default: ""

      t.references :user, index: true, foreign_key: true

      t.timestamps null: false
    end
    add_index :user_profiles, [:user_id, :username]
  end
end

我现在的问题是,如何收集这两种模型的信息并通过设计注册表单确保它们最终都在正确的位置?

我看到了有关创建状态机的资源(AASMthe answer to this SO question。我还看到了有关在同一主题上创建 a wizard with WICKEDan article 的信息。

对于我的用例来说,这些似乎都太复杂了。有什么方法可以简单地将输入与设计分开并确保最终出现在正确的位置?

【问题讨论】:

    标签: ruby-on-rails ruby devise


    【解决方案1】:

    我认为,与其简单地评论一个让我得到最终答案的答案,我会在此处存档答案,以防将来有人也试图找到这个答案:

    我会假设你已经像我上面所做的那样进行了某种设置。

    第一步是您需要将您的用户控制器修改为accept_nested_attributes_for 配置文件引用,并向模型添加一个实用方法,以便在代码中请求时,应用程序可以检索已构建的配置文件模型或构建一个。

    用户模型最终看起来像这样:

    class User < ActiveRecord::Base
      devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :trackable, :validatable
    
      has_one :user_profile, dependent: :destroy
      accepts_nested_attributes_for :user_profile
    
      def user_profile
        super || build_user_profile
      end
    end
    

    其次,您需要修改您的注册/帐户更新表单,以便能够将此辅助模型的属性传递到控制器,并最终能够为父模型构建配置文件。

    您可以使用f.fields_for 来做到这一点。

    在您的表单中添加类似的内容:

    <%= f.fields_for :user_profile do |user_profile_form| %>
     <%= user_profile_form.text_field :attribute %>
    <% end %>
    

    在我的具体情况下的一个例子是:

    <%= f.fields_for :user_profile do |user_profile_form| %>
      <div class="form-group">
        <%= user_profile_form.text_field :username, class: "form-control", placeholder: "Username" %>
      </div>
    <% end %>
    

    最后,您需要告诉 Devise 它应该接受这个新的参数散列并将其传递给模型。

    如果您创建了自己的 RegistrationsController 并扩展了 Devise,它应该类似于:

    class RegistrationsController < Devise::RegistrationsController
      private
        def sign_up_params
          params.require(:user).permit(:email, :password, user_profile_attributes: :username)
        end
    end
    

    (当然,为您的特定用例进行适当的更改。)

    如果您只是将 Devise 清理方法添加到您的应用程序控制器,它应该类似于:

    class ApplicationController < ActionController::Base
      before_filter :configure_permitted_parameters, if: :devise_controller?
    
      protected
        def configure_permitted_parameters
          devise_parameter_sanitizer.for(:sign_up) {|u|
            u.permit(:email, :password, user_profile_attributes: :username)}
        end
    end
    

    (同样,针对您的特定用例进行适当的更改。)

    关于user_profile_attributes: :username的小提示: 注意这是一个hash,当然。如果您有多个要传递的属性,例如 account_update(提示提示),则需要像 user_profile_attributes: [:attribute_1, :attribute_2, :attribute_3] 那样传递它们。

    【讨论】:

      【解决方案2】:

      【讨论】:

      • 您对文档的引用和其他 SO 问题终于让我找到了答案。
      【解决方案3】:

      另请注意,对于 Devise 4.2,devise_parameter_sanitizer 的“.for”方法已被弃用,取而代之的是“.permit”

      来自documentation

      def configure_permitted_parameters
        devise_parameter_sanitizer.permit(:sign_in) do |user_params|
          user_params.permit(:username, :email)
        end
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-24
        • 2011-08-16
        • 2013-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-14
        • 2013-11-14
        相关资源
        最近更新 更多