【问题标题】:Rails 4 - setup, automatically create profile when new user createdRails 4 - 设置,创建新用户时自动创建配置文件
【发布时间】:2016-03-15 12:19:53
【问题描述】:

我已经尝试整理这篇文章,所以对于新来的人来说似乎不会太长。它包括因以下答案中的其他人的建议而导致的错误。

我正在尝试使用 Rails 4 制作应用程序。

我使用设计和omniauth。

我有用户和个人资料的模型。用户有一个个人资料,个人资料属于用户。

我的目标是将用户模型用于用户没有真正触及的所有事物。我将配置文件模型用于用户维护的事情。

创建新用户后,我希望将用户重定向到他们的个人资料页面,该页面应部分填充在用户模型中创建的详细信息。

我遇到了麻烦。

我有:

用户.rb

has_one :profile

个人资料.rb

belongs_to :user

Omniauth_callbacks_controller.rb

if @user.persisted?
  sign_in_and_redirect_user(:user, authentication.user.profile)
  set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
else
  session["devise.#{provider}_data"] = env["omniauth.auth"]
  redirect_to new_user_registration_url
end

我也尝试过回调重定向:

 sign_in_and_redirect @user,  event: :authentication

profiles/show.html.erb

<div class="container-fluid">
    <div class="row">
        <div class="col-xs 8 col-xs-offset-1">
            <%= @profile.user.formal_name %>


            <%= @profile.occupation %>
            <%= @profile.qualification.awards %>
            <%= @profile.overview %>
            <%= @profile.research_interests %>

        </div>

        <div class="col-xs 3">
            <div class="geobox">
            <%= render 'addresses/location' %>
            <%= @profile.working_languages %>
            <%= @profile.external_profile %>

            </div>
        </div>  
    </div>

    <div class="row">
        <div class="col-xs 10 col-xs-offset-1">
            <%= render 'profiles/activity' %>
        </div>
    </div>  

</div>

_nav.html.erb

<% if user_signed_in? %>
                    Hi <%= link_to(current_user.first_name.titlecase, profile_path(current_user)) %></span>

我也试过了:

_nav.html.erb

<% if user_signed_in? %>
                    Hi <%= link_to(current_user.first_name.titlecase, user_profile_path(current_user.profile)) %></span>

我需要做什么才能添加某种功能让新用户访问他们的个人资料页面?

目前,当我尝试登录并单击导航栏链接时,我想转到个人资料页面。相反,我转到一条错误消息,指出我要查找的页面不存在。它正在寻找的路径从配置文件(而不是用户/配置文件)开始 - 不确定这是否是一个线索。

我的路线是:

个人资料:

profiles GET       /profiles(.:format)                    profiles#index
                         POST      /profiles(.:format)                    profiles#create
             new_profile GET       /profiles/new(.:format)                profiles#new
            edit_profile GET       /profiles/:id/edit(.:format)           profiles#edit
                 profile GET       /profiles/:id(.:format)                profiles#show
                         PATCH     /profiles/:id(.:format)                profiles#update
                         PUT       /profiles/:id(.:format)                profiles#update
                         DELETE    /profiles/:id(.:format)                profiles#destroy

用户:

user_password POST      /users/password(.:format)              devise/passwords#create
       new_user_password GET       /users/password/new(.:format)          devise/passwords#new
      edit_user_password GET       /users/password/edit(.:format)         devise/passwords#edit
                         PATCH     /users/password(.:format)              devise/passwords#update
                         PUT       /users/password(.:format)              devise/passwords#update
cancel_user_registration GET       /users/cancel(.:format)                users/registrations#cancel
       user_registration POST      /users(.:format)                       users/registrations#create
   new_user_registration GET       /users/sign_up(.:format)               users/registrations#new
  edit_user_registration GET       /users/edit(.:format)                  users/registrations#edit
                         PATCH     /users(.:format)                       users/registrations#update
                         PUT       /users(.:format)                       users/registrations#update
                         DELETE    /users(.:format)                       users/registrations#destroy
       user_confirmation POST      /users/confirmation(.:format)          devise/confirmations#create
   new_user_confirmation GET       /users/confirmation/new(.:format)      devise/confirmations#new
                         GET       /users/confirmation(.:format)          devise/confirmations#show
             user_unlock POST      /users/unlock(.:format)                devise/unlocks#create
         new_user_unlock GET       /users/unlock/new(.:format)            devise/unlocks#new
                         GET       /users/unlock(.:format)                devise/unlocks#show
           finish_signup GET|PATCH /users/:id/finish_signup(.:format)     users#finish_signup

