如何优化ruby方法?
How to optimize ruby method?
我有以下 ruby 方法,它看起来非常丑陋,我想重构它并降低它的感知复杂性。
def validate_hash_params(**kwargs)
kwargs.each do |k, v|
raise Sith::ProcessingError, "#{k} should be of type String" unless v&.is_a? String
raise Sith::ProcessingError, "id length should be less than equal to 25" if kwargs[:id].length > 25
raise Sith::ProcessingError, "info length should be less than equal to 100" if kwargs[:info].length > 100
raise Sith::ProcessingError, "first_name length should be less than equal to 60" if kwargs[:first_name].length > 60
raise Sith::ProcessingError, "email length should be less than equal to 50" if kwargs[:email].length > 50
raise Sith::ProcessingError, "Invalid Email" unless Sith::EMAIL_REGEX.match(kwargs[:email])
raise Sith::ProcessingError, "amount should contain digits with upto 2 decimal places" unless Sith::AMOUNT_REGEX.match(kwargs[:amount])
[kwargs[:key1], kwargs[:key2], kwargs[:key3], kwargs[:key4], kwargs[:key5]].each do |key|
raise SithError, "key length should be less than equal to 255" if key.length > 255
end
end
end
如有任何帮助,我们将不胜感激。谢谢!
您可以按如下方式重新组织您的计算。如有必要,当然可以重新排序各种验证。
def validate(**kwargs)
validate_values_are_strings(**kwargs)
validate_max_lengths(**kwargs)
validate_amount(kwargs[:amount])
validate_max_key_lengths(**kwargs)
validate_email_pattern(kwargs[:email])
end
def validate_values_are_strings(**kwargs)
kwargs.each do |k,v|
raise Sith::ProcessingError,
"value of #{k} should be of type String" unless v.is_a? String
end
end
def validate_max_lengths(**kwargs)
k,v = { id: 24, info: 100, first_name: 60, email: 50 }.find do |k,v|
kwargs[k].length > v
end
raise Sith::ProcessingError,
"#{k.to_s} length should be less than or equal to #{v}" unless k.nil?
end
def validate_amount(amount)
raise Sith::ProcessingError,
"amount should contain digits with upto 2 decimal places" unless
Sith::AMOUNT_REGEX.match?(amount)
end
def validate_max_key_lengths(**kwargs)
raise SithError, "key length should be less than equal to 255" if
[:key1, :key2, :key3].map { |k| kwargs[k].length }.max > 255
end
def validate_email_pattern(email)
raise Sith::ProcessingError, "Invalid Email" unless
Sith::EMAIL_REGEX.match?(email)
end
假设:
kwargs =
{ id: '23', info: '99', first_name: '59', email: 'hank@some_url.com',
amount: '2.63', key1: 'cow', key2: 'chicken', key3: 'goat' }
让我们检查其中一些方法的简化。
def validate_values_are_strings(**kwargs)
kwargs.each do |k,v|
raise "value of #{k} should be of type String" unless v.is_a? String
end
end
validate_values_are_strings(**kwargs)
#=> nil (no errors)
validate_values_are_strings(**(kwargs.merge(email: 7)))
#=> RuntimeError (value of email should be of type String)
def validate_max_key_lengths(**kwargs)
raise "key length should be less than equal to 255" if
[:key1, :key2, :key3].map { |k| kwargs[k].length }.max > 255
end
validate_max_key_lengths(**kwargs)
#=> nil (no errors)
validate_max_key_lengths(**(kwargs.merge(key2: 'a'*256)))
#=> RuntimeError (key length should be less than equal to 255)
def validate_amount(amount)
raise "amount should contain digits with upto 2 decimal places" unless
/\A\d+(?:\.\d{1,2})?\z/.match?(amount)
end
validate_amount(kwargs[:amount])
#=> nil (no errors)
validate_amount("2.634")
#=> RuntimeError (amount should contain digits with upto 2 decimal places)
def validate_hash_params(**kwargs)
validate_string(kwargs)
validate_length(kwargs, :id, 25)
validate_length(kwargs, :info, 100)
validate_length(kwargs, :first_name, 60)
validate_length(kwargs, :email, 50)
raise Sith::ProcessingError, 'Invalid Email' unless Sith::EMAIL_REGEX.match(kwargs[:email])
raise Sith::ProcessingError, 'amount should contain digits with upto 2 decimal places' unless Sith::AMOUNT_REGEX.match(kwargs[:amount])
validate_key_length(kwaargs)
end
def validate_length(kwargs, key, length)
raise Sith::ProcessingError, "id length should be less than equal to #{length}" if kwargs[key].length > length
end
def validate_string(kwargs)
not_a_string = kwargs.find { |_k, v| !v.is_a?(String) }
raise Sith::ProcessingError, "#{not_a_string.first} should be of type String" if not_a_string
end
def validate_key_length(kwargs)
raise SithError, 'key length should be less than equal to 255' if [:key1, :key2, :key3, :key4, :key5].any? { |k| kwargs[k].length > 255 }
end
如果这是 Rails 上的 Ruby,我建议使用 validations 而不是自定义检查和引发异常。这就需要制作一个小模型了
class Sith
include ActiveModel::Model
attr_accessor :id, :info, :first_name, :email, :amount, :keys
validates :id, length: { maximum: 25 }
validates :info, length: { maximum: 100 }
validates :first_name, length: { maximum: 60 }
validates :email, length: { maximum: 50 }, format: { with: URI::MailTo::EMAIL_REGEXP }
validate :validate_amount_decimal_places
validate :validate_keys
private def validate_amount_decimal_places
if amount != amount.round(2)
errors.add(:amount, "amount should contain digits with upto 2 decimal places")
end
end
private def validate_keys
errors.add(:keys, "there can be, at most, 5 keys") if keys.size > 5
if keys.any? { |key| key.length >= 255 }
errors.add(:keys, "keys must be shorter than 255 characters")
end
end
end
请注意,我将单独的 key1、key2、key3 参数组合到一个键数组中。
现在您可以制作Sith
并检查它是否有效。
sith = Sith.new(kwargs)
if !sith.valid?
...
end
如果您想使用例外,请使用 Strict Validations。
validates :id, length: { maximum: 25, strict: Sith::ProcessingError }
然而,很多这些“验证”似乎是不必要的,而且可能令人望而却步。为什么要限制某人电子邮件的长度?
我有以下 ruby 方法,它看起来非常丑陋,我想重构它并降低它的感知复杂性。
def validate_hash_params(**kwargs)
kwargs.each do |k, v|
raise Sith::ProcessingError, "#{k} should be of type String" unless v&.is_a? String
raise Sith::ProcessingError, "id length should be less than equal to 25" if kwargs[:id].length > 25
raise Sith::ProcessingError, "info length should be less than equal to 100" if kwargs[:info].length > 100
raise Sith::ProcessingError, "first_name length should be less than equal to 60" if kwargs[:first_name].length > 60
raise Sith::ProcessingError, "email length should be less than equal to 50" if kwargs[:email].length > 50
raise Sith::ProcessingError, "Invalid Email" unless Sith::EMAIL_REGEX.match(kwargs[:email])
raise Sith::ProcessingError, "amount should contain digits with upto 2 decimal places" unless Sith::AMOUNT_REGEX.match(kwargs[:amount])
[kwargs[:key1], kwargs[:key2], kwargs[:key3], kwargs[:key4], kwargs[:key5]].each do |key|
raise SithError, "key length should be less than equal to 255" if key.length > 255
end
end
end
如有任何帮助,我们将不胜感激。谢谢!
您可以按如下方式重新组织您的计算。如有必要,当然可以重新排序各种验证。
def validate(**kwargs)
validate_values_are_strings(**kwargs)
validate_max_lengths(**kwargs)
validate_amount(kwargs[:amount])
validate_max_key_lengths(**kwargs)
validate_email_pattern(kwargs[:email])
end
def validate_values_are_strings(**kwargs)
kwargs.each do |k,v|
raise Sith::ProcessingError,
"value of #{k} should be of type String" unless v.is_a? String
end
end
def validate_max_lengths(**kwargs)
k,v = { id: 24, info: 100, first_name: 60, email: 50 }.find do |k,v|
kwargs[k].length > v
end
raise Sith::ProcessingError,
"#{k.to_s} length should be less than or equal to #{v}" unless k.nil?
end
def validate_amount(amount)
raise Sith::ProcessingError,
"amount should contain digits with upto 2 decimal places" unless
Sith::AMOUNT_REGEX.match?(amount)
end
def validate_max_key_lengths(**kwargs)
raise SithError, "key length should be less than equal to 255" if
[:key1, :key2, :key3].map { |k| kwargs[k].length }.max > 255
end
def validate_email_pattern(email)
raise Sith::ProcessingError, "Invalid Email" unless
Sith::EMAIL_REGEX.match?(email)
end
假设:
kwargs =
{ id: '23', info: '99', first_name: '59', email: 'hank@some_url.com',
amount: '2.63', key1: 'cow', key2: 'chicken', key3: 'goat' }
让我们检查其中一些方法的简化。
def validate_values_are_strings(**kwargs)
kwargs.each do |k,v|
raise "value of #{k} should be of type String" unless v.is_a? String
end
end
validate_values_are_strings(**kwargs)
#=> nil (no errors)
validate_values_are_strings(**(kwargs.merge(email: 7)))
#=> RuntimeError (value of email should be of type String)
def validate_max_key_lengths(**kwargs)
raise "key length should be less than equal to 255" if
[:key1, :key2, :key3].map { |k| kwargs[k].length }.max > 255
end
validate_max_key_lengths(**kwargs)
#=> nil (no errors)
validate_max_key_lengths(**(kwargs.merge(key2: 'a'*256)))
#=> RuntimeError (key length should be less than equal to 255)
def validate_amount(amount)
raise "amount should contain digits with upto 2 decimal places" unless
/\A\d+(?:\.\d{1,2})?\z/.match?(amount)
end
validate_amount(kwargs[:amount])
#=> nil (no errors)
validate_amount("2.634")
#=> RuntimeError (amount should contain digits with upto 2 decimal places)
def validate_hash_params(**kwargs)
validate_string(kwargs)
validate_length(kwargs, :id, 25)
validate_length(kwargs, :info, 100)
validate_length(kwargs, :first_name, 60)
validate_length(kwargs, :email, 50)
raise Sith::ProcessingError, 'Invalid Email' unless Sith::EMAIL_REGEX.match(kwargs[:email])
raise Sith::ProcessingError, 'amount should contain digits with upto 2 decimal places' unless Sith::AMOUNT_REGEX.match(kwargs[:amount])
validate_key_length(kwaargs)
end
def validate_length(kwargs, key, length)
raise Sith::ProcessingError, "id length should be less than equal to #{length}" if kwargs[key].length > length
end
def validate_string(kwargs)
not_a_string = kwargs.find { |_k, v| !v.is_a?(String) }
raise Sith::ProcessingError, "#{not_a_string.first} should be of type String" if not_a_string
end
def validate_key_length(kwargs)
raise SithError, 'key length should be less than equal to 255' if [:key1, :key2, :key3, :key4, :key5].any? { |k| kwargs[k].length > 255 }
end
如果这是 Rails 上的 Ruby,我建议使用 validations 而不是自定义检查和引发异常。这就需要制作一个小模型了
class Sith
include ActiveModel::Model
attr_accessor :id, :info, :first_name, :email, :amount, :keys
validates :id, length: { maximum: 25 }
validates :info, length: { maximum: 100 }
validates :first_name, length: { maximum: 60 }
validates :email, length: { maximum: 50 }, format: { with: URI::MailTo::EMAIL_REGEXP }
validate :validate_amount_decimal_places
validate :validate_keys
private def validate_amount_decimal_places
if amount != amount.round(2)
errors.add(:amount, "amount should contain digits with upto 2 decimal places")
end
end
private def validate_keys
errors.add(:keys, "there can be, at most, 5 keys") if keys.size > 5
if keys.any? { |key| key.length >= 255 }
errors.add(:keys, "keys must be shorter than 255 characters")
end
end
end
请注意,我将单独的 key1、key2、key3 参数组合到一个键数组中。
现在您可以制作Sith
并检查它是否有效。
sith = Sith.new(kwargs)
if !sith.valid?
...
end
如果您想使用例外,请使用 Strict Validations。
validates :id, length: { maximum: 25, strict: Sith::ProcessingError }
然而,很多这些“验证”似乎是不必要的,而且可能令人望而却步。为什么要限制某人电子邮件的长度?