Ruby: Czy mogę napisać ciąg wieloliniowy bez konkatenacji?


397

Czy istnieje sposób, aby ten wyglądał trochę lepiej?

conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' +
          'from table1, table2, table3, etc, etc, etc, etc, etc, ' +
          'where etc etc etc etc etc etc etc etc etc etc etc etc etc'

Czy istnieje sposób na sugerowanie konkatenacji?


28
Uważaj na ataki typu SQL injection. :)
Roy Tinker,

Odpowiedzi:


595

W tej odpowiedzi są fragmenty, które pomogły mi uzyskać to, czego potrzebowałem (łatwe łączenie wielu wierszy BEZ dodatkowej białej spacji), ale ponieważ żadna z rzeczywistych odpowiedzi nie zawierała tego, kompiluję je tutaj:

str = 'this is a multi-line string'\
  ' using implicit concatenation'\
  ' to prevent spare \n\'s'

=> "this is a multi-line string using implicit concatenation to eliminate spare
\\n's"

Jako bonus, oto wersja z zabawną składnią HEREDOC (poprzez ten link ):

p <<END_SQL.gsub(/\s+/, " ").strip
SELECT * FROM     users
         ORDER BY users.id DESC
END_SQL
# >> "SELECT * FROM users ORDER BY users.id DESC"

To ostatnie dotyczyłoby głównie sytuacji wymagających większej elastyczności przetwarzania. Osobiście mi się to nie podoba, umieszcza przetwarzanie w dziwnym miejscu przed łańcuchem (tj. Przed nim, ale przy użyciu metod instancji, które zwykle pojawiają się później), ale tam jest. Zauważ, że jeśli wcinasz ostatni END_SQLidentyfikator (który jest wspólny, ponieważ prawdopodobnie znajduje się on w funkcji lub module), będziesz musiał użyć składni dzielonej (to znaczy p <<-END_SQLzamiast p <<END_SQL). W przeciwnym razie wcięcie białych znaków powoduje interpretację identyfikatora jako kontynuacji ciągu.

Nie oszczędza to dużo pisania, ale dla mnie wygląda ładniej niż używanie znaków +.

Również (mówię w edycji, kilka lat później), jeśli używasz Ruby 2.3+, dostępny jest również operator << ~ , który usuwa dodatkowe wcięcia z ostatniego ciągu. W takim przypadku powinieneś być w stanie usunąć .gsubwywołanie (chociaż może to zależeć zarówno od początkowego wcięcia, jak i twoich ostatecznych potrzeb).

EDYCJA: Dodanie jeszcze jednego:

p %{
SELECT * FROM     users
         ORDER BY users.id DESC
}.gsub(/\s+/, " ").strip
# >> "SELECT * FROM users ORDER BY users.id DESC"

2
To stare pytanie, ALE albo w odpowiedzi jest błąd, albo od tego czasu nastąpiła zmiana składni. p <<END_SQLpowinno być p <<-END_SQLW przeciwnym razie jest to Odpowiedź. opcjonalnie możesz usunąć wiodące białe znaki za pomocą squiggly operatora HEREDOC,<<~END_SQL
jaydel

To tylko błąd, jeśli końcowy identyfikator jest wcięty (myślnik mówi tłumaczowi rubyowi, aby przyciął białe znaki przed określeniem końcowego identyfikatora). Mogę jednak wspomnieć o tym. Ponadto ~ jest niepotrzebne, gsub \ s + i strip już usuwają wiodące białe znaki.
A. Wilson,

Dodanie <<~do odpowiedzi byłoby fajne, w końcu badałem to stamtąd. Osobiście używam, <<~MSG.strip ... MSGktóry usuwa również ostatni \n.
Qortex

1
Kiedy napisałem tę odpowiedź (dziewięć lat temu, sheesh!), Ruby była na 1.9, a << ~ (najwyraźniej) zostało wprowadzone dopiero w 2.3. W każdym razie, pomijając historię starożytną, dodam ją, dzięki za jej poruszenie.
A. Wilson

Dziękujemy za to, że jesteś jedną z niewielu odpowiedzi, które nie dodają nowych znaków, a tego właśnie unikałem, gdy znalazłem to pytanie.
Josh

174

W Ruby 2.0 możesz teraz po prostu używać %

