Как определить, вызывается ли код ruby ​​через Ruby on Rails - PullRequest
0 голосов
/ 01 ноября 2018

Я написал небольшой инструмент .rb, который использовал "blank?" метод. Я хочу, чтобы моя программа продолжала работать, если вызывается напрямую через ruby. Я Monkey Patched Object с кодом ниже, но я не хочу Monkey Patched при работе под Rails. Что я могу сделать?

class Object
  def blank?
    respond_to?(:empty?) ? (respond_to?(:strip) ? strip.empty? : !!empty?) : !self
  end
end

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

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

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

Это также позволяет условно включать миксин. Например, общее требование в Ruby Gems состоит в том, чтобы реализовывать или определять что-то, только если другая библиотека уже загружена. Обычный способ сделать это - проверить, определена ли константа из этой библиотеки. Например, в вашем случае вы можете сделать это:

module PresenceExtensions
  def blank?
    respond_to?(:empty?) ? (respond_to?(:strip) ? strip.empty? : !!empty?) : !self
  end
end

unless Module.const_defined?("Rails") || Object.method_defined?(:blank?)
  Object.include PresenceExtensions
end

Другая распространенная техника - попытаться загрузить драгоценный камень, а затем добавить альтернативный патч обезьяны, только если драгоценный камень недоступен:

begin
  require "active_support/core_ext/object/blank"
rescue LoadError
  Object.include PresenceExtensions
end

Преимущество этого метода заключается в том, что он немедленно сообщит вам, если камень недоступен, так что вам не придется беспокоиться о порядке загрузки.

0 голосов
/ 01 ноября 2018

Rails по умолчанию не должен загружать файл во время выполнения, если не ожидается, что он будет через какую-то конфигурацию либо по умолчанию, либо через инициализатор и т. Д. Если это определение класса просто находится внутри вашего lib/monkey.rb, например, Rails не будет автоматически - загрузи, если не скажешь

Вы можете проверить это в консоли rails, если вы используете pry.

Просто сделай:

rails c
# inside your console:
show-method Object.blank?
# this should show you the actual method definition which should be somthing
# like:
From: /Users/myself/.rvm/gems/ruby-2.5.1/gems/activesupport-4.2.10/lib/active_support/core_ext/object/blank.rb @ line 16:
Owner: Object
Visibility: public
Number of lines: 3

def blank?
  respond_to?(:empty?) ? !!empty? : !self
end

Но если бы rails загрузил ваш lib-файл, вы бы увидели вместо этого определение, которое вы можете ввести в консоли с помощью require

require './lib/monkey.rb'
show-method Object.blank?

From: /Users/myself/some/rails/project/lib/monkey.rb @ line 2:
Owner: Object
Visibility: public
Number of lines: 4

def blank?
  puts "this is a monkey patch"
  respond_to?(:empty?) ? (respond_to?(:strip) ? strip.empty? : !!empty?) : !self
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...