2016-08-14 5 views
0

Эта проблема возникает в генераторе Креветки PDF в моем приложении Rails, где у меня есть следующие строки:Почему конвейер Carrierwave и конвейер активов интерпретируются как config.asset_host иначе?

image open(@user.avatar.url) 

В тестах эта линия началась неудачу со следующей ошибкой:

No such file or directory @ rb_sysopen - /images/fallback/default.png 

Аватар является Carrierwave загрузчик с изображением по умолчанию (see here)

def default_url(*args) 
    ActionController::Base.helpers.asset_path("images/fallback/default.png") 
end 

Это казалось, что это было бы легко исправить - определить актив Хост в test.rb

config.asset_host = Rails.root.join('app', 'assets').to_s 

, но тогда все мои JS включен тесты функция начала неудачу

Capybara::Poltergeist::JavascriptError: 
One or more errors were raised in the Javascript code on the page. 
ReferenceError: Can't find variable: SomeVariable 

, так как пути строятся с двумя assets, например,

...app/assets/assets/jquery..

Я явно что-то делать «нетрадиционную», что идет вразрез с образом Rails делать вещи. Поэтому мне интересно, что такое конвенция.

Одним из решений было бы перемещение, где я определяю папку с ресурсами из test.rb загрузчику.

#config/environments/test.rb 
config.asset_host = Rails.root.join('app').to_s 
#app/uploaders/avatar.eb 
def default_url(*args) 
    ActionController::Base.helpers.asset_path("assets/images/fallback/default.png") 
end 

, но это означало бы, что helpers.asset_path в действительности не вызывающему путь активов, но в папку приложения, которое снова, кажется, идти против Rails конвенции.

Я думал, что будет работать локальный

config.asset_host = "http://localhost" 

но снова JS файлы неисправного

Я уверен, что я что-то очевидное здесь с видом. Благодарен за указатели в правильном направлении.

ответ

1

Я думаю, что это сводится к смешиванию различных значений пути и URL.

Прежде всего asset_host используется, когда вы хотите обслуживать свои файлы активов с другого сервера в своем приложении (т. Е. Из cdn). Если вы посмотрите на источник на asset_path, то рельсы сначала вычисляют путь к активу, а затем добавляют хозяина. Это создает URL, который браузер будет позже попытаться принести, так предваряя путь как /Users/andy/some_app не имеет смысла

Установка в http://localhost не работает, потому что предполагается, порт по умолчанию HTTP, в то время как капибара запускает приложение на случайный порт. Вам не нужно устанавливать asset_host в тестовую среду.

Переход на несущую волну, avatar.url также предоставляет URL-адрес (в вашем случае только часть пути) с точки зрения браузера - он предназначен для встраивания в тег img, например. С другой стороны, метод open ничего не знает о браузерах и серверах и просто хочет получить путь к файлу в локальной файловой системе.

Если вам нужен путь к локальной файловой системе, вам нужен метод avatar.path. Насколько я знаю, нет никакого эквивалента default_url для пути, так что вы должны быть готовы для того, чтобы вернуть ноль (и заменить его на пути к вашей запасной вариант вместо)

#config/environments/test.rb 
# do not set config.asset_host 

#pdf_generator.rb 
image open(@user.avatar.path) 

#app/uploaders/avatar.rb 
def path(*args) 
    if model.avatar? 
    super 
    else 
    "#{Rails.root}/app/assets/images/fallback/" + ["default_",version_name, ".png"].compact.join('') 
    end 
end 
+0

благодаря @frederick, это хорошее объяснение и устраняет множество вопросов. Но 'avatar.path' по существу возвращает то же самое, что и' avatar.url' без хоста, правильно? В этом случае '/ images/fallback/default.png', что в любом случае возвращает' avatar.url' в моих тестах и ​​не подходит для метода 'open'. Должен ли 'open' отвечать на' avatar.path'? –

+0

Сравните значения и посмотрите, что они возвращают - не должно быть одно и то же. Кроме того, резервное изображение представляет собой немного особый случай - путь i вещи просто вернет нуль. –

+0

Правильно, с возвратом возвращается 'nil'. Если изображение установлено, 'avatar.path' возвращает' avatars/filename.jpg', тогда как 'avatar.url' возвращает' http: // путь/в/app/avatars/filename.jpg'. Поэтому мне нужен метод, который: 'if avatar.path.nil?' Возвращает '/ app/assets/images/fallback/default.png'. Или я не понимаю? –

Смежные вопросы