2012-06-29 5 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 코드를 생성하는 방법입니다.