我在测试中收到错误,尽管代码正常运行。 Capybara为实例方法中的属性集抛出未定义的方法错误是否正常?我的代码如下:
应用/模型/ user.rb
class User < ActiveRecord::Base
attr_accessible :email, :first_name, :last_name, :password, :bio, :resume,
:website, :focus, :location, :aspirations, :password_reset_token, :profile_photo, :school, :profile_photo_file_name, :profile_photo_content_type, :profile_photo_file_size, :profile_photo_updated_at
attr_accessor :password_reset_token
attr_reader :password
validates :email, :first_name, :last_name, presence: true
validates :email, uniqueness: true
validates :password, length: { minimum: 6, allow_nil: true }
validates :password_digest, presence: { message: "Password can't be blank" }
after_initialize :ensure_session_token
default_scope order('created_at ASC')
has_attached_file :profile_photo, styles: {
medium: "250x250>", thumb: "50x50>"
}, convert_options: { :thumb => "-quality 75 -strip"
}
has_attached_file :resume
has_many(
:roles,
class_name: 'Role',
foreign_key: :user_id,
primary_key: :id,
inverse_of: :user,
dependent: :destroy
)
has_many(
:taggings,
as: :taggable,
dependent: :destroy
)
has_many(
:posts,
class_name: 'Post',
foreign_key: :user_id,
primary_key: :id,
inverse_of: :user,
dependent: :destroy
)
has_many(
:comments,
class_name: 'Comment',
foreign_key: :user_id,
primary_key: :id,
inverse_of: :user,
dependent: :destroy
)
has_many(
:honors,
class_name: 'Honor',
foreign_key: :user_id,
primary_key: :id,
inverse_of: :user,
dependent: :destroy
)
has_many(
:experiences,
class_name: 'Experience',
foreign_key: :user_id,
primary_key: :id,
inverse_of: :user,
dependent: :destroy
)
has_many :courses, through: :roles, source: :course
has_many :tags, through: :taggings, source: :tag
def self.generate_token
SecureRandom.urlsafe_base64(16)
end
def self.find_by_credentials(email, password)
user = User.find_by_email(email)
return nil if user.nil?
user.is_password?(password) ? user : nil
end
def password=(password)
@password = password
self.password_digest = BCrypt::Password.create(password)
end
def is_password?(password)
BCrypt::Password.new(self.password_digest).is_password?(password)
end
def reset_session_token!
self.session_token = self.class.generate_token
end
def full_name
"#{self.first_name} #{self.last_name}"
end
def set_password_reset_token
self.password_reset_token = self.class.generate_token
end
def send_password_reset
set_password_reset_token
self.save!
UserMailer.password_reset(self).deliver!
end
private
def ensure_session_token
self.session_token ||= self.class.generate_token
end
def find_role(course_id)
Role.select(:title)
.where(user_id: self.id, course_id: course_id).first.title.titleize
end
end
应用/控制器/ password_resets_controller.rb
class PasswordResetsController < ApplicationController
skip_before_filter :require_current_user!
def new
end
def create
user = User.find_by_email(params[:email])
user.send_password_reset if user
flash[:notice] = "Email sent with password reset instructions."
redirect_to signin_url
end
def edit
@user = User.find_by_password_reset_token(params[:id])
end
def update
@user = User.find_by_password_reset_token(params[:id])
if @user.update_attributes(params[:user])
flash[:notice] = "Password has been reset!"
redirect_to signin_url
else
render :edit
end
end
end
分贝/ schema.rb
create_table "users", :force => true do |t|
t.string "email", :null => false
t.string "password_digest", :null => false
t.string "first_name", :null => false
t.string "last_name", :null => false
t.string "session_token", :null => false
t.string "bio"
t.string "location"
t.string "focus"
t.string "aspirations"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "profile_photo_file_name"
t.string "profile_photo_content_type"
t.integer "profile_photo_file_size"
t.datetime "profile_photo_updated_at"
t.string "resume_file_name"
t.string "resume_content_type"
t.integer "resume_file_size"
t.datetime "resume_updated_at"
t.string "school"
t.string "password_reset_token"
end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true
add_index "users", ["session_token"], :name => "index_users_on_session_token", :unique => true
Capybara错误消息
PasswordResets
updates the user password when confirmation matches (FAILED - 1)
Failures:
1) PasswordResets updates the user password when confirmation matches
Failure/Error: user.set_password_reset_token
NoMethodError:
undefined method `password_reset_token=' for #<User:0x007fd237d31e20>
# ./app/models/user.rb:107:in `set_password_reset_token'
# ./spec/features/password_resets_spec.rb:25:in `block (2 levels) in <top (required)>'
Finished in 0.19426 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/features/password_resets_spec.rb:23 # PasswordResets updates the user password when confirmation matches
答案 0 :(得分:0)
如果您有一个不想保存到数据库中的值,则应使用attr_accessor
。在这种情况下,您不需要它,因为您想将:password_reset_token
保存到数据库中,并且rails已经提供了setter和getter方法。
修改强>
使用attr_accessor
更改getter和setter方法并定义实例变量。它确实不更改Active Record使用的属性。这意味着保存模型时,即使相关列存在,使用attr_accessor
设置的值也不会保存到数据库中。
您可以在打印属性时看到我的意思:
u = User.new
u.password_reset_token = "abc"
u.attributes #=> { ... "password_reset_token"=>nil ... }
在同一属性上同时使用attr_accessor
和attr_accessible
没有意义。您应该从模型中删除attr_accessor :password_reset_token
。
这可能无法完全解决问题 - 但它应该可以帮助您解决真正的问题所在。
我建议您为User#set_password_reset_token
编写单元测试,以确保在编写验收测试之前它的行为符合您的预期。