Ruby / eval / wrong number of arguments / require

Sziasztok,

Mikor Ruby kódot futtatok az eval() funkcióval (ez ugye szöveget értelmez Ruby kódként), akkor az eval() meghívása előtt defniálnom kell bizonyos require hívásokat az értelmezett kódból, de nem mindegyiket.

Azt most hagyjuk hogy miért akarom megetetni a kódot az eval()-lal.

Futtassuk az alábbi szöveget eval-lal:

eval "require 'resolv'; require 'json'; puts 5**5"

Habár ez nem ad hibát, és nem is tudom reprodukálni a saját kódomnál lévő problémát, általában némelyik require-t be kell tenni az eval futtatása elé. De nem mindegyiket.

(Az eredeti kódot nem adhatom ki, illetve hatalmas a kódbázis és nincs idő lenyomozni hogy milyen kombinációban nem adna hibát az eval.)

Ha viszont így futtatom, akkor jó:

require 'resolv'
eval "require 'resolv'; require 'json'; puts 5**5"

Körülbelül 15 require-t használok az eredeti kódban, és pont hogy beépítettekre dob hibát, nem pedig külső gem-ként telepítettre.

Vajon miért lehet ez? Miért kell bizonyos require-t (2-t a 15-ből) definiálnom az eval előtt és miért pont azt?

A hibaüzenet az eval() futtatásakor ez:
http://paste.ubuntu.com/23223835/

Egy másik kérdésem, amiből a fenti következik. Erre valakinek ötlet?

https://www.ruby-forum.com/topic/6879045

Nincs valami pipe megoldás, amivel a string-et úgy tudnám kiszolgálni mintha fájl lenne?

Köszi.

Hozzászólások

Szóval valamilyen eval okozza a gondot, de nem árulhatod el, hogy pontosan mi is az, csak annyit tudunk a log alapján, hogy DNS-hez lehet köze (talán genetikus algoritmus?).
Nehéz lesz így mondani valamit...

Szívesen elárulom, de semmi különös nincs. Van pár require, meg utána kód, de csak a require a gond, ez biztos, mert ha odateszem az eval elé, akkor megszűnik a probléma.

Tehát hiába másolok be ide kódot, szerintem nem sokat fog segíteni. A require és az eval kapcsolata lesz a kulcs sejtésem szerint. Olvastam neten a működésről, de nem találtam infót ami segítene lenyomozni.

Talán ilyesmi:


eval "require 'this'; require; require 'that'; require #{uninitalized}; require 'lastone'; dosomething";

Totál nem érted amit felvázoltam, de legalább trollkodsz. Te nem C-ben szoktál mókolni?

Nem szintaktikailag hibás a require, hanem valamiért bizonyosokra hibát dob az eval ha nem definiálom "kívül" is.

Tehát ezzel hibát dob:

mycode = "require 'gem1'; require 'gem2'; p 'hello world'"
eval mycode

Ezzel pedig nem:

mycode = "require 'gem1'; require 'gem2'; p 'hello world'"
require "gem2"
eval mycode

Ennek mi lehet az oka? Hogy melyiket kell kívül definiálnom kicsit megjósolhatatlannak tűnik számomra, mert belső függéseket is ki kell írnom a require-el.

Nem idezted be a hibát okozó utasítást; valami mást idéztél be, ami szerinted nem okoz hibát, csak hasonlít a hibát okozó utasításra.

A log, amit belinkeltél, mintha paraméter nélküli require-re utal.

Nem hiszem, hogy ennyi adat alapján lehetne segíteni az ügyön, de mindenesetre sok szerencsét kívánok hozzá, remélem, sikerül megtalálnod a hibát.

Tudom a hiba mentes és a hibás verzió közti különbséget, azt leírtam. Több infó sajnos nincs. De ezt a vonalat hagyom szerintem.

Inkább ezen indulok el. Erre nincs ötleted?
https://www.ruby-forum.com/topic/6879045

Ezt úgy kellene elképzelni, hogy:

echo "mycode" | ruby

vagyis

echo "p 'hello world'" | ruby

De ezt megcsinálni Ruby kódból hogy lehetne vajon? Sajnos az Open3 nem fut le jól az FCGI-men belül:

require "open3"
o, e, s= Open3.capture3("ruby", stdin_data: "p 'hello world'")

Igazából az egész dolog önnét jön, hogy az FCGI érzékeny nagyon a Ruby kódra. Nem dobhat semmi semmit az STDERR-re, mert akkor nem fut le. Nem is kellene hogy dobjon a kód alapján, de nem fut le mégsem.

Tehát az alábbi kód működik:

mycode = "require \"fcgi\"; FCGI.each_cgi do |cgi| puts \"Content-Type: text/plain; charset=utf-8\n\EZ EGY TESZT\n\" end"

eval mycode

Ha kiírom fájlba, az is működik:

File.write("temp", mycode)
system("ruby temp")

Viszont ez nem:

require "open3"
o, e, s= Open3.capture3("ruby", stdin_data: mycode)

Ez sem:

system("echo '#{mycode}' | ruby")

Ez sem:

`"echo '#{mycode}' | ruby"`

Bahh. Az echo szivat. Egyelőre ez működik (de nem jó megoldás):

`ruby -e 'puts #{mycode}' | ruby`

Ez a kód működik:

http://paste.ubuntu.com/23228945/

require "fcgi"

mycode = 'puts "Content-Type: text/plain; charset=utf-8\n\nHELLO\n"'

FCGI.each_cgi do |cgi|
tempfile = "/tmp/tempfile"
File.write tempfile, mycode

system("ruby #{tempfile}")
# system("cat #{tempfile} | ruby")
end

De ha felcserélem a kommentet a 2 system hívás között, akkor nem működik. Miért nem mehet a cat-tel?

Mert egy interpreter (nem csak a ruby, hanem mindegyik), amikor egy scriptet futtat, akkor nem a standard-inputot irányítja a script-fájlba, a standard input marad, ami volt (például /dev/tty), hanem egy külön handlén keresztül olvassa a script-fájlt.


$ cat proba.sh
#!/bin/sh
ls -l /proc/$$/fd

$ ./proba.sh
lrwx------ 1 teve users 64 Sep 27 06:55 0 -> /dev/pts/0
lrwx------ 1 teve users 64 Sep 27 06:55 1 -> /dev/pts/0
lrwx------ 1 teve users 64 Sep 27 06:55 2 -> /dev/pts/0
lr-x------ 1 teve users 64 Sep 27 06:55 10 -> /home/teve/proba.sh