allow content entry file field type to access the size of the file + new liquid filter: human_size to format nicely the size of a file for instance

did committed Feb 18, 2016
commit 0db5573cdf5c44edd279c6ef7aba4b6b2c4084d7
Showing 14 changed files with 139 additions and 33 deletions
locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb b/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb +22 -0
@@ @@ -22,6 +22,7 @@ module Locomotive
modify_for_selects(_attributes)
modify_for_associations(_attributes)
+ modify_for_files(_attributes)
list << _attributes
end
@@ @@ -34,6 +35,27 @@ module Locomotive
end
end
+ def modify_for_files(attributes)
+ content_type.file_fields.each do |field|
+ attributes[:"#{field.name}_size"] ||= {}
+ value = attributes[:"#{field.name}_size"]
+
+ if (path = attributes[field.name.to_sym]).is_a?(Hash)
+ path.each { |locale, path| value[locale.to_s] = file_size(path) }
+ else
+ value['default'] = file_size(path)
+ end
+ end
+ end
+
+ def file_size(path)
+ return nil if path.blank?
+
+ _path = File.join(site_path, 'public', path)
+
+ File.exists?(_path) ? File.size(_path) : nil
+ end
+
def modify_for_associations(attributes)
content_type.association_fields.each do |field|
case field.type
locomotive/steam/entities/content_entry.rb b/lib/locomotive/steam/entities/content_entry.rb +8 -3
@@ @@ -129,8 +129,13 @@ module Locomotive::Steam
end
def _cast_file(field)
- _cast_convertor(field.name) do |value|
- value.respond_to?(:url) ? value : FileField.new(value, self.base_url, self.updated_at)
+ _cast_convertor(field.name) do |value, locale|
+ if value.respond_to?(:url)
+ value
+ else
+ size = (self[:"#{field.name}_size"] || {})[locale || 'default']
+ FileField.new(value, self.base_url, size, self.updated_at)
+ end
end
end
@@ @@ -172,7 +177,7 @@ module Locomotive::Steam
# Represent a file
class FileField
- attr_accessor_initialize :filename, :base, :updated_at
+ attr_accessor_initialize :filename, :base, :size, :updated_at
def url
return if filename.blank?
locomotive/steam/entities/content_type.rb b/lib/locomotive/steam/entities/content_type.rb +1 -0
@@ @@ -7,6 +7,7 @@ module Locomotive::Steam
def_delegator :fields, :associations, :association_fields
def_delegator :fields, :selects, :select_fields
+ def_delegator :fields, :files, :file_fields
def_delegator :fields, :default, :fields_with_default
def initialize(attributes = {})
locomotive/steam/liquid/drops/upload_file.rb b/lib/locomotive/steam/liquid/drops/upload_file.rb +0 -23
@@ @@ -1,23 +0,0 @@
- module Locomotive
- module Steam
- module Liquid
- module Drops
- class UploadedFile < Base
-
- delegate :size, :filename, to: :@_source
-
- def url
- asset_host.compute(@_source.url, @_source.updated_at.try(:to_i))
- end
-
- private
-
- def asset_host
- @context.registers[:services].asset_host
- end
-
- end
- end
- end
- end
- end
locomotive/steam/liquid/drops/uploaded_file.rb b/lib/locomotive/steam/liquid/drops/uploaded_file.rb +23 -0
@@ @@ -0,0 +1,23 @@
+ module Locomotive
+ module Steam
+ module Liquid
+ module Drops
+ class UploadedFile < Base
+
+ delegate :size, :filename, to: :@_source
+
+ def url
+ asset_host.compute(@_source.url, @_source.updated_at.try(:to_i))
+ end
+
+ private
+
+ def asset_host
+ @context.registers[:services].asset_host
+ end
+
+ end
+ end
+ end
+ end
+ end
locomotive/steam/liquid/filters/number.rb b/lib/locomotive/steam/liquid/filters/number.rb +4 -0
@@ @@ -12,6 +12,10 @@ module Locomotive
NumberProxyHelper.new(:percentage, @context).invoke(input, options)
end
+ def human_size(input, *options)
+ NumberProxyHelper.new(:human_size, @context).invoke(input, options)
+ end
+
def mod(input, modulus)
input.to_i % modulus.to_i
end
locomotive/steam/models/i18n_field.rb b/lib/locomotive/steam/models/i18n_field.rb +3 -1
@@ @@ -43,7 +43,9 @@ module Locomotive::Steam
if default
@translations = Hash.new(yield(default))
else
- each { |l, _value| self[l] = yield(_value) }
+ each do |l, _value|
+ self[l] = block.arity == 2 ? yield(_value, l) : yield(_value)
+ end
end
self
end
locomotive/steam/repositories/content_type_field_repository.rb b/lib/locomotive/steam/repositories/content_type_field_repository.rb +4 -0
@@ @@ -22,6 +22,10 @@ module Locomotive
query { where(type: :select) }.all
end
+ def files
+ query { where(type: :file) }.all
+ end
+
def belongs_to
query { where(type: :belongs_to) }.all
end
spec/fixtures/default/data/songs.yml +4 -2
@@ @@ -8,7 +8,9 @@
duration: "6:28"
short_description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vitae tincidunt urna. Nunc felis purus, ultricies et venenatis bibendum, fringilla eu lectus. Sed cursus, sem at blandit mattis, libero quam egestas tortor, eget cursus dolor tellus id nunc.
audio_url: http://blip.tv/file/get/NicolasRaynier-Milk617.flv
- cover: /samples/asset_collections/cover.jpg
+ cover:
+ en: /samples/asset_collections/cover.jpg
+ fr: /samples/photo_2.jpg
band: pearl-jam
- "Song #3":
duration: "6:28"
@@ @@ -43,4 +45,4 @@
duration: "6:28"
short_description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur vitae tincidunt urna. Nunc felis purus, ultricies et venenatis bibendum, fringilla eu lectus. Sed cursus, sem at blandit mattis, libero quam egestas tortor, eget cursus dolor tellus id nunc.
audio_url: http://blip.tv/file/get/NicolasRaynier-Milk617.flv
- cover: /samples/asset_collections/cover.jpg
\ No newline at end of file
+ cover: /samples/asset_collections/cover.jpg
spec/unit/adapters/filesystem/yaml_loaders/content_entry_spec.rb +19 -3
@@ @@ -6,7 +6,7 @@ require_relative '../../../../../lib/locomotive/steam/adapters/filesystem/yaml_l
describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::ContentEntry do
let(:site_path) { default_fixture_site_path }
- let(:content_type) { instance_double('Bands', _id: 42, slug: 'bands', association_fields: [], select_fields: []) }
+ let(:content_type) { instance_double('Bands', _id: 42, slug: 'bands', association_fields: [], select_fields: [], file_fields: []) }
let(:scope) { instance_double('Scope', locale: :en, context: { content_type: content_type }) }
let(:loader) { described_class.new(site_path) }
@@ @@ -23,7 +23,7 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::ContentEntry do
context 'a content type with a belongs_to field' do
let(:field) { instance_double('Field', name: 'band', type: :belongs_to) }
- let(:content_type) { instance_double('Songs', slug: 'songs', association_fields: [field], select_fields: []) }
+ let(:content_type) { instance_double('Songs', slug: 'songs', association_fields: [field], select_fields: [], file_fields: []) }
it 'adds a new attribute for the foreign key' do
expect(subject.first[:band_id]).to eq 'pearl-jam'
@@ @@ -36,7 +36,7 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::ContentEntry do
context 'a content type with a select field' do
let(:field) { instance_double('Field', name: 'kind', type: :select) }
- let(:content_type) { instance_double('Bands', slug: 'bands', select_fields: [field], association_fields: []) }
+ let(:content_type) { instance_double('Bands', slug: 'bands', select_fields: [field], association_fields: [], file_fields: []) }
it 'adds a new attribute for the foreign key' do
expect(subject.first[:kind_id]).to eq 'grunge'
@@ @@ -45,6 +45,22 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::ContentEntry do
end
+ context 'a content type with a file field' do
+
+ let(:field) { instance_double('Field', name: 'cover', type: :file) }
+ let(:content_type) { instance_double('Songs', slug: 'songs', select_fields: [], association_fields: [], file_fields: [field]) }
+
+ it 'stores the size of the file' do
+ expect(subject.first[:cover_size]).to eq('default' => 14768)
+ end
+
+ it 'stores the size of the file in multiple locales' do
+ expect(subject[1][:cover_size]).to eq('en' => 14768, 'fr' => 165883)
+ end
+
+
+ end
+
end
end
spec/unit/entities/content_entry_spec.rb +9 -0
@@ @@ -169,11 +169,20 @@ describe Locomotive::Steam::ContentEntry do
context 'a file' do
let(:field_type) { :file }
let(:value) { '/foo.png' }
+ let(:attributes) { { my_field: value, my_field_size: { 'default' => 42 } } }
it { expect(subject.url).to eq('/foo.png') }
+ it { expect(subject.size).to eq(42) }
context 'localized' do
let(:value) { build_i18n_field(en: '/foo-en.png', fr: '/foo-fr.png') }
+ let(:attributes) { { my_field: value, my_field_size: { 'en' => 42, 'fr' => 7 } } }
it { expect(subject.translations[:en].url).to eq('/foo-en.png') }
+ it { expect(subject.translations[:en].size).to eq(42) }
it { expect(subject.translations[:fr].url).to eq('/foo-fr.png') }
+ it { expect(subject.translations[:fr].size).to eq(7) }
+ end
+ context 'no file size provided' do
+ let(:attributes) { { my_field: value } }
+ it { expect(subject.size).to eq(nil) }
end
end
spec/unit/liquid/drops/content_entry_spec.rb +1 -1
@@ @@ -101,7 +101,7 @@ describe Locomotive::Steam::Liquid::Drops::ContentEntry do
describe '#as_json' do
let(:type) { instance_double('Type', fields_by_name: { title: instance_double('StringField', type: :string ), picture: instance_double('FileField', type: :file), category: instance_double('SelectField', type: :select) }) }
- let(:picture_field) { Locomotive::Steam::ContentEntry::FileField.new('foo.png', 'http://assets.dev', 42) }
+ let(:picture_field) { Locomotive::Steam::ContentEntry::FileField.new('foo.png', 'http://assets.dev', 0, 42) }
before do
allow(entry).to receive(:to_hash).and_return({ '_id' => 1, 'title' => 'Hello world', 'picture' => picture_field, 'category_id' => 42 })
spec/unit/liquid/filters/number_spec.rb +29 -0
@@ @@ -87,6 +87,35 @@ describe Locomotive::Steam::Liquid::Filters::Number do
end
+ describe '#human_size' do
+
+ subject { human_size(input, options) }
+
+ context 'not a number' do
+
+ it { expect(subject).to eq nil }
+
+ end
+
+ context 'a number' do
+
+ let(:input) { 1234567890 }
+
+ it { expect(subject).to eq '1.15 GB' }
+
+ end
+
+ context 'with options' do
+
+ let(:input) { '1234567' }
+ let(:options) { ['precision: 2'] }
+
+ it { expect(subject).to eq '1.2 MB' }
+
+ end
+
+ end
+
describe '#mod' do
it 'returns correct number modulus' do
spec/unit/repositories/content_type_field_repository_spec.rb +12 -0
@@ @@ -55,6 +55,18 @@ describe Locomotive::Steam::ContentTypeFieldRepository do
subject { repository.default }
it { expect(subject.first.name).to eq 'email' }
+ it { expect(subject.count).to eq 1 }
+
+ end
+
+ describe '#files' do
+
+ let(:collection) { [{ name: 'name', type: 'string' }, { name: 'picture', type: 'file' }] }
+
+ subject { repository.files }
+
+ it { expect(subject.first.name).to eq 'picture' }
+ it { expect(subject.count).to eq 1 }
end