Jak wygląda tablica po zapisie z pliku

Witam.
Mam kolejny problem.
W dalszym ciągu ćwiczę na irc bocie.
Gdy miał on listę adminów w formie:
admini = [“admin1”, “admin2”]
Taki kod:

admini = ["admin1", "admin2"] if admini.include?($1) then puts "Odezwał się admin."
Działał.
$1 to nick z wyrażenia regularnego.
Jednak kiedy zechcę tablicę wczytać z pliku w którym nicki zapisane są jeden pod drugim:

[code=ruby]admini = []
admin = File.open(“admini.txt”, “r”)
admin.readlines.each { |l|
admini << l
}
admin.close

A potem jej użyć:

           if admini.include?($1) then
           puts "Odezwał się admin."[/code]

To warunek pozostaje niespełniony. Choć sprawdzałem i tablica zwiera nicki adminów.
Ktoś wie dlaczego to może nie działać? Po sześciu dniach już nie mam pojęcia co może być nie tak.

Nie zapominaj, że każda linia w Twoim pliku kończy się znakiem nowego wiersza. Po załadowaniu metodą readlines Twoja tablica będzie miała postać: [“admin1\n”, “admin2\n”]. Rozwiązanie jest proste - musisz oczyścić łańcuch ze znaków nowego wiersza:

admin.readlines.each { |l| admini << l.chop }

Nie wiem czy warto wymyślać koło od nowa. Rozumiem że to ćwiczenia :wink: ale myślę że warto się zainteresować biblioteką YAML
Przykład:

Plik admins

[code]—

  • asia
  • tomek
  • adam[/code]
    Kod w irb

irb(main):001:0> require 'yaml' => true irb(main):002:0> YAML::load_file('admins') => ["asia", "tomek", "adam"]

+1 dla PaK’a

admini = []
admin = File.open("admini.txt", "r")
admin.readlines.each { |l|
              admini << l 
              }

readlines zwraca tablice, więc nie ma po co jej przepisywać po elemencie do kolejnej

czyli w skrócie

admins = (File.open("admins.txt").readlines.map(&:chop) rescue [])

? :slight_smile:

I faktycznie, rozwiązanie z YAML lepiej wygląda.

EDIT:
@cube (poniżej): racja, racja :wink:

@sevos: kontynuując ten hackaton, z Twojego kodu można pozbyć się jeszcze readlines :wink:

dobrze by było od razu zamknąć plik

admins = File.open("admins.txt"){|f| f.readlines}.map ...

balinski Twój sposób niestety nie zadziałał.
Instalowanie bibliotek niestety na razie odpada, bo nie działam u siebie, a na shellu.
Zauważyłem, że o ile taki kod nie działa:

admini = [] admin = File.open("admini.txt", "r") admin.readlines.each { |l| admini << l } admin.close if admini.include?($1) then puts "Odezwał się admin."
To jeśli odniosę się do danego elementu tablicy, to już działa:

admini = [] admin = File.open("admini.txt", "r") admin.readlines.each { |l| admini << l } admin.close if admini[0].include?($1) then puts "Odezwał się admin."
Niestety takie rozwiązanie odpada.

Nie działa, bo nadal są \n na końcu każdej linii. Użyj chompa, tak jak napisano w pierwszej odpowiedzi :wink:

[quote=Risus]balinski Twój sposób niestety nie zadziałał.
Instalowanie bibliotek niestety na razie odpada, bo nie działam u siebie, a na shellu.[/quote]
pracując na shellu możesz doinstalować gem lokalnie i uzywać go.

[quote=Risus]To jeśli odniosę się do danego elementu tablicy, to już działa:

admini = [] admin = File.open("admini.txt", "r") admin.readlines.each { |l| admini << l } admin.close if admini[0].include?($1) then puts "Odezwał się admin."
Niestety takie rozwiązanie odpada.[/quote]
Zdecydowanie odpada. Co Ci proponuję zrobić?

Uruchom konsolę interaktywną, irb i wpusuj po kolei komendy. Albo do swojego kodu dopisz

puts admini.inspect
if admini[0].include?($1)

“działa”, bo sprawdzasz czy pierwszy na liście admin się zalogował
tak naprawdę wykonujesz:

"admin\n".include?("admin")

Co jest prawdą. Spróbuj podać nazwe innego admina i nie przejdzie. Tak jak pisaliśmy Ci wcześniej, użyj metody chop na każdym stringu.

Poza tym można to zapisac krócej, jak już cube mnie poprawił:

admins = File.open("admins.txt", &:readlines).map(&:chop)

Rada na przyszłość. Używaj IRB i najczęsciej jak się da inspektuj obiekty, wyniki działania metod: np.

$ irb IRB initialized! irb(main):001:0> File.open("admini.txt") => #<File:admini.txt> irb(main):002:0> File.open("admini.txt", &:readlines) => ["sevos\n", "root\n", "admin\n"] irb(main):003:0> File.open("admini.txt", &:readlines).map(&:chop) => ["sevos", "root", "admin"] irb(main):004:0>
Możesz zapytać, czym jest “magiczny” zapis &:readlines. Jest to skrócony zapis bloku:

File.open("admini.txt") { |f| f.readlines} File.open("admini.txt", &:readlines)
obie powyższe linijki znaczą to samo. Więcej dowiesz się googlając za hasłem “symbol to proc”. Ale powiedzmy, że to taki bajer :wink:

Hmm ciekawe rozwiązanie z &:readlines. Trzeba się będzie douczyć. :wink:
Ok, kilka poprawek w kodzie i zastosowanie sposobu sevosa zdało rezultat.
Działa jak powinno. Dzięki chłopaki. ^^

sevos, dzieki za Symbol#to_proc, nie znalem tego a swietnie skraca kod

Symbol#to_proc poznałem chyba oglądajc railscasty, ale głowy nie dam.