3

我对 Rails 非常陌生,并且有点挣扎。

我的用户遵循基本的注册、编辑流程。

我有一种情况,用户可以“部分注册”,即数据库中的用户电子邮件地址具有随机密码,因为他们通过现有用户的邀请过程放入其中。

当技术上已经存在于数据库中的受邀用户尝试注册时,我会得到“电子邮件已经存在”,因为我确实对用户对象应用了唯一性检查,并且在表上设置了唯一索引。

我确实将其关闭并在 create 方法中使用 if 语句来查看用户是否存在并检查其他值是否进行了更新或新建并保存。所有 if 条件都被忽略并创建了一个新用户。

我想要做的是使用“创建”用户的相同注册表单,以使用输入的密码和名称更新现有的“部分注册”用户(如果存在)(电子邮件地址检查),并且其他数据库标志设置为 true。如果用户确实存在但不满足条件,则加载“忘记密码”页面,或者如果用户是新用户,则创建并保存。

关于如何实现上述目标的任何帮助或建议都将是绝妙的。

谢谢

维姬


这是我的设置:

用户类

class User < ActiveRecord::Base
  attr_accessor :password
  attr_accessible :email, :name, :password, :password_confirmation, :tandc

  email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

  validates :name, :presence => true,
                   :length => { :maximum => 50 }

  validates :email, :presence => true,
                    :format => {:with => email_regex },
                    :uniqueness => { :case_sensitive => false }

  validates :password,  :presence => true,
                        :confirmation => true,
                        :length => { :within => 6..40 }

  validates :tandc, :presence => true

  before_save :encrypt_password
  .
  .
  .
end

我有一个带有以下内容的 UsersController

  def new
    @user = User.new
    @title = "Sign Up"
  end

def create
 if @user.save
    sign_in @user
    redirect_to @user
 else
    @title = "Sign up"
    render 'new'
 end
end

def update
  if @user.update_attributes(params[:user])
    redirect_to @user
  else
   @title = "Edit"
   render 'edit'
  end
end
.
.
.

我有意见:用户 > new.html.erb

<%= form_for(@user, :html => { :class => "validateUser", :name =>"edit_user"}) do |f| %>
  .
  .
  .
  form stuff here
  .
  .
  .
<% end %>

和用户 > edit.html.erb

  <%= form_for(@user, :html => { :class => "validateUser", :name =>"edit_user"}) do |f| %>
  .
  .
  .
  form stuff here
  .
  .
  .
  <% end %>

我的用户路线如下

    users GET    /users(.:format)                users#index
          POST   /users(.:format)                users#create
 new_user GET    /users/new(.:format)            users#new
edit_user GET    /users/:id/edit(.:format)       users#edit
     user GET    /users/:id(.:format)            users#show
          PUT    /users/:id(.:format)            users#update
          DELETE /users/:id(.:format)            users#destroy
4

5 回答 5

2

一个快速但不优雅的解决方案可能是:

def create
 if user = User.find_by_email(params[:user][:email])
    if user.part_registered?
       user.update_attributes(params[:user])
       user.save
       sign_in user
       redirect_to user
    else
       @user = User.new(params[:user])
       if @user.save
       # just to trigger the error messages ...
       else
          @title = "Sign up"
          render 'new'
       end
    end
 else
    @user = User.new(params[:user])
    if @user.save
       sign_in @user
       redirect_to @user
    else
       @title = "Sign up"
       render 'new'
    end
 end
end

抱歉,我现在没有时间优化这些条件

于 2012-10-26T13:17:29.090 回答
2

首先,不要删除用户电子邮件上的唯一索引。如果您使用它作为模型的自然密钥,您需要它是唯一的,也就是使用它登录。

问问自己,邀请的意义何在?我有一个偷偷摸摸的怀疑创建一个新用户并不是你想要应用程序做的事情......如果用户从不接受邀请的邀请人怎么办?

相反,您可以使用用户的电子邮件和邀请者(如果这是邀请的目的)创建一个 Invitation 对象。然后您可以提供一个链接,将邀请作为参数传递:<%= link_to new_user_url, email: invitation_email_here %>并将该链接放入电子邮件中给受邀用户。

您可以传入值以users/new.html.erb使用电子邮件预先填写表单:

<%= f.email_field :email, value: params[:email] %>


另外,我会把你的表格放在一个部分,不要重复你自己。

form_for 的工作方式,如果@user 是新的,它将create向UsersController 的操作发出一个带有填充值的POST 请求。如果@user 是现有模型,它将使用现有值填充表单,向用户控制器的update操作发出 PUT 请求。

长话短说editnew视图可以有相同的形式。要简单地显示相同的表单,请在 users/veiws 目录中创建一个部分。

<!-- app/views/users/_form.html.erb -->
<%= form_for(@user, html: { class: "validateUser" }) do |f| %>
  ...
<% end %>

然后在要放置表单的视图中,放置<%= render 'users/form' %>

于 2012-10-26T13:18:05.273 回答
2

您可以使用类似的东西User.find_or_initialize_by_email(:email => params[:user_email])来获取 User 对象。

基本上,find_or_initialize将尝试从数据库中获取用户,如果它无法获取任何内容,它将创建一个新的,您可以稍后保存。

获得 User 对象后,您可以对其字段执行任何操作,然后将结果保存到数据库中(更新旧条目或创建新条目)。

(注意:如果你想检查用户之前是否存在,使用.persisted?返回的对象find_or_initialize,这将返回一个布尔值,告诉你它是否已经在数据库中。)

于 2012-10-26T13:20:15.737 回答
2

当有人在网站上注册时,您可以在他们登录之前发送一封帐户验证电子邮件。该电子邮件包含一个带有系统生成令牌的链接(例如“User.token”)。当他们单击链接时,您的 verification_controller 会通过他们的令牌检索用户并让他们设置密码。

# In class User < ActiveRecord::Base
# Give the user a unique, random token
user.token = SecureRandom.urlsafe_base64(20)

# In class VerificationsController < ApplicationController
# Retrieve the user with their token
@user = User.find_by_token(params[:token])

现在让我们考虑你的情况。当受邀用户在接受邀请之前尝试注册时,您仍然可以发送帐户验证电子邮件。现在他们有两封电子邮件:1)来自邀请和 2)来自他们的注册。没关系...他们只需单击链接并设置密码。

您可能希望使令牌过期,因为它提供了访问帐户的方法。一个流行的身份验证框架 AuthLogic有一个很有帮助的密码重置教程。它展示了一种类似的技术,并可能为您的手工构建解决方案提供一些想法。

于 2012-10-26T13:22:09.127 回答
1

你可以试试 users_controller.rb

def edit
  @user = User.find(params[:id])
end

def update
  @user = User.find(params[:id])

  respond_to do |format|
    if @user.update_attributes(params[:user])
      format.html { redirect_to @collection, notice: 'User was successfully updated.'}
      format.json { head :no_content }
    else
      format.html { render action: "edit" }
      format.json { render json: @user.errors, status: :unprocessable_entity }
    end
  end
end

添加链接到您的视图

<%= link_to content_tag(:span, "Edit"), edit_user_path(@user), :class => 'edit' %> 

在 new.html.erb 中删除表单并添加

<%= render 'form' %>

(这将呈现您将添加表单代码的部分)

创建 _form.html.erb 并将表单代码添加到此

然后创建您的 edit.html.erb 视图并添加代码

<%= render 'form' %>
于 2012-10-26T13:13:24.387 回答