Ruby on rails 设计-Ruby-根据用户定义的标题从同一数据源创建多个CSV文件
我正在研究的要求,我们有大约100+键的散列数据。我们需要根据用户定义的头生成CSV文件,并进行一些转换,我们可能最终拥有100多个模板 主要变化将是 1) 更改列名,例如Fname–>First name 2) 数据转换,如全名–>名字+姓氏(添加2列) 3) 固定立柱的位置–Fname应位于35个位置等 请建议是否可以定义声明方式或任何可用的gem。你能告诉我我们在这里可以采用什么样的设计模式吗 一些示例场景 我有这样的输入,有许多列(100+) 一些客户需要CSV作为Ruby on rails 设计-Ruby-根据用户定义的标题从同一数据源创建多个CSV文件,ruby-on-rails,ruby,algorithm,design-patterns,architecture,Ruby On Rails,Ruby,Algorithm,Design Patterns,Architecture,我正在研究的要求,我们有大约100+键的散列数据。我们需要根据用户定义的头生成CSV文件,并进行一些转换,我们可能最终拥有100多个模板 主要变化将是 1) 更改列名,例如Fname–>First name 2) 数据转换,如全名–>名字+姓氏(添加2列) 3) 固定立柱的位置–Fname应位于35个位置等 请建议是否可以定义声明方式或任何可用的gem。你能告诉我我们在这里可以采用什么样的设计模式吗 一些示例场景 我有这样的输入,有许多列(100+) 一些客户需要CSV作为 Employee I
Employee ID, First Name, Last Name, Date of birth, Salary, Bonus
001,John,Dee,10/10/1983,100000,50000,...
002,Alex,Peck,11/01/1988,120000,70000,...
其他(仅标题更改)
另一个(合并列FName、LName->Fullname)
其他(合并薪资、奖金->薪资+奖金列)
其他(列顺序也改变,而不是Dob需要年龄)
就像许多输入相同的变体一样
感谢您的帮助您需要的是演示者设计模式 您的控制器将请求数据并将其存储在局部变量中,然后您必须为您的客户端加载一个presenter,并将数据变量传递给它。 作为响应,您将获得返回到客户端的最终CSV 假设您的客户机有uniq代码,因此
Client
模型实例有一个code
属性,它是一个字符串
因此,您的控制器将如下所示:
app/controllers/exports\u controller.rb
类导出控制器 data=MyService.fetchData#您需要的是presenter设计模式
您的控制器将请求数据并将其存储在局部变量中,然后您必须为您的客户端加载一个presenter,并将数据变量传递给它。
作为响应,您将获得返回到客户端的最终CSV
假设您的客户机有uniq代码,因此Client
模型实例有一个code
属性,它是一个字符串
因此,您的控制器将如下所示:
app/controllers/exports\u controller.rb
类导出控制器 data=MyService.fetchData#您可以通过构造一个转换散列来实现您的目标,该散列的键按顺序为所需CSV文件中的列的名称,其值为procs,当使用等于给定散列数组元素的参数调用时,返回要写入CSV文件中与键对应的列中的行中的元素
代码
require 'csv'
def construct_csv(fname, arr, transform)
CSV.open(fname, "wb") do |csv|
keys = transform.keys
csv << keys
arr.each { |h| csv << keys.map { |k| transform[k].call(h) } }
end
end
使用相同的键、相同的顺序和相同的值编写CSV文件
编写一个CSV文件,其中列重新排序1
使用密钥子集编写CSV文件,重命名并重新排序
删除键并添加值已计算的键后,编写CSV文件
一,。我不理解这样做的原因,但这是一个可能的要求。您可以通过构造一个转换哈希来实现您的目标,该哈希的键是所需CSV文件中的列的名称,按顺序排列,其值是procs,当使用等于给定哈希数组的元素的参数调用时,返回要写入CSV文件中与键对应的列中的行中的元素
代码
require 'csv'
def construct_csv(fname, arr, transform)
CSV.open(fname, "wb") do |csv|
keys = transform.keys
csv << keys
arr.each { |h| csv << keys.map { |k| transform[k].call(h) } }
end
end
使用相同的键、相同的顺序和相同的值编写CSV文件
编写一个CSV文件,其中列重新排序1
使用密钥子集编写CSV文件,重命名并重新排序
删除键并添加值已计算的键后,编写CSV文件
一,。我不明白这样做的原因,但这是一个可能的要求。选择一些列并重新排序似乎很简单。但是您如何计划用户定义转换呢?在我看来,如果不添加空格,您的示例(全名–>名字+姓氏)就没有意义。但是如果用户想要姓+名,他们可能需要在两者之间加一个逗号。有很多隐藏的复杂性。你能详细说明这一部分吗?如果你能举出一些例子,回答起来就容易多了。从任意散列创建CSV并不困难。看看您是否对rails创建csv文档有很好的了解,这是可能的,并且它是完全可定制的。没有值得推荐的gem。@spickermann使用示例场景进行了更新,感谢您的帮助选择一些列并对它们重新排序似乎很简单。但是您如何计划用户定义转换呢?在我看来,如果不添加空格,您的示例(全名–>名字+姓氏)就没有意义。但是如果用户想要姓+名,他们可能需要在两者之间加一个逗号。有很多隐藏的复杂性。你能详细说明这一部分吗?如果你能举出一些例子,回答起来就容易多了。从任意散列创建CSV并不困难。看看您是否对rails创建csv文档有很好的了解,这是可能的,并且它是完全可定制的。没有可推荐的gem。@spickermann使用示例场景进行了更新,谢谢您的帮助
ID, Fullname, Dob, Salary, Bounus
001,John Dee,10/10/1983,100000,50000,...
002,Alex Peck,11/01/1988,120000,70000,...
ID, FName, LName, Dob, Salary
001,John,Dee,10/10/1983,150000,...
002,Alex,Peck,11/01/1988,190000,...
FName, LName, ID, age, Salary
John,Dee,001,36,150000,...
Alex,Peck,003,32,190000,...
require 'csv'
def construct_csv(fname, arr, transform)
CSV.open(fname, "wb") do |csv|
keys = transform.keys
csv << keys
arr.each { |h| csv << keys.map { |k| transform[k].call(h) } }
end
end
arr = [{:employee_id=>"001", :first_name=>"John", :last_name=>"Dee",
:date_of_birth=>"10/10/1983", :salary=>"100000", :bonus=>"50000" },
{:employee_id=>"002", :first_name=>"Alex", :last_name=>"Peck",
:date_of_birth=>"11/01/1988", :salary=>"120000", :bonus=>"70000" }]
FName = 'temp.csv'
keys = arr.first.keys
#=> [:employee_id, :first_name, :last_name, :date_of_birth, :salary, :bonus]
transform = keys.each_with_object({}) { |k,g| g[k] = ->(h) { h[k] } }
#=> {:employee_id=>#<Proc:0x00005bd270a0e710@(irb):451 (lambda)>,
# :first_name=>#<Proc:0x00005bd270a13260@(irb):451 (lambda)>,
# ...
# :bonus=>#<Proc:0x00005bd270a19cc8@(irb):451 (lambda)>}
construct_csv(FName, arr, transform)
puts File.read(FName)
employee_id,first_name,last_name,date_of_birth,salary,bonus
001,John,Dee,10/10/1983,100000,50000
002,Alex,Peck,11/01/1988,120000,70000
col_order = [:last_name, :first_name, :employee_id, :salary, :bonus,
:date_of_birth]
keys = arr.first.keys
order_map = col_order.each_with_object({}) { |k,h| h[k] = keys.index(k) }
#=> {:last_name=>2, :first_name=>1, :employee_id=>0, :salary=>4,
# :bonus=>5, :date_of_birth=>3}
transform = col_order.each_with_object({}) { |k,g|
g[k] = ->(h) { h[keys[order_map[k]]] } }
#=> {:last_name=>#<Proc:0x00005bd270f8e5a0@(irb):511 (lambda)>,
# :first_name=>#<Proc:0x00005bd270f8e550@(irb):511 (lambda)>,
# ...
# :date_of_birth=>#<Proc:0x00005bd270f8e3c0@(irb):511 (lambda)>}
construct_csv(FName, arr, transform)
puts File.read(FName)
last_name,first_name,employee_id,salary,bonus,date_of_birth
Dee,John,001,100000,50000,10/10/1983
Peck,Alex,002,120000,70000,11/01/1988
keymap = { :FirstName=>:first_name, :LastName=>:last_name, :ID=>:employee_id,
:Salary=>:salary, :Bonus=>:bonus }
transform = keymap.each_with_object({}) { |(new,old),g| g[new] = ->(h) { h[old] } }
#=> {:FirstName=>#<Proc:0x00005bd270d50298@(irb):391 (lambda)>,
# :LastName=>#<Proc:0x00005bd270d50220@(irb):391 (lambda)>,
# ...
# :Bonus=>#<Proc:0x00005bd270d830f8@(irb):391 (lambda)>}
construct_csv(FName, arr, transform)
puts File.read(FName)
FirstName,LastName,ID,Salary,Bonus
John,Dee,001,100000,50000
Alex,Peck,002,120000,70000
keys_to_remove = [:first_name, :last_name]
keys_to_add = [:full_name, :compensation]
keys = arr.first.keys + keys_to_add - keys_to_remove
#=> [:employee_id, :date_of_birth, :salary, :bonus, :full_name,
# :compensation]
transform = keys.each_with_object({}) do |k,h|
h[k] =
case k
when :full_name
->(h) { h[:first_name] + " " + h[:last_name] }
when :compensation
->(h) { h[:salary].to_i + h[:bonus].to_i }
else
->(h) { h[k] }
end
end
#=> {:employee_id=>#<Proc:0x00005bd271001000@(irb):501 (lambda)>,
# :date_of_birth=>#<Proc:0x00005bd271000f88@(irb):501 (lambda)>,
# :salary=>#<Proc:0x00005bd271000f10@(irb):501 (lambda)>,
# :bonus=>#<Proc:0x00005bd271000ec0@(irb):501 (lambda)>,
# :full_name=>#<Proc:0x00005bd271000e20@(irb):497 (lambda)>,
# :compensation=>#<Proc:0x00005bd271000dd0@(irb):499 (lambda)>}
construct_csv(FName, arr, transform)
puts File.read(FName)
employee_id,date_of_birth,salary,bonus,full_name,compensation
001,10/10/1983,100000,50000,John Dee,150000
002,11/01/1988,120000,70000,Alex Peck,190000