2012-06-29 76 views
1

我试图在每个循环的每行结尾处插入一个逗号作为红宝石。我不想在最后一行输入逗号。我知道array.join(',')特性,但在这种情况下我有点困惑。Ruby每个循环的最后迭代

我该如何重构我的第一次尝试去做我需要的东西?

重要的行

@headers.each do |header| 
      file.puts "`#{table[:source_database]}`.`#{table[:current_name]}`.`#{header[:current_name]}` AS `#{header[:magi_name]}`#{("," unless @headers.last == header)}" if header[:table_id] == table[:id] 
     end 

全类

class Table < ActiveRecord::Base   
    has_many :headers 

    #--------------------------------------------------------------------------------------------------# 

    def self.generate 
    @tables = Table.select([:id, :source_database, :current_name, :magi_name]) 
    @headers = Header.select([:id, :table_id, :current_name, :magi_name]) 

    File.new("magi_generation.sql", "w") 
    @tables.each do |table| 
     File.open("magi_generation.sql", "a+") do |file| 
     file.puts "#Drops current view #{table[:magi_name]} and then recreates it using updated columns" 
     file.puts "DROP VIEW IF EXISTS `#{table[:magi_name]}`;" 
     file.puts "CREATE ALGORITHM=UNDEFINED DEFINER=`user`@`127.0.0.1` SQL SECURITY DEFINER VIEW `#{table[:magi_name]}`" 
     file.puts "AS select" 
     @headers.each do |header| 
      file.puts "`#{table[:source_database]}`.`#{table[:current_name]}`.`#{header[:current_name]}` AS `#{header[:magi_name]}`#{("," unless @headers.last == header)}" if header[:table_id] == table[:id] 
     end 
     file.puts "FROM `#{table[:source_database]}`.`#{table[:current_name]}`;" 
     file.puts "" 
     end 
    end 

    end 

end 
+0

使用each_with_index并查看索引是否是最后一个? –

+0

因此更改为@ tables.each_with_index do | table,index |然后如果index.last ==什么?我几乎已经掌握了这些概念,但还没有完全实现。 – jwg2s

+0

index是一个数字,因此您应该将它与一个数字进行比较,例如:index == @ tables.length-1,那么您应该得到“是最后一个元素”的布尔值 – robustus

回答

7

您可以使用each_with_index,让你当前元素和索引。这样,您可以比较数组的大小和当前元素。

但是,我不喜欢这种方法。在你的情况下,这不是干净的,因为你正在过滤循环内的记录。我宁愿过滤记录,然后只循环有效记录。

file.puts @headers. 
    # keep only elements where the condition matches 
    select { |header| header[:table_id] == table[:id] }. 
    # convert each element into a line 
    map { |header| "`#{table[:source_database]}`.`#{table[:current_name]}`.`#{header[:current_name]}` AS `#{header[:magi_name]}`" }. 
    # merge everything into a single string 
    join(", ") 
+0

+1,功能更多,更清晰。 –

+0

+1,你打我3分钟:) – dbenhur

+0

谢谢,这工作得很好!这正是我想要完成的,但在概念上并不存在。 – jwg2s

1

处理一切就像你想要的,在最后放置一个逗号和换行符并将其放入一个String变量中。完成后,chop关闭字符串的最后两个字符,然后将其写入文件。

for_file = "" 
@header.each do |header| 
    for_file << header + ",\n" 
end 
for_file.chop.chop # Gets rid of last newline and comma 
file.puts for_file 

我意识到我的例子循环不包括您在您的循环在做什么的程度,但它把重要的事情它在一个字符串,然后.chop.chop

此外,不是每个新行都有file.puts ...,而是考虑一个heredoc。

file.puts <<EOF 
SELECT 'nothing' 
FROM dual 
UNION 
SELECT 'something' 
FROM dual; 
EOF 

它可能会使您的SQL更具可读性,您仍然可以使用字符串插值。

这是我如何在我自己的脚本中使用字符串插值生成SQL代码。