2012-06-29 4 views
1

Я пытаюсь вставить запятую в конце каждой строки в каждом цикле в ruby. Я не хочу, чтобы запятая была на последней строке. Я знаю о функции 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-код со строчной интерполяцией в собственных скриптах.

Смежные вопросы