Apa praktik terbaik jika saya ingin require
file relatif di Ruby dan saya ingin itu berfungsi di 1.8.x dan> = 1.9.2?
Saya melihat beberapa opsi:
- lakukan saja
$LOAD_PATH << '.'
dan lupakan semuanya - melakukan
$LOAD_PATH << File.dirname(__FILE__)
require './path/to/file'
- periksa apakah
RUBY_VERSION
<1.9.2, lalu definisikanrequire_relative
sebagairequire
, gunakan direquire_relative
mana-mana yang diperlukan setelahnya - periksa apakah
require_relative
sudah ada, jika sudah, coba untuk melanjutkan seperti pada kasus sebelumnya - gunakan konstruksi aneh seperti - sayangnya mereka sepertinya tidak bekerja di Ruby 1.9 secara menyeluruh, karena, misalnya:
require File.join(File.dirname(__FILE__), 'path/to/file')
$ cat caller.rb require File.join(File.dirname(__FILE__), 'path/to/file') $ cat path/to/file.rb puts 'Some testing' $ ruby caller Some testing $ pwd /tmp $ ruby /tmp/caller Some testing $ ruby tmp/caller tmp/caller.rb:1:in 'require': no such file to load -- tmp/path/to/file (LoadError) from tmp/caller.rb:1:in '<main>'
- Bahkan konstruksi yang lebih aneh: tampaknya berfungsi, tetapi aneh dan tidak cukup tampan.
require File.join(File.expand_path(File.dirname(__FILE__)), 'path/to/file')
- Gunakan backports gem - ini agak berat, membutuhkan infrastruktur rubygem dan memasukkan banyak solusi lain, sementara saya hanya ingin
require
bekerja dengan file relatif.
Ada pertanyaan terkait erat di StackOverflow yang memberikan beberapa contoh lagi, tetapi itu tidak memberikan jawaban yang jelas - yang merupakan praktik terbaik.
Apakah ada solusi universal yang layak dan diterima oleh semua orang untuk membuat aplikasi saya berjalan pada Ruby <1.9.2 dan> = 1.9.2?
MEMPERBARUI
Klarifikasi: Saya tidak hanya menginginkan jawaban seperti "Anda dapat melakukan X" - pada kenyataannya, saya telah menyebutkan sebagian besar pilihan yang dipertanyakan. Saya ingin alasan , yaitu mengapa itu adalah praktik terbaik, apa pro dan kontra dan mengapa harus dipilih di antara yang lain.
require
danrequire_relative
?a.rb
dan ingin membuat penerjemah membaca dan mem-parsing isi fileb.rb
dalam direktori saat ini (biasanya dir yang sama dengana.rb
), Anda hanya akan menulisrequire 'b'
dan itu akan baik-baik saja karena jalur pencarian default termasuk direktori saat ini. Dalam Ruby 1.9 yang lebih modern, Anda harus menulisrequire_relative 'b'
dalam hal ini, karenarequire 'b'
hanya akan mencari di jalur perpustakaan standar. Itulah hal yang merusak kompatibilitas maju dan mundur untuk skrip sederhana yang tidak akan diinstal dengan benar (misalnya, instal skrip sendiri).backports
hanya untukrequire_relative
, lihat jawaban saya ...Jawaban:
Solusi untuk ini baru saja ditambahkan ke permata 'aws' jadi saya pikir saya akan membagikannya karena terinspirasi oleh pos ini.
https://github.com/appoxy/aws/blob/master/lib/awsbase/require_relative.rb
Ini memungkinkan Anda untuk menggunakan
require_relative
seperti yang Anda lakukan di ruby 1.9.2 di ruby 1.8 dan 1.9.1.sumber
require_relative
Fungsi termasuk dalam proyek perluasan ke perpustakaan inti Ruby, ditemukan di sini: rubyforge.org/projects/extensions Anda harus dapat menginstal mereka dengangem install extensions
. Kemudian dalam kode Anda tambahkan baris berikut sebelumrequire_relative
: memerlukan 'ekstensi / semua' (bersumber dari posting Aurril di sini )Sebelum saya melakukan lompatan ke 1.9.2 saya menggunakan yang berikut ini untuk keperluan relatif:
Agak aneh pertama kali Anda melihatnya, karena sepertinya ada tambahan '..' di awal. Alasannya adalah bahwa
expand_path
akan memperluas path relatif ke argumen kedua, dan argumen kedua akan ditafsirkan seolah-olah itu adalah direktori.__FILE__
jelas bukan direktori, tapi itu tidak masalah karenaexpand_path
tidak peduli apakah ada file atau tidak, itu hanya akan menerapkan beberapa aturan untuk memperluas hal-hal seperti..
,.
dan~
. Jika Anda bisa melupakan awal "waitaminute tidak ada tambahan di..
sana?" Saya pikir kalimat di atas bekerja dengan baik.Dengan asumsi bahwa
__FILE__
adalah/absolute/path/to/file.rb
, apa yang terjadi adalah bahwaexpand_path
akan membangun string/absolute/path/to/file.rb/../relative/path
, dan kemudian menerapkan aturan yang mengatakan bahwa..
harus menghapus komponen path sebelum (file.rb
dalam kasus ini), kembali/absolute/path/to/relative/path
.Apakah ini praktik terbaik? Tergantung pada apa yang Anda maksud dengan itu, tetapi sepertinya itu semua di atas basis kode Rails, jadi saya akan mengatakan itu setidaknya idiom yang cukup umum.
sumber
Beliung memiliki cuplikan untuk 1,8. Ini dia:
Ini pada dasarnya hanya menggunakan apa yang dijawab Theo, tetapi Anda masih bisa menggunakannya
require_relative
.sumber
$RUBY_VERSION
atau dengan memeriksa apakahrequire_relative
ada secara langsung?require_relative
sudah ditentukan.Ini bukan kebiasaan keamanan yang baik: mengapa Anda harus mengekspos seluruh direktori Anda?
Ini tidak berfungsi jika RUBY_VERSION <1.9.2
Anda sudah menjawab mengapa ini bukan pilihan terbaik.
Ini mungkin berhasil, tetapi ada cara yang lebih aman dan lebih cepat: untuk menghadapi pengecualian LoadError:
sumber
Saya penggemar menggunakan permata rbx-membutuhkan-relatif ( sumber ). Awalnya ditulis untuk Rubinius, tetapi juga mendukung MRI 1.8.7 dan tidak melakukan apa pun di 1.9.2. Membutuhkan permata itu sederhana, dan saya tidak perlu membuang potongan kode ke proyek saya.
Tambahkan ke Gemfile Anda:
Lalu
require 'require_relative'
sebelum Andarequire_relative
.Misalnya, salah satu file pengujian saya terlihat seperti ini:
Ini adalah solusi terbersih dari semua IMO ini, dan permata itu tidak seberat backports.
sumber
The
backports
permata sekarang memungkinkan pemuatan individu backports.Anda kemudian dapat dengan mudah:
Ini
require
tidak akan memengaruhi versi yang lebih baru, juga tidak akan memperbarui metode bawaan lainnya.sumber
Pilihan lain adalah memberi tahu penerjemah jalur mana yang harus dicari
sumber
Satu masalah yang belum saya lihat ditunjukkan dengan solusi berdasarkan __FILE__ adalah bahwa mereka putus berkaitan dengan symlinks. Misalnya katakan saya punya:
Script utama, titik masuk, aplikasi adalah foo.rb. File ini ditautkan ke ~ / Scripts / foo yang ada di $ PATH saya. Pernyataan persyaratan ini rusak ketika saya menjalankan 'foo':
Karena __FILE__ adalah ~ / Scripts / foo sehingga pernyataan yang diperlukan di atas mencari ~ / Scripts / foo / lib / someinclude.rb yang jelas tidak ada. Solusinya sederhana. Jika __FILE__ adalah tautan simbolik, tautan tersebut perlu ditinjau ulang. Pathname # realpath akan membantu kami dengan situasi ini:
sumber
Jika Anda sedang membangun permata, Anda tidak ingin mencemari jalur muatan.
Tetapi, dalam kasus aplikasi mandiri, sangat mudah untuk hanya menambahkan direktori saat ini ke path load seperti yang Anda lakukan dalam 2 contoh pertama.
Pilihan saya masuk ke opsi pertama dalam daftar.
Saya ingin melihat beberapa literatur praktik terbaik Ruby yang solid.
sumber
Saya akan mendefinisikan sendiri
relative_require
jika tidak ada (yaitu di bawah 1,8) dan kemudian menggunakan sintaks yang sama di mana-mana.sumber
Cara Ruby on Rails:
sumber