我正在开发一个小型Ruby程序,为Neo4J数据库生成随机数据,包括人员、地址、电话号码等。
我完全是Ruby的初学者,所以我想在这里张贴我的进展,以得到审查。我刚刚完成了“人员”生成功能。
=begin
EntityFaker.rb
=end
require_relative "EntityFactory"
class Main
public
def self.generate_entities
puts "Generating entities..."
EntityFactory.test_function
end
generate_entities
end=begin
Entity-Factory
=end
require 'faker'
require 'pp'
require_relative 'Entities/Person'
class EntityFactory
@@person_array = []
public
def self.test_function()
generate_people(15)
end
private
def self.generate_people(number)
number.times do |n|
sex = Faker::Gender.binary_type
age = rand(18...65)
person = Person.new(
rand_bool ? Faker::Name.prefix : nil,
(sex == 'Male') ? Faker::Name.unique.male_first_name : Faker::Name.unique.female_first_name,
rand_bool ? Faker::Name.middle_name : nil,
Faker::Name.unique.last_name,
rand_bool ? Faker::Name.last_name : nil,
rand_bool ? Faker::Name.suffix : nil,
Time.now.to_i - age * 31556900, # dob in seconds since epoch
Person.random_height(sex),
Person.random_weight,
sex,
rand_bool ? sex : Faker::Gender.type,
Person.random_blood_type,
Faker::Color.color_name,
Faker::Color.color_name,
age,
Person.random_complexion,
Person.random_build,
Faker::Demographic.race
)
@@person_array.push(person)
end
pp @@person_array
end
private
def self.rand_bool
[true, false].sample
end
end=begin
Person.rb
=end
class Person
# http://chartsbin.com/view/38919
@@min_male_height = 166
@@max_male_height = 184
# http://chartsbin.com/view/38920
@@min_female_height = 147
@@max_female_height = 170
# For males and females combined, no data could be found seperating the two.
# https://en.wikipedia.org/wiki/Human_body_weight#Average_weight_around_the_world
@@min_weight = 49.591
@@max_weight = 87.398
# https://github.com/rubocop-hq/ruby-style-guide/issues/289
def initialize(
prefix,
given_name,
middle_name,
family_name,
maiden_name,
suffix,
dob,
height,
weight,
sex,
gender,
blood_type,
eye_colour,
hair_colour,
age,
complexion,
build,
race
)
@prefix = prefix
@given_name = given_name
@middle_name = middle_name
@family_name = family_name
@maiden_name = maiden_name
@suffix = suffix
create_full_name(prefix, given_name, middle_name, family_name, suffix)
@dob = dob
@height = height
@weight = weight
@sex = sex
@gender = gender
@blood_type = blood_type
@eye_colour = eye_colour
@hair_colour = hair_colour
@age = age
@complexion = complexion
@build = build
@race = race
end
private
def create_full_name(prefix, given_name, middle_name, family_name, suffix)
@legal_name = @full_name = [prefix, given_name, middle_name, family_name, suffix].compact.join(" ")
end
public
def self.random_weight
range(@@min_weight, @@max_weight)
end
public
def self.random_height(sex)
(sex == "Male") ? range(@@min_male_height, @@max_male_height) : range(@@min_female_height, @@max_female_height)
end
public
def self.random_complexion
# https://www.quora.com/What-are-all-the-different-types-of-skin-tones-or-complexions
["Type I", "Type II", "Type III", "Type IV", "Type V", "Type VI"].sample
end
public
def self.random_blood_type
# https://www.livescience.com/36559-common-blood-type-donation.html
["O-positive", "O-negative", "A-positive", "A-negative", "B-positive", "B-negative", "AB-positive", "AB-negative"].sample
end
public
def self.random_build
# https://www.cityofsacramento.org/-/media/Corporate/Files/Police/Resources/Suspect-Description-Form-SPD.pdf?la=en
["Slender", "Medium", "Heavy", "Fat", "Muscular"].sample
end
private
def self.range(min, max)
(rand * (max - min) + min).round(1)
end
end发布于 2018-07-20 02:56:07
我将主要根据ruby样式和最佳实践来查看您的代码,而不是具体的改进,因为您似乎不熟悉ruby通常的编写方式,并试图将其他语言(特别是它看起来像Java)的想法嵌入ruby语法。这并不是一件坏事,它只是表明你(和我们其他人)仍然在学习。
让我们从语法和更简单的代码样式更改开始,然后我们将深入讨论一些结构更改。
首先,让我们看看您的EntityFaker.rb文件:
我注意到的第一件事是Main类,它似乎是从Java带来的。我们不需要一个主类,我们可以把它放在最外面的范围里,也不需要把它包装在一个方法中。此外,在ruby中,我们通常避免使用=begin和=end的块注释,甚至对于多行注释也更喜欢#。因此,我们的EntityFaker.rb文件最终看起来如下所示:
# EntityFaker.rb
require_relative "EntityFactory"
puts "Generating entities..."
EntityFactory.test_function现在,让我们继续讨论其他两个文件中的一些结构更改。首先,您滥用了类与实例方法的概念,滥用了ruby中的公共/私有方法的概念。类的目的是使它能够被实例化。通过使用def self.name语法声明类方法,可以有效地使其成为保存方法的命名空间,而不是类。此外,当您声明类方法(def self.name)时,它们都是公共的,因此使用公共或私有关键字没有任何效果。这些关键字仅适用于实例方法(def name)。
您还将类用作某种工厂。这不是一堂课应该做的。类应该是生成类实例的模板。您可以构建一个生成类的类,但这不是您在这里要做的。似乎您希望创建一个类并将该类的实例追加到数组中。
您可以使用工厂为类的属性生成随机值,但我认为允许用户随意传递值会更优雅,但如果没有传递值,则可以随机选择。这将让我们将两个文件合并成一个很好的、整洁的类,如下所示:
class Person
# I've changed all these class variables because 1) class variables
# are considered bad practice (they have some weird behaviors) and 2)
# because these numbers are... well... constants.
# http://chartsbin.com/view/38919
MIN_MALE_HEIGHT = 166
MAX_MALE_HEIGHT = 184
# http://chartsbin.com/view/38920
MIN_FEMALE_HEIGHT = 147
MAX_FEMALE_HEIGHT = 170
# For males and females combined, no data could be found seperating the two.
# https://en.wikipedia.org/wiki/Human_body_weight#Average_weight_around_the_world
MIN_WEIGHT = 49.591
MAX_WEIGHT = 87.398
# The general gist of what I've done here is I've take the arguments as
# a hash instead of as a long list, which could become unclear. Taking
# arguments as a hash lets you create a person like so:
# Person.new({sex: "Male", age: 64}) which is the same thing as:
# Person.new(sex: "Male", age: 64) which is the same thing as:
# Person.new sex: "Male", age: 64 which is much clearer and neater.
# Also, I've changed it so that any options not passed in the opts hash
# will be randomly generated.
#
# You may be wondering about my usage of "||" (the OR operator). What
# I'm doing is checking if opts[:whatever] exists. If it does not exist
# it will return nil, which evaluates to false, and so will move on to
# to the other side of the operator which will do the random generation.
# This is a common idiom in ruby.
def initialize(**opts)
# Note that I've moved @sex to the top, because it's used in @given_name
# I've also moved @age, because it's used in a couple other places
@sex = opts[:sex] || Faker::Gender.binary_type
@age = opts[:age] || rand(18...65)
# I've taken the default values of @sex and @age from EntityFactory
@prefix = opts[:prefix] || rand_bool ? Faker::Name.prefix : nil
@given_name = opts[:given_name] || (@sex == 'Male') ? Faker::Name.unique.male_first_name : Faker::Name.unique.female_first_name
@middle_name = opts[:middle_name] || rand_bool ? Faker::Name.middle_name : nil
@family_name = opts[:family_name] || Faker::Name.unique.last_name
@maiden_name = opts[:maiden_name] || Faker::Name.unique.last_name
@suffix = opts[:suffix] || rand_bool ? Faker::Name.suffix : nil
create_full_name(prefix, given_name, middle_name, family_name, suffix)
@dob = opts[:dob] || Time.now.to_i - age * 31556900 # dob in seconds since epoch
@height = opts[:height] || random_height(sex)
@weight = opts[:weight] || random_weight
@gender = opts[:gender] || rand_bool ? @sex : Faker::Gender.type
@blood_type = opts[:blood_type] || random_blood_type
@eye_colour = opts[:eye_colour] || Faker::Color.color_name
@hair_colour = opts[:hair_colour] || Faker::Color.color_name
@complexion = opts[:complexion] || random_complexion
@build = opts[:build] || random_build
@race = opts[:race] || Faker::Demographic.race
end
private # Note that this private keyword applies to all instance methods below it
def rand_bool
[true, false].sample
end
def create_full_name(prefix, given_name, middle_name, family_name, suffix)
@legal_name = @full_name = [prefix, given_name, middle_name, family_name, suffix].compact.join(" ")
end
def random_weight
range(MIN_WEIGHT, MAX_WEIGHT)
end
# This could use some restructuring, which I'll go into later
def random_height(sex)
(sex == "Male") ? range(MIN_MALE_HEIGHT, MAX_MALE_HEIGHT) : range(MIN_FEMALE_HEIGHT, MAX_FEMALE_HEIGHT)
end
def random_complexion
# https://www.quora.com/What-are-all-the-different-types-of-skin-tones-or-complexions
["Type I", "Type II", "Type III", "Type IV", "Type V", "Type VI"].sample
end
def random_blood_type
# https://www.livescience.com/36559-common-blood-type-donation.html
["O-positive", "O-negative", "A-positive", "A-negative", "B-positive", "B-negative", "AB-positive", "AB-negative"].sample
end
def random_build
# https://www.cityofsacramento.org/-/media/Corporate/Files/Police/Resources/Suspect-Description-Form-SPD.pdf?la=en
["Slender", "Medium", "Heavy", "Fat", "Muscular"].sample
end
def range(min, max)
(rand * (max - min) + min).round(1)
end
end最后,要像您设置的那样生成15个人,运行以下命令:
people = (0..15).map do
Person.new
end这将使用rubys范围从0到15创建一个数字数组,然后迭代数组并将每个数字更改为一个新的人。
我可能会回到这个答案,并编辑一些更多的想法,但现在我必须要跑。享受吧!
https://codereview.stackexchange.com/questions/199641
复制相似问题