Rails创建或更新用户

时间:2012-10-26 12:38:06

标签: ruby-on-rails rails-activerecord rails-routing

我对Rails非常陌生并且正在努力奋斗。

我的用户遵循基本的注册,编辑过程。

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

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

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

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

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

由于

维基


这是我的设置:

用户类

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
.
.
.

我有意见:  用户&gt; new.html.erb

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

和用户&gt; 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

5 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:2)

首先,不会删除用户电子邮件中的唯一索引。如果您将它用作模型的自然键,即使用它登录,则需要它是唯一的。

问问自己,邀请的重点是什么?我有一个潜在的怀疑,创建一个新用户并不是你想要的应用程序做什么...如果用户从未接受邀请函上的邀请者怎么办?

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

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

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


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

form_for的工作方式,如果@user是new,它将发出一个POST请求,其中填充了UsersController的create操作的值。如果@user是现有模型,它将使用现有值填充表单,向UsersController的update操作发出PUT请求。

长话短说editnew次观看次数相同。要简单地显示相同的表单,请在users / veiws目录中进行部分显示。

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

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

答案 2 :(得分:2)

您可以使用User.find_or_initialize_by_email(:email => params[:user_email])行的内容来获取User对象。

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

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

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

答案 3 :(得分: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有一个password resets tutorial,它很有帮助。它显示了一种类似的技术,可能会为您的手工构建解决方案提供一些想法。

答案 4 :(得分: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' %>