我正在开发一个API。为了让开发者有更好的体验,我想要向用户报告任何易于发现的params
问题。我的代码验证字符串、整数、布尔值、ISO8601日期和特定于域的值列表。我正在寻找一种方法来验证字符串是否是有效的UUID。我正在研究可能的选项。
我正在开发一个API。为了让开发者有更好的体验,我想要向用户报告任何易于发现的params
问题。我的代码验证字符串、整数、布尔值、ISO8601日期和特定于域的值列表。我正在寻找一种方法来验证字符串是否是有效的UUID。我正在研究可能的选项。
基于广泛的建议使用正则表达式:
def validate_uuid_format(uuid)
uuid_regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
return true if uuid_regex.match?(uuid.to_s.downcase)
log_and_raise_error("Given argument is not a valid UUID: '#{format_argument_output(uuid)}'")
end
请注意,这仅检查字符串是否符合 8-4-4-4-12
格式,并忽略任何版本检查。尽管我的回答会稍微限制问题的普适性,但我希望它仍然足够有趣。这个限制是假设您基于要检查的参数集实例化一个新对象,开始验证,然后返回错误对象,除非为nil。
# params[:lot] = { material_id: [SOME STRING], maybe: more_attributes }
lot = Lot.new params[:lot]
lot.valid?
# models/lot.rb
# material_id is of type string, as per db/schema.rb
validates :material_id,
uuid: true
ArgumentError (Unknown validator: 'UuidValidator')
# lib/uuid_validator.rb
class UuidValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless value =~ /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i
msg = options[:message] || "is not a valid UUID"
record.errors.add(attribute, msg)
end
end
end
lot = Lot.new({material_id: 1})
lot.material_id
=> "1" # note the auto type cast based on schema definition
lot.valid?
=> false
lot.errors.messages
=> {:material_id=>["is not a valid UUID"]}
# now, assign a valid uuid to material_id
lot.material_id = SecureRandom.uuid
=> "8c0f2f01-8f8e-4e83-a2a0-f5dd2e63fc33"
lot.valid?
=> true
重要提示:
一旦您将属性的数据类型更改为uuid,
# db/schema.rb
create_table "lots", id: false, force: :cascade do |t|
#t.string "material_id"
t.uuid "material_id"
end
lot = Lot.new
# trying to assign an integer...
lot.material_id({material_id: 1})
# results in gracious failure
=> nil
# the same is true for 'nearly valid' UUID strings, note the four last chars
lot.material_id = "44ab2cc4-f9e5-45c9-a08d-de6a98c0xxxx"
=> nil
lot.valid?
=> false
lot.errors.messages
=> {:material_id=>["is not a valid UUID"]}
my_model_instance.method(:valid?).source_location
来询问实例以获取该方法的定义。然后从源代码中导航并从那里跟进。 - Andreas Gebhardcreate!
、save!
和update!
方法;UuidValidator方法不再可行,不会导致.valid?
返回false,也不会更新errors
。 - undefinedgem 'rspec-uuid'
it { expect(user_uuid).to be_a_uuid }
或者,您可以检查特定的UUID版本:
it { expect(user_uuid).to be_a_uuid(version: 4) }
如果你需要在将参数传递给Postgres之前验证它,只需检查字符串是否遵循8-4-4-4-12十六进制格式即可。
参数的简短检查:
uuid.to_s.match /\h{8}-(\h{4}-){3}\h{12}/
人话翻译:
UUID.validate(my_string)
类方法。UUID.validate(my_string)
。 - AlexandreUUID
不属于 Ruby。你在这里链接一个 gem,在 Ruby 的基础上提供了这个类。 - Robin使用正则表达式匹配器验证它,这取决于您要验证的UUID版本。我相信有很多资源可以提供每个UUID版本的正则表达式模式。