新尝试: 根据以下建议,我将资源嵌套为:

  resources :users do
     resources :profile
  end

我将重定向更改为:

def self.provides_callback_for(provider)
    class_eval %Q{
      def #{provider}
        @user = User.find_for_oauth(env["omniauth.auth"])

        if @user.persisted?
           sign_in_and_redirect [current_user, current_user.profile || current_user.build_profile]

          set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
        else
          session["devise.#{provider}_data"] = env["omniauth.auth"]
          redirect_to new_user_registration_url
        end
      end
    }
  end

我收到此错误:NoMethodError(nil:NilClass 的未定义方法 `profile'):

下一次尝试:

我保留以上所有内容,但尝试像这样替换重定向:

def self.provides_callback_for(provider)
    class_eval %Q{
      def #{provider}
        @user = User.find_for_oauth(env["omniauth.auth"])

        if @user.persisted?
           sign_in_and_redirect [@user, @user.profile || @user.build_profile]

          set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
        else
          session["devise.#{provider}_data"] = env["omniauth.auth"]
          redirect_to new_user_registration_url
        end
      end
    }
  end

RuntimeError (Could not find a valid mapping for [#<User id: 1 ... 

然后它会列出用户表中的所有属性,然后显示:

#<Profile id: nil, user_id: 1, 

紧随其后的是配置文件表中的所有属性。

新尝试

我发现了这个帖子:Rails Trying to create a profile after the user has been created

我尝试添加:

 after_create do
    create_user_profile
  end

到我的用户模型。

我将重定向保持不变(按照 Alexei 的建议)并再次尝试。

我收到同样的错误信息:

RuntimeError (Could not find a valid mapping for [#<User id: 1

谁能看看如何解决这个问题?

进一步的尝试:

然后我发现了这个帖子: Ruby on Rails - Creating a profile when user is created

对于 Rails 4(我使用),我只需要这个回调:

after_create :create_profile

当我尝试这个时,我得到了与上面相同的错误。

一个想法:

我为我的配置文件控制器使用了脚手架生成器。

我的创建方法是:

  def create
    @profile = Profile.new(profile_params)

    respond_to do |format|
      if @profile.save
        format.html { redirect_to @profile }
        format.json { render :show, status: :created, location: @profile }
      else
        format.html { render :new }
        format.json { render json: @profile.errors, status: :unprocessable_entity }
      end
    end
  end

此错误是否可能与此方法中未具体引用用户 ID 有关。我已在配置文件控制器的强参数中将 user_id 列入白名单。

新尝试

本文建议使用 build_profile 而不是 create_profile。

https://stackoverflow.com/questions/8337682/create-another-model-upon-user-new-registration-in-devise

我将 user.rb 更改为

  after_create :build_profile

当我保存并尝试时,我得到了同样的错误。

另一个尝试

Matt 在这篇文章中的回答表明我必须将 build_profile 的定义包含为:

 after_create :build_profile

  def build_profile
    Profile.create(user: self) # Associations must be defined correctly for this syntax, avoids using ID's directly.
  end

我将 user.rb 更改为:

  after_create :build_profile

  def build_profile
    Profile.create(user: self) # Associations must be defined correctly for this syntax, avoids using ID's directly.
  end

当我保存并尝试此操作时,我收到了类似的错误,但包含更多信息。日志仍然显示:

RuntimeError (Could not find a valid mapping for [#<User id: 1,

但在所有这些错误消息之后,它提供了以下新信息:

SQL (2.9ms)  INSERT INTO "profiles" ("user_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["user_id", 1], ["created_at", "2015-12-18 21:58:49.993866"], ["updated_at", "2015-12-18 21:58:49.993866"]]
2015-12-18T21:58:49.966648+00:00 app[web.1]:   Profile Load (1.5ms)  SELECT  "profiles".* FROM "profiles" WHERE "profiles"."user_id" = $1 LIMIT 1  [["user_id", 1]]
2015-12-18T21:58:50.007428+00:00 app[web.1]: Completed 500 Internal Server Error in 113ms (ActiveRecord: 21.8ms)
2015-12-18T21:58:49.941385+00:00 app[web.1]:   User Load (1.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]

这对问题有任何启示吗?

更新

我再次尝试了这个(没有对代码进行任何更改)。现在我得到一个错误,但这次日志说:

RuntimeError (Could not find a valid mapping for [#<User id: 1, first_name: "Me", last_name: "Ma", email: "mema@gmail.com", encrypted_password: "$2a$jqQn..HSvlcNtfAH/28.DQoWetO...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 16, current_sign_in_at: "2015-12-15 09:57:14", last_sign_in_at: "2015-12-15 09:27:07", current_sign_in_ip: #<IPAddr: IPv4:49.191.55>, last_sign_in_ip: #<IPAddr: IPv4:49.191.135.255.255>, confirmation_token: nil, confirmed_at: "2015-12-15 09:02:58", confirmation_sent_at: "2015-12-15 08:42:48", unconfirmed_email: nil, failed_attempts: 0, unlock_token: nil, locked_at: nil, created_at: "2015-12-09 23:53:20", updated_at: "2015-12-15 09:57:14", image: nil>, #<Profile id: 1, user_id: 1, title: nil, hero_image: nil, overview: nil, occupation: nil, external_profile: nil, working_languages: nil, created_at: "2015-12-18 21:58:49", updated_at: "2015-12-18 21:58:49">]):

这次的不同之处在于配置文件的用户 ID 键为 1。以前,这是 nil。

【问题讨论】:

  • 您如何rake routes 寻找用户和配置文件路径? :)
  • 嗨大卫,我在上面复制了它们
  • “它正在寻找的路径从配置文件(而不是用户/配置文件)开始 - 不确定这是否是一个线索。”您是否希望每个用户都链接到唯一的个人资料?或者您希望能够访问domain/profile/1 以获取第一个个人资料?
  • 每个用户都应该有自己的个人资料页面。我正在努力做到这一点,所以当每个用户登录时,他们都会被重定向到自己的个人资料页面
  • 您的应用程序控制器中有after_sign_in_path_for 吗? github.com/plataformatec/devise/wiki/…

标签: ruby-on-rails path routes resources


【解决方案1】:

你可以使用嵌套资源

resources :users do
  resource :profile
end

然后

redirect_to [current_user, current_user.profile || current_user.build_profile]

【讨论】:

  • 嗨 - 我试过这个,但得到这个错误:NoMethodError (undefined method `profile' for nil:NilClass): 2015-12-15T10:33:09.278064+00:00 app[web.1 ]:
  • 它告诉你没有 current_user (current_user == nil)。如果已定义,请使用 @user。
  • 嗨,阿列克谢。我用设计。我有 current_user 助手可用。另外,当方法说配置文件时,您确定它在谈论用户吗?非常感谢您的帮助
  • 当我用@user 尝试它时,我仍然得到同样的错误。我更新了帖子以显示在上面。
  • 该错误清楚地表明您正在向 NilClass 发送消息“配置文件”(即 nil.profile)。要仔细检查,请在“redirect_to”之前添加“puts current_user.inspect”。
【解决方案2】:

您在回调控制器中添加了sing_in_and_redirect_user。 要编辑它重定向到的路径,您还应该覆盖并编辑 after_sign_in_path_for 在你的applications_controller 中。

class ApplicationController < ActionController::Base
  def after_sign_in_path_for(resource)
    request.env['omniauth.origin'] || stored_location_for(resource) || root_path
  end
end

您可以在此处编辑重定向到的实际路径。不确定omniauth部分,但您可以添加profile_path(resource.profile)

参考: https://github.com/plataformatec/devise/wiki/How-To:-redirect-to-a-specific-page-on-successful-sign-in

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-02
    • 2020-08-03
    • 1970-01-01
    • 2011-08-05
    • 2012-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多