Na przykład:

SQL = %{
SELECT user, name
FROM users
WHERE users.id = #{var}
LIMIT #{var2}
}

14
Działa również w Ruby 1.9.3.
Andy Stewart,

26
Ciąg utworzony za pomocą tej składni będzie zawierał zarówno znaki nowego wiersza, jak i wcięcia dodane do kolejnych wierszy.
James

To jest nawet lepsze niż << EOT ...... EOT (tutaj dokument)! w razie potrzeby wykonuje również interpolację.
Nasser

1
@Nasser Hredok również interpoluje.
Pozew Fund Moniki w dniu

3
Jeśli używasz Railsów, wywołanie squishwyjścia powinno być pomocne.
Jignesh Gohel,

167

Tak, jeśli nie przeszkadza ci wstawianie dodatkowych znaków nowej linii:

 conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7
            from table1, table2, table3, etc, etc, etc, etc, etc,
            where etc etc etc etc etc etc etc etc etc etc etc etc etc'

Alternatywnie możesz użyć heredoc :

conn.exec <<-eos
   select attr1, attr2, attr3, attr4, attr5, attr6, attr7
   from table1, table2, table3, etc, etc, etc, etc, etc,
   where etc etc etc etc etc etc etc etc etc etc etc etc etc
eos

87
Możesz również użyć%Q(...)
BaroqueBobcat

3
@Zombies: Znaki nowego wiersza są zwykle dozwolone w instrukcjach SQL i są traktowane jak zwykłe białe znaki.
Mark Byers,

2
zobacz moją odpowiedź poniżej, możesz po prostu użyć% teraz.
Robbie Guilfoyle

4
Możesz także użyć%(...)
dzielnik zero

1
Należy pamiętać o tym, jeśli celowo dodajesz końcowe białe znaki i używasz jednego z tych rozwiązań, ponieważ edytor może automatycznie usuwać końcowe miejsce podczas zapisywania pliku. Chociaż zwykle wolę takie zachowanie, kilka razy spowodowało to nieoczekiwane problemy. Rozwiązaniem jest napisanie ciągu wieloliniowego, tak jak OP zrobił w pytaniu.
Dennis

50

Istnieje wiele składni ciągów wieloliniowych, które już przeczytałeś. Moim ulubionym jest styl Perla:

conn.exec %q{select attr1, attr2, attr3, attr4, attr5, attr6, attr7
      from table1, table2, table3, etc, etc, etc, etc, etc,
      where etc etc etc etc etc etc etc etc etc etc etc etc etc}

