【问题标题】:rails 3.2 model convert to rails 4rails 3.2 模型转换为 rails 4
【发布时间】:2023-03-05 10:27:02
【问题描述】:

我尝试将我的 rails-3.2-model 更改为 rails 4,但我不明白。
也许你可以帮我改一下。
3.2:

class User < ActiveRecord::Base
  attr_accessible :email, :username, :password, :password_confirmation
  attr_accessor :password
  before_save :encrypt_password

  validates_confirmation_of :password
  validates_presence_of :password, :on => :create
  validates_presence_of :email, :on => :create
  validates_presence_of :username, :on => :create
  validates_uniqueness_of :email
  validates_uniqueness_of :username

  def self.authenticate(email, password)
    user = find_by_email(email)
    if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
      user
    else
      nil
    end
  end

  def encrypt_password
    if password.present?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
    end
  end
end

4.0.4:

class User < ActiveRecord::Base

  validates :name, presence: true, uniqueness: {case_sensitive: true}, length: {minimum: 3, too_short: "must have at least %{count} characters"}
  validates :email, presence: true, uniqueness: {case_sensitive: true}
  validates :password_hash

end

我试图摆脱attr_accessibleattr_accessor,但我不知道如何。
attr_accessor :passwordattr_accessible [...] :password_confirmation没有存储在数据库中,所以我该如何使用它我的观点?

编辑:
查看:

<p>Sign Up</p>
    <%= form_for @user, :as => :user, :url => auth_sign_up_path, :html => {:class => 'navbar-form', :role => 'login'} do |user_form_builder| %>
        <p>
          <%= user_form_builder.label 'name:' %><br/>
          <%= user_form_builder.text_field :name %>
          <%= show_field_error(@user, :name) %>
        </p>
        <p>
          <%= user_form_builder.label 'email:' %><br/>
          <%= user_form_builder.text_field :email %>
          <%= show_field_error(@user, :email) %>
        </p>
        <p>
          <%= user_form_builder.label 'password:' %><br/>
          <%= user_form_builder.password_field :password %>
          <%= show_field_error(@user, :password) %>
        </p>
        <p>
          <%= user_form_builder.label 'password confirmation:' %><br/>
          <%= user_form_builder.password_field :password_confirmation %>
          <%= show_field_error(@user, :password_confirmation) %>
        </p>
        <p>
          <%= user_form_builder.submit 'Sign Up' %>
          <%= user_form_builder.submit 'Clear Form', :type => 'reset' %>
        </p>
    <% end %>

控制器:

def sign_up
    @user = User.new
  end

  def register
    @user = User.new(user_params)

    if @user.valid?
      @user.save
      session[:user_id] = @user.id
      flash[:notice] = 'Welcome.'
      redirect_to :root
    else
      render :action => "sign_up"
    end
  end

private
  def user_params
    params.require(:user).permit(:email, :name, :password, :password_confirmation)
  end

型号:

require 'bcrypt'
class User < ActiveRecord::Base

  attr_accessor :name, :email, :password, :password_confirmation
  before_save :encrypt_password
  after_save :clear_password

  validates :name, presence: true, uniqueness: {case_sensitive: true}, length: {minimum: 3, too_short: "must have at least %{count} characters"}
  validates :email, presence: true, uniqueness: {case_sensitive: true}
  validates :password, presence: true, length: {minimum: 8, too_short: "must have at least %{count} characters"}, :confirmation => true #password_confirmation attr

  def initialize(attributes = {})
    super # must allow the active record to initialize!
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end

  def self.authenticate_by_email(email, password)
    user = find_by_email(email)
    if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
      user
    else
      nil
    end
  end

  def self.authenticate_by_name(name, password)
    user = find_by_username(name)
    if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
      user
    else
      nil
    end
  end

  def encrypt_password
    if password.present?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
    end
  end

  def clear_password
    self.password = nil
  end

end

迁移:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.string :password_hash
      t.string :password_salt
      t.string :cal_owner, :array => true, :default => '{}'
      t.string :cal_joined, :array => true, :default => '{}'

      t.timestamps
    end
  end
end

路线:

Calendar::Application.routes.draw do

  # You can have the root of your site routed with "root"
  root 'welcome#index'

  get "auth/sign_up" => "auth#sign_up"
  get "auth/sign_in" => "auth#sign_in"
  get "auth/sign_out" => "auth#sign_out"
  get "auth/settings"
  get "auth/pwd_reset"
  get "welcome/index"

  post "auth/sign_in" => "auth#login"
  post "auth/sign_up" => "auth#register"
end

我用了一个教程,但我不知道作者为什么要添加这个:

def initialize(attributes = {})
        super # must allow the active record to initialize!
        attributes.each do |name, value|
          send("#{name}=", value)
        end
      end

作者写道:

对于每个键值对(哈希),我们将值分配给属性 调用“发送”函数(Ruby 中的所有方法调用实际上都是 消息。)

重要:

我们实际上不需要对 User 类执行此操作,因为 Rails 提供的构造函数将允许我们从 只要我们分配的字段是一个哈希 指定为“attr_accessible”,他们有。然而,有 想要初始化多个字段的情况(例如 ID 在 多对多表)不打算被视图访问 而是用“attr_accessor”指定。以上 功能是提供安全质量分配能力的简单方法 内部构造函数。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-4 model


    【解决方案1】:

    据我现在了解,您的用户表除了 ID 之外实际上还有 4 列,创建于等:

    • 姓名
    • 电子邮件
    • 密码哈希
    • password_salt

    在您的视图中,您有字段:

    • 姓名
    • 电子邮件
    • 密码
    • 密码确认

    您的控制器看起来正确。 user_params 方法将视图中的 4 个字段列入白名单,并让它们传递给 User 模型以创建新用户。

    在您的模型中,您需要进行 2 处更改。

    首先,您应该从attr_accessor 行中删除nameemail

    attr_accessor :password, :password_confirmation
    

    您只需要passwordpassword_confirmation。这样做的原因是因为 name 和 email 是数据库中的列,Rails 会自动为您提供这些属性的 getter 和 setter 方法。 attr_accessor 让您不必为 passwordpassword_confirmation 显式编写 getter 和 setter 方法,并让它们在使用来自视图的值创建新用户时自动填充。

    其次,您应该删除 initialize 方法。 User 继承自 ActiveRecord::Base 并且无需构造函数就能够非常愉快地构建新的用户记录。

    本教程的作者包含了进行批量赋值的构造函数。然而,在 Rails 4 中,这已更改为使用强参数,因此现在控制器负责说明哪些参数可以传递给模型。您可以在控制器的 user_params 方法中正确执行此操作。

    我希望这会有所帮助。

    【讨论】:

    • 我认为你的解释已经足够好了。谢谢你。如果我得到它的工作,我会这样做并将其标记为已解决。
    • 我还要解决一些问题。 ATM 我无法将其标记为已解决。
    • 它不起作用,因为我的数据库中只有“”而不是用户名等。任何的想法 ?我想我应该问一个新问题。?!
    • 对不起,我不明白。您能否用您的用户表中的确切内容编辑您的问题。我对你试图在你的模型中改变什么感到有点困惑——从 Rails 3.2 到 4.0,只需要用控制器的强参数替换 attr_accessible。您之前拥有的所有attr_accessor 逻辑都可以保留。
    • 感谢您更新问题 - 我已经更新了我的答案。希望对你有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 2013-03-17
    相关资源
    最近更新 更多