конфликтующие рубиновые камни - PullRequest
7 голосов
/ 21 декабря 2010

Мне нужно использовать два драгоценных камня в моем проекте, которые оба требуют пространства имен PDF: pdf-reader и htmldoc.

Есть ли способ заставить их хорошо играть вместе? Единственный способ, которым я могу придумать, - переписать мою собственную версию htmldoc, чтобы дать ей другое пространство имен.

Ответы [ 4 ]

5 голосов
/ 21 декабря 2010

В принципе, вы ничего не можете сделать. В Ruby рекомендуется использовать отличительные имена в пространстве имен верхнего уровня точно по этой причине, и вы случайно наткнулись на две библиотеки, которые нарушают эту практику.

Одна вещь, которую вы могли бы сделать, это использовать Kernel#load вместо Kernel#require. Kernel#load принимает необязательный логический аргумент, который скажет ему оценить файл в анонимном модуле. Обратите внимание, однако, что это ни в коем случае не безопасно: вполне возможно явно поместить материал в пространство имен верхнего уровня (используя что-то вроде module ::PDF) и, таким образом, вырваться из анонимного модуля.

Обратите внимание, что API действительно дрянной: load просто возвращает true или false, как require. (На самом деле, поскольку load всегда загружается, он всегда возвращает true.) На самом деле get в анонимном модуле невозможно. Вы в основном должны вытащить его из ObjectSpace вручную. О, и, конечно, поскольку на самом деле ничто не ссылается на анонимный модуль, он будет собирать мусор, так что вам не только нужно рыться в недрах ObjectSpace до найти модуля, вы также гонка сборщик мусора.

Иногда мне бы хотелось, чтобы у Ruby была подходящая система модулей, такая как Newspeak, Standard ML или Racket.

2 голосов
/ 21 декабря 2010

Вероятно, нет элегантного решения проблемы.Если вам действительно нужны два драгоценных камня, работающих бок о бок, я думаю, что ваш лучший вариант - раскошелиться на один из них (или, возможно, оба) и использовать ваш форк.Вот как я могу это сделать:

  • Если какой-либо гем находится на Github, то его разветвляют, или если оба находятся на Github, тот, который кажется наименее эффективным.
  • Если на Github нет ни одного драгоценного камня, посмотрите, сможете ли вы достать источник (возможно, вытащить его из драгоценного камня, но может оказаться полезным найти настоящий репозиторий, поскольку там могут быть другие файлы, которые не включены вдрагоценный камень), и поместите его в хранилище на Github.Убедитесь, что лицензия gem позволяет это (что почти наверняка делает, если это одна из распространенных лицензий с открытым исходным кодом).
  • Внесите изменения.
  • Убедитесь, что в файле .gemspecв корне хранилища, следующий шаг не будет работать в противном случае.
  • Используйте Bundler для управления зависимостями ваших проектов.Вместо указания зависимости от библиотеки, которую вы изменили как

    gem 'the_gem'
    

    , укажите ее следующим образом:

    gem 'the_gem', :git => 'git://github.com/you/the_gem.git'
    

    (но измените URL-адрес хранилища на действительный)

  • Отправьте электронное письмо сопровождающему модифицированного вами камня и попросите его или ее рассмотреть возможность объединения ваших изменений в следующем выпуске.

Bundler позволяет легко использовать альтернативные версии драгоценных камней с минимальными хлопотами.Я часто разветвляю гемы, исправляю ошибки или добавляю функции, меняю свой Gemfile, чтобы он указывал на мою версию, а затем прошу сопровождающего включить мои изменения.Когда или если это произойдет, я просто изменю свой Gemfile обратно, чтобы просто сослаться на официальную версию драгоценного камня.

Альтернативная стратегия, если сопровождающий не хочет объединять ваши изменения и вы хотитераспространять вашу версию среди других - значит выдвинуть вашу версию в Rubygems в качестве нового гема, но в этом случае перед именем гема добавьте ваше имя или некоторую другую строку, которая идентифицирует ваш гем как вариант.

0 голосов
/ 19 мая 2016

Я ответил на это по ссылке https://stackoverflow.com/a/37311072/292780

С уважением не согласен с ответом выше.Вот как я это делаю:

ruby -S gem list my_gem

`*** LOCAL GEMS ***
my_gem (1.0.1, 1.0.0, 0.0.2)
`

ruby -S gem lock my_gem-1.0.0 > locklist.rb

, который создает список зависимостей для конкретной версии в locklist

require 'rubygems'
gem 'my_gem', '= 1.0.0'
gem 'gem_base', '= 1.0.0'
gem 'rest-client', '= 1.7.2'
gem 'savon', '= 1.1.0'
gem 'addressable', '= 2.3.6'
gem 'mime-types', '= 1.25.1'
gem 'netrc', '= 0.11.0'

теперь вы можете сделать load('locklist.rb'), который будет загружать конкретную версию драгоценного камня вместе с его зависимостями.Смотри, ма, не Бандлер.

0 голосов
/ 21 декабря 2010

Я слышал о новой функциональности под названием уточнения.Он предназначен для того, чтобы избежать двух разных патчей обезьян, влияющих на один и тот же класс, вызывающих проблемы, но я посмотрю, может ли это помочь с вашей проблемой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...