Ruby 中的方法定义和命名约定
Method definition and naming conventions in Ruby
我主要来自 C# 背景,目前我在 Rails 上学习 Ruby。通读 railstutorial.org,我看到很多这样的代码(这个是代码清单 10.49):
class PasswordResetsController < ApplicationController
before_action :get_user, only: [:edit, :update]
before_action :valid_user, only: [:edit, :update]
.
.
.
def edit
end
private
def get_user
@user = User.find_by(email: params[:email])
end
# Confirms a valid user.
def valid_user
unless (@user && @user.activated? &&
@user.authenticated?(:reset, params[:id]))
redirect_to root_url
end
end
end
现在,我学到的是让方法尽可能细化,方法名称尽可能提供信息。这里的方法 valid_user
检查用户是否有效,如果无效则重定向到 root_url
。
在这种情况下,我要做的是将方法重命名为 redirect_to_root_if_not_valid
,或者不使用单独的方法,如果需要检查,只需使用 user.valid?
之类的方法,并且然后在需要的地方重定向。
对我来说,方法名称和方法信息具有误导性,它不仅确认有效用户,如果用户无效,它还会重定向到某个地方。
这对我来说是不是很奇怪,因为我来自 C# 背景,还是这只是我不习惯的另一种做事方式?
我认为这些方法的命名很糟糕。首先,我会将 activated?
的检查拉入 User
class 的保护子句中,因为非活动用户可以 never 进行身份验证在我看来:
class User < ActiveRevord::Base
# ...
def authenticated?(...)
return false unless activated?
# ...
end
end
然后,我将方法重命名为 assign_user
和 ensure_user_authenticated
,将身份验证检查提取到一个单独的方法中,并使用 @obj.try(:method, args)
而不是 @obj && @obj.method(args)
控制器:
class PasswordResetsController < ApplicationController
before_action :assign_user, only: [:edit, :update]
before_action :ensure_user_authenticated, only: [:edit, :update]
# ...
private
def assign_user
@user = User.find_by(email: params[:email])
end
def ensure_user_authenticated
redirect_to root_url unless user_authenticated?
end
def user_authenticated?
@user.try(:authenticated?, :reset, params[:id])
end
end
您正在进入 "what's the best way to do x" 的恐怖谷,ruby 社区的人们喜欢这样。不管怎样,我将再提供一个关于如何重构代码的意见:
创建一个 authenticated?
和过滤方法 [并将它们放在 ApplicationController
中,您可能会重用它 |与否,这取决于逻辑是否可共享]。此外,我喜欢定义一个 user
方法和编写器,而不是使用过滤器来实现 [几乎] 相同的行为。
class ApplicationControlller < ActionController::Base
before_action :restrict_access_to_authenticated_users
private
def restrict_access_to_authenticated_users
redirect_to root_path unless authenticated?
end
def authenticated?(u = user)
u && u.activated? && u.authenticated?(:reset, params[:id])
end
attr_writer :user # I use this so you can overwrite the user without using the code beneath
def user
@user ||= User.find_by_email(params[:email])
end
end
我主要来自 C# 背景,目前我在 Rails 上学习 Ruby。通读 railstutorial.org,我看到很多这样的代码(这个是代码清单 10.49):
class PasswordResetsController < ApplicationController
before_action :get_user, only: [:edit, :update]
before_action :valid_user, only: [:edit, :update]
.
.
.
def edit
end
private
def get_user
@user = User.find_by(email: params[:email])
end
# Confirms a valid user.
def valid_user
unless (@user && @user.activated? &&
@user.authenticated?(:reset, params[:id]))
redirect_to root_url
end
end
end
现在,我学到的是让方法尽可能细化,方法名称尽可能提供信息。这里的方法 valid_user
检查用户是否有效,如果无效则重定向到 root_url
。
在这种情况下,我要做的是将方法重命名为 redirect_to_root_if_not_valid
,或者不使用单独的方法,如果需要检查,只需使用 user.valid?
之类的方法,并且然后在需要的地方重定向。
对我来说,方法名称和方法信息具有误导性,它不仅确认有效用户,如果用户无效,它还会重定向到某个地方。
这对我来说是不是很奇怪,因为我来自 C# 背景,还是这只是我不习惯的另一种做事方式?
我认为这些方法的命名很糟糕。首先,我会将 activated?
的检查拉入 User
class 的保护子句中,因为非活动用户可以 never 进行身份验证在我看来:
class User < ActiveRevord::Base
# ...
def authenticated?(...)
return false unless activated?
# ...
end
end
然后,我将方法重命名为 assign_user
和 ensure_user_authenticated
,将身份验证检查提取到一个单独的方法中,并使用 @obj.try(:method, args)
而不是 @obj && @obj.method(args)
控制器:
class PasswordResetsController < ApplicationController
before_action :assign_user, only: [:edit, :update]
before_action :ensure_user_authenticated, only: [:edit, :update]
# ...
private
def assign_user
@user = User.find_by(email: params[:email])
end
def ensure_user_authenticated
redirect_to root_url unless user_authenticated?
end
def user_authenticated?
@user.try(:authenticated?, :reset, params[:id])
end
end
您正在进入 "what's the best way to do x" 的恐怖谷,ruby 社区的人们喜欢这样。不管怎样,我将再提供一个关于如何重构代码的意见:
创建一个 authenticated?
和过滤方法 [并将它们放在 ApplicationController
中,您可能会重用它 |与否,这取决于逻辑是否可共享]。此外,我喜欢定义一个 user
方法和编写器,而不是使用过滤器来实现 [几乎] 相同的行为。
class ApplicationControlller < ActionController::Base
before_action :restrict_access_to_authenticated_users
private
def restrict_access_to_authenticated_users
redirect_to root_path unless authenticated?
end
def authenticated?(u = user)
u && u.activated? && u.authenticated?(:reset, params[:id])
end
attr_writer :user # I use this so you can overwrite the user without using the code beneath
def user
@user ||= User.find_by_email(params[:email])
end
end