Вот репозиторий, демонстрирующий использование пользовательского шрифта с Rails 5.2, который работает на Heroku. Это идет дальше и оптимизирует обслуживание шрифтов, чтобы быть максимально быстрым в соответствии с https://www.webpagetest.org/
https://github.com/nzoschke / edgecors
app/assets/fonts
@font-face
в файл scss и использовать font-url
помощник Из app/assets/stylesheets/welcome.scss
:
@font-face {
font-family: 'Inconsolata';
src: font-url('Inconsolata-Regular.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
body {
font-family: "Inconsolata";
font-weight: bold;
}
Я использую CloudFront, добавленный с Heroku Edge addon .
Если вы используете свой собственный CloudFront, не забудьте настроить его так, чтобы он перенаправлял заголовок браузера Origin
на исходный сервер.
Сначала настройте префикс CDN и заголовки Cache-Control
по умолчанию в production.rb
:
Rails.application.configure do
# e.g. https://d1unsc88mkka3m.cloudfront.net
config.action_controller.asset_host = ENV["EDGE_URL"]
config.public_file_server.headers = {
'Cache-Control' => 'public, max-age=31536000'
}
end
Если вы попытаетесь получить доступ к шрифту с URL-адреса herokuapp.com на URL-адрес CDN, вы получите Ошибка CORS в вашем браузере:
Доступ к шрифту в ' https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf ' from origin ' https://edgecors.herokuapp.com 'заблокировано политикой CORS: в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». edgecors.herokuapp.com/ GET https://d1unsc88mkka3m.cloudfront.net/assets/Inconsolata-Regular.ttf net :: ERR_FAILED
Поэтому настройте CORS, чтобы разрешить доступ к шрифт от Heroku к URL CDN:
module EdgeCors
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.2
config.middleware.insert_after ActionDispatch::Static, Rack::Deflater
config.middleware.insert_before 0, Rack::Cors do
allow do
origins %w[
http://edgecors.herokuapp.com
https://edgecors.herokuapp.com
]
resource "*", headers: :any, methods: [:get, :post, :options]
end
end
end
end
Конвейер ресурсов создает файл .ttf.gz
, но не обслуживает его. Этот патч обезьяны заменяет белый список gzip конвейера ресурсов на черный список:
require 'action_dispatch/middleware/static'
ActionDispatch::FileHandler.class_eval do
private
def gzip_file_path(path)
return false if ['image/png', 'image/jpeg', 'image/gif'].include? content_type(path)
gzip_path = "#{path}.gz"
if File.exist?(File.join(@root, ::Rack::Utils.unescape_path(gzip_path)))
gzip_path
else
false
end
end
end
Конечным результатом является файл нестандартного шрифта в app/assets/fonts
, который подается из долгоживущего кеша CloudFront.
I believe to check if a key exists in a hash you just do
if (exists $strings{$string}) {
...
} else {
...
}
Я бы посоветовал не использовать if ($ hash {$ key})
, поскольку он не будет делать то, что вы ожидаете, если ключ существует, но его значение равно нулю или пусто.
Что ж, весь ваш код может быть ограничен следующим:
foreach $line (@lines){
$strings{$1}++ if $line =~ m|my regex|;
}
Если значение отсутствует, оператор ++ примет его значение 0 (а затем увеличит его до 1). Если он уже есть - он просто будет увеличен.
I guess that this code should answer your question:
use strict;
use warnings;
my @keys = qw/one two three two/;
my %hash;
for my $key (@keys)
{
$hash{$key}++;
}
for my $key (keys %hash)
{
print "$key: ", $hash{$key}, "\n";
}
Output:
three: 1
one: 1
two: 2
The iteration can be simplified to:
$hash{$_}++ for (@keys);
(See $_
in perlvar.) And you can even write something like this:
$hash{$_}++ or print "Found new value: $_.\n" for (@keys);
Which reports each key the first time it’s found.