2016-01-21 2 views
0

Я пишу вспомогательный метод для преобразования изображений в base64 строки, когда это необходимо. Ниже приведен кодКак передать файл url методу helper в middleman

# config.rb 
    helpers do 
    def base64_url(img_link, file_type: "jpg") 
     require "base64" 
     if file_type =="jpg" 
     "data:image/jpg;base64,#{Base64.encode64(open(img_link).to_a.join)}" 
     elsif file_type =="png" 
     "data:image/jpg;base64,#{Base64.encode64(open(img_link).to_a.join)}" 
     else 
     link 
     end 
    end 
    end 

В page.html.erb

<%= image_tag base64_url('/images/balcozy-logo.jpg') %>

Теперь проблема когда рубин читает '/images/balcozy-logo.jpg' считывает файл из корневой системы не от корня проекта.

Сообщение об ошибке следующего

Errno::ENOENT at/
No such file or directory @ rb_sysopen - /images/balcozy-logo.jpg 

Как обойти это и передать правильное изображение из URL project_root/source/images

+0

Знаете ли вы, что у вас есть данные: image/jpg в обеих ветвях вашего 'if'? –

ответ

1

В Посредник app.root возвращает корневой каталог приложения. Там также app.root_path, который делает то же самое, но возвращает Pathname объект, который является немного более удобным:

full_path = app.root_path.join("source", img_link.gsub(/^\//, '')) 

gsub необходимо, если img_link начинается с /, так как это будет истолковано как корень вашей файловой системы.

Я взял на себя смелость сделать еще несколько изменений к вашему методу:

require "base64" 

helpers do 
    def base64_url(path, file_type: "jpg") 
    return path unless ["jpg", "png"].include?(file_type) 

    full_path = app.root_path.join("source", path.gsub(/^\//, '')) 

    data_encoded = File.open(full_path, 'r') do |file| 
     Base64.urlsafe_encode64(file.read) 
    end 

    "data:image/#{file_type};base64,#{data_encoded}" 
    end 
end 

я сделал несколько вещей здесь:

  1. Переехал require "base64" в верхней части файл; он не принадлежит внутри метода.

  2. Отметьте file_type в самом начале метода и верните его раньше, если он не относится к перечисленным типам.

  3. Вместо open(filename).to_a.join (или более краткий open(filename).read), используйте File.open. OpenURI (который поставляет метод open, который вы использовали) является излишним для чтения из локальной файловой системы.

  4. Использовать Base64.urlsafe_encode64 вместо encode64. Наверное, не нужно, но это не больно.

  5. Удалить ненужные if; поскольку мы знаем, что file_type будет либо jpg, либо png, мы можем использовать его непосредственно в URI данных.

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

+0

Спасибо за тонну за усилия, которые вы вложили в это. Мне пришлось изменить две вещи, чтобы заставить ее работать. Путь full_path пропускает исходный каталог, поэтому он не находит файл. Поэтому я пробовал этот путь «full_path = app.root_path +» # {: source} »+.gsub (/^\ //, '') 'и это сработало. По какой-то причине 'urlsafe_encode64 (file.read)' encode не работает, поэтому просто пошел с 'encode64 (file.read)' Теперь он работает отлично. Также проверено с png, все отлично. Еще раз спасибо :) –

+0

Отмечено как принятый ответ, пожалуйста, обновите код для тех, кто придет позже. Я мог бы сделать это, но я хотел бы, чтобы вы сделали почести :) –

+1

': source' - это просто символ, который является особым видом строки в Ruby, поэтому' '# {: source}" 'равнозначен to ': source.to_s', который является просто« источником ». Я обновил свой ответ, чтобы использовать 'app.root_path.join (« source », path.gsub (...))' вместо 'app.root_path + path.gsub (...)'. –