2017-03-05 5 views
0

Ok, also habe ich ein DSL bauen und ein Teil davon erfordert den Benutzer des DSL zu definieren, was ich einen 'Schreibblock'Ich habe ein Rätsel mit Blöcken und übergibt sie herum, brauche Hilfe, es zu lösen

writer do |data_block| 
    CSV.open("data.csv", "wb") do |csv| 
     headers_written = false 
     data_block do |hash| 
     (csv << headers_written && headers_written = true) unless headers_written 
     csv << hash.values 
     end 
    end 
    end 

der Schriftsteller Block wird wie folgt aufgerufen:

def pull_and_store 
    raise "No writer detected" unless @writer 
    @writer.call(-> (&block) { 
     pull(pull_initial,&block) 
    }) 
    end 

das Problem ist zweifach, erstens, ist dies der beste Weg, um diese Art der Sache zu handhaben und die zweiten ein seltsamer Fehler ich erhalte:

undefined method data_block' for Servo_City:Class (NoMethodError) 

Es ist seltsam, weil ich data_block genau dort sehen kann, oder zumindest existiert es vor dem CSV Block auf jeden Fall.

Was ich versuche zu erstellen ist eine Möglichkeit für den Benutzer, einen Wrapper-Block zu schreiben, der sich um einen Block wickelt und einen Block für den Block, der gewickelt wird, ergibt, wow, das ist ein Bissen.

+0

Hmm, ich verstehe nicht wirklich, was Sie erreichen wollen. Es gibt mehrere mögliche Fehlerursachen, einige möglicherweise in dem Code, den Sie nicht zeigen. Nur eine begründete Vermutung: Sie rufen 'writer' mit einem Block auf, der einen Block' data_block' akzeptiert, der wiederum einen Block akzeptiert. Scheint sehr kompliziert für ein DSL. Versuchen Sie es wie folgt zu dereferenzieren: 'writer do | & data_block |' und rufen Sie es dann mit 'data_block.call do | hash |' auf. Was ich nicht sehe ist, wo der 'hash' übergeben wird. (Tut' '' 'das?) Warum gibst du es nicht zuerst an den Writerblock, wie' writer do | data_block, hash | ' ? – Raffael

+0

Deshalb frage ich, es ist ein bisschen kompliziert. 'pull' nimmt einen Block und gibt ihm einen Hash; folglich nimmt '@ writer.call' einen Block, der an den Block' data_block' übergeben wird. Der Grund, warum ich es so mache, ist die einzige Möglichkeit, die mir erlaubt, die Pull-Methode in den CSV-Block zu integrieren.Andernfalls müsste ich ein csv-Objekt erstellen, den Hash an die CSV-Datei anhängen und dann für jeden ausgegebenen Hash schließen. Ich habe das Gefühl, dass ich dies zu sehr verkompliziere. Könnte ich vielleicht ein IO-Objekt oder etwas anderes mit mir passieren und es stattdessen benutzen? – Thermatix

Antwort

1

Inner mir will nicht eine Antwort schreiben, bevor die Frage geklärt ist.
Andere mich Wetten, die Codebeispiele helfen, das Problem zu klären.


Ich gehe davon aus, dass der Schriftsteller Block die Aufgabe, persistierende einige Daten hat. Können Sie die Daten in aufzählbarer Form in den Block übertragen? Das würde dem DSL-Benutzer erlauben, etwas in der Art zu schreiben:

writer do |data| 
    CSV.open("data.csv", "wb") do |csv| 
    csv << header_row 
    data.each do |hash| 
     data_row = hash.values 
     csv << data_row 
    end 
    end 
end 

Keine Blockübergabe erforderlich.

Beachten Sie, dass Sie eine Lazy Sammlung übergeben können, wenn Sie mit sehr großen Datensätzen zu tun haben.

Löst dies Ihr Problem?

+0

Tut mir leid, dass ich bisher nicht geantwortet habe. 'Data.each' funktioniert nicht, weil es keinen Iterator ergibt, sondern den Block aufruft und einen Hash an den Block übergibt. – Thermatix

+0

Das ist der Punkt. Machen Sie es zu einem Aufzählungszeichen. Warum müssen es Blöcke sein? – Raffael

+0

Weil es einfach nicht möglich ist, es aufzählbar zu machen, nicht mit der Art, wie der Code strukturiert ist und der Block ein paar Methodenaufrufe ausführt, bevor er den Block benutzt. – Thermatix

0

Der Versuch, die CSV-Datei jedes Mal zu öffnen, wenn Sie einen Datensatz schreiben möchten, erscheint zu komplex und führt wahrscheinlich zu einer schlechten Leistung (es sei denn, die Schreibvorgänge sind unterbrochen). Es überschreibt auch die CSV-Datei jedes Mal, es sei denn, Sie ändern den Dateimodus von wb zu ab.

Ich denke, etwas Einfaches wie:

csv = CSV.open('data.csv', 'wb') 
csv << headers 
writer do |hash| 
    csv << hash.values 
end 

verständlicher wäre etwas.

Verwandte Themen