Ciąg wieloliniowy zaczyna się od% q, po którym następuje {, [lub (, a następnie kończy się odpowiednim odwróconym znakiem.% Q nie zezwala na interpolację;% Q robi to, abyś mógł napisać takie rzeczy:

conn.exec %Q{select attr1, attr2, attr3, attr4, attr5, attr6, attr7
      from #{table_names},
      where etc etc etc etc etc etc etc etc etc etc etc etc etc}

Właściwie nie mam pojęcia, jak nazywane są tego rodzaju ciągi wieloliniowe, więc nazwijmy je multilinią Perl.

Zauważ jednak, że niezależnie od tego, czy używasz multilinii Perla, czy heredoków, jak sugerowali Mark i Peter, skończysz z potencjalnie niepotrzebnymi białymi spacjami. Zarówno w moich przykładach, jak i ich przykładach, linie „from” i „where” zawierają wiodące białe znaki ze względu na ich wcięcia w kodzie. Jeśli ten biały znak nie jest pożądany, musisz użyć połączonych łańcuchów, tak jak teraz.


4
z # {nazwa_tabeli} nie działałby w tym przykładzie, ponieważ użyłeś% q {}, działałby, gdybyś użył% q [] lub ()
MatthewFord

2
Moim ulubionym w tym stylu jest po prostu% {super multiline string z obsługą interpolacji}
Duke

ciągi utworzone z %qrodziny będą zawierać nowe wiersze, które nie są równoważne z oryginalnym kodem.
Josh

29

Czasami warto usunąć nowe znaki wiersza, \ntakie jak:

conn.exec <<-eos.squish
 select attr1, attr2, attr3, attr4, attr5, attr6, attr7
 from table1, table2, table3, etc, etc, etc, etc, etc,
 where etc etc etc etc etc etc etc etc etc etc etc etc etc
eos

5
jest to szyna oparta na nie rubinowym
a14m

23

Możesz także użyć podwójnych cudzysłowów

x = """
this is 
a multiline
string
"""

2.3.3 :012 > x
 => "\nthis is\na multiline\nstring\n"

Jeśli to konieczne, aby usunąć podziały wiersza „\ n”, użyj ukośnika odwrotnego „\” na końcu każdej linii


5
Ten sam wynik można osiągnąć za pomocą pojedynczych podwójnych cudzysłowów. W Ruby nie ma czegoś takiego jak potrójne podwójne cytaty. Po prostu interpretuje je jako "" + "double quotes with some content" + "".
rakvium

Tak, ale „” „+” \ n hello \ n ”+” „
Dziwnie

1
Tak, wygląda to dziwnie i dlatego nie ma powodu, aby dodawać dodatkowe podwójne cudzysłowy, gdy można po prostu użyć pojedynczych cudzysłowów z tym samym wynikiem.
rakvium

Tak, miałem na myśli znak plus. Podwójne cudzysłowy bez niego wyglądają dobrze, są czytelne i łatwiejsze do znalezienia zamiast pojedynczego cudzysłowu, którego należy używać w ciągach pojedynczych wierszy.
juliangonzalez

1
Mam na myśli, że po prostu "x"wygląda lepiej i działa szybciej niż """x"""(który jest w zasadzie taki sam jak ""+"x"+"") lub """""x"""""(który jest taki sam jak "" + "" + "x" + "" + ""). To Ruby, a nie Python, którego używasz """zamiast, "gdy potrzebujesz ciągu wieloliniowego.
rakvium

15
conn.exec = <<eos
  select attr1, attr2, attr3, attr4, attr5, attr6, attr7
  from table1, table2, table3, etc, etc, etc, etc, etc,
  where etc etc etc etc etc etc etc etc etc etc etc etc etc
eos

1
użycie heredoc bez „-”, tak jak w „<< - eos”, obejmie dodatkowe pola lidera. patrz odpowiedź Marka Byersa.
ives

heredoc będzie zawierać nowe wiersze, które nie są równoważne z oryginalnym kodem.
Josh

15

Inne opcje:

#multi line string
multiline_string = <<EOM
This is a very long string
that contains interpolation
like #{4 + 5} \n\n
EOM

puts multiline_string

#another option for multiline string
message = <<-EOF
asdfasdfsador #{2+2} this month.
asdfadsfasdfadsfad.
EOF

puts message

1
Czy należy zmienić <<EOMna <<-EOM, nie?
kingPuppy

Może to wyglądało na mój <<-EOFprzykład. Domyślam się, że tak czy inaczej działa.
Alex Cohen

heredoc będzie zawierać nowe wiersze, które nie są równoważne z oryginalnym kodem.
Josh

11

Niedawno dzięki nowym funkcjom w Ruby 2.3 nowy squiggly HEREDOCpozwoli ci napisać nasze ciągi wielowierszowe w przyjemny sposób przy minimalnej zmianie, więc użycie tego w połączeniu z .squish(jeśli używasz szyn) pozwoli ci pisać w sposób przyjemny! w przypadku tylko przy użyciu Ruby, można zrobić <<~SQL.split.join(" ")co jest prawie taka sama

[1] pry(main)> <<~SQL.squish
[1] pry(main)*   select attr1, attr2, attr3, attr4, attr5, attr6, attr7
[1] pry(main)*   from table1, table2, table3, etc, etc, etc, etc, etc,
[1] pry(main)*   where etc etc etc etc etc etc etc etc etc etc etc etc etc
[1] pry(main)* SQL
=> "select attr1, attr2, attr3, attr4, attr5, attr6, attr7 from table1, table2, table3, etc, etc, etc, etc, etc, where etc etc etc etc etc etc etc etc etc etc etc etc etc"

ref: https://infinum.co/the-capsized-eight/multiline-strings-ruby-2-3-0-the-squiggly-heredoc


squish to szyny, a nie rubin
Josh

1
@Josh, tak, masz rację, zaktualizowałem odpowiedź, na zdrowie.
Mark Jad

6
conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' <<
        'from table1, table2, table3, etc, etc, etc, etc, etc, ' <<
        'where etc etc etc etc etc etc etc etc etc etc etc etc etc'

<< jest operatorem konkatenacji ciągów znaków


2
+jest zwykłym operatorem konkatenacji, <<jest operatorem dołączającym w miejscu . Przydaje się tutaj stosowanie efektów ubocznych w dosłowności (pierwszy ciąg jest dwukrotnie modyfikowany i zwracany), ale IMHO jest dziwny i sprawia, że ​​robię podwójne ujęcie, +co byłoby całkowicie jasne. Ale może jestem po prostu nowy dla Ruby ...
Beni Cherniavsky-Paskin

To nie zadziała, jeśli frozen_string_literaljest włączone
Raido,

6

Jeśli masz na myśli dodatkowe spacje i znaki nowej linii, możesz użyć

conn.exec %w{select attr1, attr2, attr3, attr4, attr5, attr6, attr7
  from table1, table2, table3, etc, etc, etc, etc, etc,
  where etc etc etc etc etc etc etc etc etc etc etc etc etc} * ' '

(użyj% W dla interpolowanych ciągów)


Bardzo mi się podoba, ponieważ pozwala na znacznie więcej kombinacji użytkowania.
schmijos

1
Spowoduje to zgniecenie wielu sąsiadujących ze sobą pól w jedno. (Wygładzenie linii + nowy wcięcie po wygranej jest tutaj zwycięstwem, ale może być zaskakujące.)
Beni Cherniavsky-Paskin

5

Aby uniknąć zamykania nawiasów dla każdej linii, możesz po prostu użyć podwójnych cudzysłowów z odwrotnym ukośnikiem, aby wyjść z nowej linii:

"select attr1, attr2, attr3, attr4, attr5, attr6, attr7 \
from table1, table2, table3, etc, etc, etc, etc, etc, \
where etc etc etc etc etc etc etc etc etc etc etc etc etc"

To jedna z niewielu odpowiedzi na tej stronie, która faktycznie odpowiada na pytanie!
Josh

4
conn.exec [
  "select attr1, attr2, attr3, ...",
  "from table1, table2, table3, ...",
  "where ..."
].join(' ')

Ta sugestia ma tę przewagę nad dokumentami i długimi łańcuchami, że automatyczne wcięcia mogą odpowiednio wciąć każdą część łańcucha. Ale ma to koszt wydajności.


@Aidan, możesz zamienić przecinki na ukośniki odwrotne (a la C) i nie będzie konieczne łączenie (lub tablica): interpreter połączy łańcuchy w czasie (chyba) parsowania, dzięki czemu będzie dość szybki w porównaniu do większości alternatyw . Jedną zaletą łączenia szeregu ciągów jest to, że niektóre auto-wcięcia wykonują lepszą pracę niż na przykład z ciągami tutaj-doc lub \.
Wayne Conrad

1
Jedna uwaga, składnia heredoc << - pozwoli na odpowiednie wcięcie.
A. Wilson,

2

Ruby-way (TM) od Ruby 2.3: Aby zdefiniować wieloliniowy ciąg znaków z nowymi liniami i prawidłową identyfikacją, użyj zawijasowego HEREDOC <<~ :

conn.exec <<~EOS
            select attr1, attr2, attr3, attr4, attr5, attr6, attr7
            from table1, table2, table3, etc, etc, etc, etc, etc
            where etc etc etc etc etc etc etc etc etc etc etc etc etc
          EOS

# -> "select...\nfrom...\nwhere..."

Jeśli poprawna identyfikacja nie stanowi problemu, wówczas pojedyncze i podwójne cudzysłowy mogą obejmować wiele wierszy w języku Ruby:

conn.exec "select attr1, attr2, attr3, attr4, attr5, attr6, attr7 
           from table1, table2, table3, etc, etc, etc, etc, etc, 
           where etc etc etc etc etc etc etc etc etc etc etc etc etc"    

# -> "select...\n           from...\n           where..."

Jeśli pojedyncze lub podwójne cudzysłowy są kłopotliwe, ponieważ wymagałoby to mnożenia znaków ucieczki, to oznaczenie literału procentowego ciągu %jest najbardziej elastycznym rozwiązaniem:

conn.exec %(select attr1, attr2, attr3, attr4, attr5, attr6, attr7
            from table1, table2, table3, etc, etc, etc, etc, etc
            where (ProductLine = 'R' OR ProductLine = "S") AND Country = "...")
# -> "select...\n            from...\n            where..."

Jeśli celem jest uniknięcie nowych linii (które spowodują zarówno zawijany HEREDOC, cudzysłowy, jak i procent literału łańcucha), to odwrotny ukośnik, jako ostatni znak niebiałej spacji, będzie kontynuował linię i spowoduje, że Ruby połączy łańcuchy z powrotem do tyłu (uważaj na spacje w cytowanym ciągu):

conn.exec 'select attr1, attr2, attr3, attr4, attr5, attr6, attr7 ' \
          'from table1, table2, table3, etc, etc, etc, etc, etc, ' \
          'where etc etc etc etc etc etc etc etc etc etc etc etc etc'

# -> "select...from...where..."

Jeśli używasz Railsów, String.squishusunie ciąg początkowej i końcowej spacji i zwinie wszystkie kolejne białe spacje (znaki nowej linii, tabulatory i wszystkie) w jedną spację:

conn.exec "select attr1, attr2, attr3, attr4, attr5, attr6, attr7 
           from table1, table2, table3, etc, etc, etc, etc, etc, 
           where etc etc etc etc etc etc etc etc etc etc etc etc etc".squish

# -> "select...from...where..."

Więcej szczegółów:

Ruby Składnia HEREDOC

Działa tutaj notacja dokumentacyjna dla ciągów znaków, która jest sposobem na oznaczenie długich bloków tekstu w kodzie. Po nim <<następuje zdefiniowany przez użytkownika ciąg znaków (terminator końca łańcucha). Wszystkie następujące wiersze są konkatenowane do momentu znalezienia terminatora End of String na samym początku wiersza:

puts <<HEREDOC 
Text Text Text Text
Bla Bla
HEREDOC
# -> "Text Text Text Text\nBlaBla"

Terminator końca łańcucha można wybierać dowolnie, ale często używa się czegoś takiego jak „EOS” (koniec łańcucha) lub czegoś, co pasuje do domeny łańcucha, np. „SQL”.

HEREDOC domyślnie obsługuje interpolację lub gdy podwójny cudzysłów terminatora EOS:

price = 10
print <<"EOS"  # comments can be put here
1.) The price is #{price}.
EOS
# -> "1.) The price is 10."

Interpolację można wyłączyć, jeśli terminator EOS jest cytowany:

print <<'EOS' # Disabled interpolation
3.) The price is #{price}.
EOS
# -> "3.) The price is #{price}."

Jednym ważnym ograniczeniem <<HEREDOCjest to, że terminator końca łańcucha musi znajdować się na początku wiersza:

  puts <<EOS 
    def foo
      print "foo"
    end
  EOS
EOS
#-> "....def foo\n......print "foo"\n....end\n..EOS

Aby obejść ten problem, utworzono <<-składnię. Umożliwia wcięcie terminatora EOS, dzięki czemu kod wygląda ładniej. Linie między <<-terminatorem i terminatorem EOS są nadal używane w pełnym zakresie, włączając wszystkie wcięcia:

puts <<-EOS # Use <<- to indent End of String terminator
  def foo
    print "foo"
  end
EOS
# -> "..def foo\n....print "foo"\n..end"

Od Ruby 2.3 mamy teraz zawijas HEREDOC <<~usuwa wiodące białe znaki:

puts <<~EOS # Use the squiggly HEREDOC <<~ to remove leading whitespace (since Ruby 2.3!)
  def foo
    print "foo"
  end
EOS
# -> "def foo\n..print "foo"\nend"

Puste linie i linie zawierające tylko tabulatory i spacje są ignorowane przez << ~

puts <<~EOS.inspect 
  Hello

    World!
EOS
#-> "Hello\n..World!"

Jeśli używane są zarówno tabulatory, jak i spacje, tabulatory są traktowane jako równe 8 spacjom. Jeśli linia z najmniejszymi wcięciami znajduje się na środku karty, karta ta nie jest usuwana.

puts <<~EOS.inspect
<tab>One Tab
<space><space>Two Spaces
EOS
# -> "\tOne Tab\nTwoSpaces"

HEREDOC może robić szalone rzeczy, takie jak wykonywanie poleceń za pomocą odwrotnych poleceń:

puts <<`EOC`            
echo #{price}
echo #{price * 2}
EOC

Definicje ciągów HEREDOC można „ustawiać w stos”, co oznacza, że ​​pierwszy terminator EOS (poniżej EOSFOO) zakończy pierwszy ciąg i rozpocznie drugi (poniżej EOSBAR):

print <<EOSFOO, <<EOSBAR    # you can stack them
I said foo.
EOSFOO
I said bar.
EOSBAR

Nie sądzę, aby ktokolwiek kiedykolwiek używałby go jako takiego, ale <<EOStak naprawdę jest to dosłownie ciąg znaków i można go umieścić wszędzie tam, gdzie zwykle można go umieścić:

def func(a,b,c)
  puts a
  puts b
  puts c
end

func(<<THIS, 23, <<THAT) 
Here's a line
or two.
THIS
and here's another.
THAT

Jeśli nie masz Ruby 2.3, ale Rails >=3.0, możesz użyć String.strip_heredoctego samego co<<~

# File activesupport/lib/active_support/core_ext/string/strip.rb, line 22
class String
  def strip_heredoc
    gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "".freeze)
  end
end

puts <<-USAGE.strip_heredoc # If no Ruby 2.3, but Rails >= 3.0
  This command does such and such.

  Supported options are:
    -h         This message
    ...
USAGE

Procent literałów łańcuchowych

Zobacz RubyDoc do sposobu korzystania z znak procentu po którym następuje ciąg w nawiasach powiązać takie jak %(...), %[...], %{...}, itd. Lub parę jakiegokolwiek charakteru niealfanumeryczne takich jak%+...+

Ostatnie słowa

Wreszcie, aby uzyskać odpowiedź na pierwotne pytanie „Czy istnieje sposób sugerowania konkatenacji?” odpowiedział: Ruby zawsze oznacza konkatenację, jeśli dwa ciągi (pojedyncze i podwójne cudzysłowy) zostaną znalezione jeden po drugim:

puts "select..." 'from table...' "where..."
# -> "select...from table...where..."

Zastrzeżenie polega na tym, że nie działa to w przypadku łamania linii, ponieważ Ruby interpretuje koniec instrukcji, a wynikowa linia samych ciągów w linii nic nie robi.


1

Elegancka odpowiedź dzisiaj:

<<~TEXT
Hi #{user.name}, 

Thanks for raising the flag, we're always happy to help you.
Your issue will be resolved within 2 hours.
Please be patient!

Thanks again,
Team #{user.organization.name}
TEXT

Istnieje różnica w, <<-TEXTi <<~TEXTpierwszy zachowuje odstępy wewnątrz bloku, a drugi nie.

Istnieją również inne opcje. Podobnie jak konkatenacja itp., Ale ogólnie rzecz biorąc ma to większy sens.

Jeśli się tutaj mylę, daj mi znać, jak ...


heredoc będzie zawierać nowe wiersze, które nie są równoważne z oryginalnym kodem.
Josh

1

Podobnie jak ty szukałem również rozwiązania, które nie obejmuje nowych linii . (Chociaż mogą być bezpieczne w SQL, w moim przypadku nie są bezpieczne, a ja mam duży blok tekstu do załatwienia)

Jest to prawdopodobnie równie brzydkie, ale możesz w ukośniku heredoc uciec przed ukośnikiem, aby pominąć je w powstałym ciągu:

conn.exec <<~END_OF_INPUT
    select attr1, attr2, attr3, attr4, attr5, attr6, attr7 \
    from table1, table2, table3, etc, etc, etc, etc, etc, \
    where etc etc etc etc etc etc etc etc etc etc etc etc etc
  END_OF_INPUT

Pamiętaj, że nie można tego zrobić bez interpolacji (IE <<~'END_OF_INPUT'), więc bądź ostrożny. #{expressions}zostaną ocenione tutaj, ale nie będą w twoim oryginalnym kodzie. Odpowiedź A. Wilsona może być z tego powodu lepsza.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.