images_gallery 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/images_gallery/cli.rb +4 -4
  3. data/lib/images_gallery/generator.rb +5 -4
  4. data/lib/images_gallery/models/collection.rb +17 -0
  5. data/lib/images_gallery/models/image.rb +21 -0
  6. data/lib/images_gallery/models/source.rb +107 -0
  7. data/lib/images_gallery/version.rb +1 -1
  8. data/lib/images_gallery/views/base.rb +57 -0
  9. data/lib/images_gallery/views/index.rb +2 -2
  10. data/lib/images_gallery/views/make.rb +2 -2
  11. data/lib/images_gallery/views/model.rb +2 -2
  12. data/spec/lib/images_gallery/cli_spec.rb +3 -3
  13. data/spec/lib/images_gallery/{collection_spec.rb → models/collection_spec.rb} +2 -2
  14. data/spec/lib/images_gallery/{image_spec.rb → models/image_spec.rb} +2 -2
  15. data/spec/lib/images_gallery/{source_spec.rb → models/source_spec.rb} +2 -2
  16. data/spec/lib/images_gallery/{view_spec.rb → views/base_spec.rb} +2 -2
  17. data/spec/lib/images_gallery/views/index_spec.rb +1 -5
  18. data/spec/lib/images_gallery/views/make_spec.rb +1 -5
  19. data/spec/lib/images_gallery/views/model_spec.rb +1 -5
  20. data/spec/support/helpers.rb +7 -0
  21. data/spec/tmp/canon/canon_eos_20d.html +1 -0
  22. data/spec/tmp/canon/canon_eos_400d_digital.html +1 -0
  23. data/spec/tmp/canon.html +1 -0
  24. data/spec/tmp/fuji_photo_film_co_ltd/slp1000se.html +1 -0
  25. data/spec/tmp/fuji_photo_film_co_ltd.html +1 -0
  26. data/spec/tmp/fujifilm/finepix_s6500fd.html +1 -0
  27. data/spec/tmp/fujifilm.html +1 -0
  28. data/spec/tmp/index.html +1 -0
  29. data/spec/tmp/leica/d_lux_3.html +1 -0
  30. data/spec/tmp/leica.html +1 -0
  31. data/spec/tmp/nikon_corporation/nikon_d80.html +1 -0
  32. data/spec/tmp/nikon_corporation.html +1 -0
  33. data/spec/tmp/panasonic/dmc_fz30.html +1 -0
  34. data/spec/tmp/panasonic.html +1 -0
  35. data/spec/tmp/unknown_make/unknown_model.html +1 -0
  36. data/spec/tmp/unknown_make.html +1 -0
  37. metadata +14 -14
  38. data/lib/images_gallery/collection.rb +0 -15
  39. data/lib/images_gallery/image.rb +0 -19
  40. data/lib/images_gallery/source.rb +0 -104
  41. data/lib/images_gallery/view.rb +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6776c25e3826043bb0f8a6b2fd9264670288ffec
4
- data.tar.gz: 9a89ef53659d2fbaeb782345752432db6995519a
3
+ metadata.gz: 67e420173590772158f6bab51506ccd9a836fe5c
4
+ data.tar.gz: d53ff9a4c056c12d17d31396b8325841ad16111e
5
5
  SHA512:
6
- metadata.gz: e9e1951ea8e2bfcbe22142fc19cb514150aa1f1e6532583e8b401aaf9966075c76f284727d14d9906ca65ea8cb63b78b7d34f98aa744cc849486966e044cb500
7
- data.tar.gz: c6f5e80500100a94b18050ff6a5d0ad841ec5f97df50cfc618d11a0af91ca148543a42fe7eac6800cdd405dd54eb662ac72498668b1ef9b4f725de6c9212facf
6
+ metadata.gz: 74de38ecf7c3ab952260a7403218354f05eccb271310f77b05872a83b1aa89555c91a6092f3b99bbaf2c6e90dd19ef6f0f2aa459773ea968fba535f3f607175e
7
+ data.tar.gz: 01e3e36847c68a09f17f8892c793898788b28087f0e2933e2ac1ec41d3aa66dd17875b5166bff707c6df2993633e56e56c30c339479821e6cfcda42579995480
@@ -6,15 +6,15 @@ module ImagesGallery
6
6
  class CLI < Thor
7
7
 
8
8
  desc 'generate SOURCE TARGET', 'Generate a static HTML images gallery in the TARGET directory from the SOURCE file contents.'
9
- def generate(source, target=nil, error=STDERR, out=STDOUT)
9
+ def generate(source, target, error=STDERR, out=STDOUT)
10
10
  begin
11
11
  out.puts generator.run(source, target)
12
12
  rescue ImagesGallery::SourceFileNotFoundError
13
- error.puts 'Please make sure the specified source file exists.'
13
+ error.puts 'ERROR: Please make sure the specified source file exists.'
14
14
  rescue ImagesGallery::TargetDirectoryNotFoundError
15
- error.puts 'Please make sure the specified target directory exists.'
15
+ error.puts 'ERROR: Please make sure the specified target directory exists.'
16
16
  rescue ImagesGallery::SourceFileInvalidError
17
- error.puts 'The source file is invalid. Please check it is well-formed XML.'
17
+ error.puts 'ERROR: The source file is invalid. Please check it is well-formed XML.'
18
18
  end
19
19
  end
20
20
 
@@ -1,5 +1,6 @@
1
1
  require 'images_gallery/errors'
2
- require 'images_gallery/source'
2
+ require 'images_gallery/models/collection'
3
+ require 'images_gallery/models/source'
3
4
  require 'images_gallery/views/index'
4
5
  require 'images_gallery/views/make'
5
6
  require 'images_gallery/views/model'
@@ -15,7 +16,7 @@ module ImagesGallery
15
16
  raise SourceFileNotFoundError unless File.file? source
16
17
  raise TargetDirectoryNotFoundError unless File.directory? target
17
18
 
18
- @source = Source.new(source)
19
+ @source = Models::Source.new(source)
19
20
  @target = target
20
21
 
21
22
  @source.parse
@@ -31,14 +32,14 @@ module ImagesGallery
31
32
  files['index'] = Views::Index.new(images).render
32
33
 
33
34
  images.makes.each do |make|
34
- images_by_make = Collection.new
35
+ images_by_make = Models::Collection.new
35
36
  images.select{ |image| image.make == make }.each do |image|
36
37
  images_by_make << image
37
38
  view = Views::Make.new(images_by_make)
38
39
  files[view.file_identifier(image.make)] = view.render
39
40
 
40
41
  images_by_make.models.each do |model|
41
- images_by_model = Collection.new
42
+ images_by_model = Models::Collection.new
42
43
  images_by_make.select{ |image| image.model == model }.each do |image|
43
44
  images_by_model << image
44
45
  view = Views::Model.new(images_by_model)
@@ -0,0 +1,17 @@
1
+ require 'images_gallery/models/image'
2
+
3
+ module ImagesGallery
4
+ module Models
5
+ class Collection < Array
6
+
7
+ def makes
8
+ map { |image| image.make }.uniq.sort
9
+ end
10
+
11
+ def models
12
+ map { |image| image.model }.uniq.sort
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module ImagesGallery
2
+ module Models
3
+ class Image
4
+
5
+ attr_accessor :id, :src, :make, :model
6
+
7
+ def make
8
+ @make || 'Unknown Make'
9
+ end
10
+
11
+ def model
12
+ @model || 'Unknown Model'
13
+ end
14
+
15
+ def description
16
+ "Image #{@id}"
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,107 @@
1
+ require 'libxml'
2
+
3
+ require 'images_gallery/models/collection'
4
+ require 'images_gallery/models/image'
5
+
6
+ module ImagesGallery
7
+ module Models
8
+ class Source
9
+
10
+ include LibXML
11
+ include XML::SaxParser::Callbacks
12
+
13
+ attr_reader :images
14
+
15
+ # Provides a collection of images to presenters
16
+ #
17
+ # Extracts some images attributes from an XML collection of works
18
+ # and collects the images as plain Ruby objects so other classes
19
+ # can use them with presentational purpose.
20
+ #
21
+ # This class should be able to parse efficiently large XML files.
22
+ #
23
+ # file - Path to an XML representation of the images (metadata, EXIF)
24
+ #
25
+ # Example:
26
+ #
27
+ # source = ImagesGallery::Source.new('path/to/source.xml')
28
+ # source.parse # creates a Collection of Images
29
+ # source.images # is available after parsing
30
+ #
31
+ # Returns a Source object, ready to parse the corresponding XML file.
32
+ def initialize(file)
33
+ @file = XML::SaxParser.file(file)
34
+ @file.callbacks = self
35
+ end
36
+
37
+ def parse
38
+ @images = Models::Collection.new
39
+ begin
40
+ @file.parse
41
+ rescue LibXML::XML::Error
42
+ raise SourceFileInvalidError
43
+ end
44
+ end
45
+
46
+ # Callbacks can't be private, yet they are not part of the public API.
47
+
48
+ def on_start_element(element, attributes)
49
+ @current_element = element
50
+
51
+ if element == 'work'
52
+ @current_image = Models::Image.new
53
+ end
54
+
55
+ if element == 'url' && attributes['type'] == 'small'
56
+ @current_element = 'thumbnail URL'
57
+ end
58
+ end
59
+
60
+ def on_end_element(element)
61
+ if element == 'work'
62
+ @images << @current_image
63
+ end
64
+
65
+ if element == 'id'
66
+ @current_image.id = @current_id
67
+ end
68
+
69
+ if element == 'make'
70
+ @current_image.make = @current_make
71
+ end
72
+
73
+ if element == 'model'
74
+ @current_image.model = @current_model
75
+ end
76
+
77
+ if @current_element == 'thumbnail URL'
78
+ @current_image.src = @current_src
79
+ end
80
+
81
+ @current_element = nil
82
+ end
83
+
84
+ def on_characters(char)
85
+ if @current_element == 'id'
86
+ @current_id = char
87
+ end
88
+
89
+ if @current_element == 'make'
90
+ @current_make = char
91
+ end
92
+
93
+ if @current_element == 'model'
94
+ @current_model = char
95
+ end
96
+
97
+ if @current_element == 'thumbnail URL'
98
+ @current_src = char
99
+ end
100
+ end
101
+
102
+ def on_end_document
103
+ @current_element = nil
104
+ end
105
+ end
106
+ end
107
+ end
@@ -1,3 +1,3 @@
1
1
  module ImagesGallery
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.1'
3
3
  end
@@ -0,0 +1,57 @@
1
+ require 'erb'
2
+
3
+ module ImagesGallery
4
+ module Views
5
+ class Base
6
+
7
+ # Provides context and helpers to the corresponding template
8
+ #
9
+ # Any variable defined in the context of this class will be accessible
10
+ # from the corresponding ERb template.
11
+ # See http://ruby-doc.org/stdlib-2.2.2/libdoc/erb/rdoc/ERB.html#method-i-result
12
+ #
13
+ # Usage:
14
+ #
15
+ # Do not instanciate this class, define subclasses instead an define their
16
+ # template methods as demonstrated in Views::Index.
17
+ #
18
+ # Conventionally, templates could be stored in images_gallery/templates, but
19
+ # there is no obligation to follow the convention.
20
+ #
21
+ # This class not meant to be instanciated, subclasses do return View instances (kind of).
22
+ def initialize
23
+ @template = File.new(template)
24
+ end
25
+
26
+ def template
27
+ raise NotImplementedError
28
+ end
29
+
30
+ def render
31
+ ERB.new(File.new(template).read).result(binding)
32
+ end
33
+
34
+ def thumbnails(images)
35
+ template = File.expand_path('../../templates/_thumbnails.html.erb', __FILE__)
36
+ ERB.new(File.new(template).read).result(binding)
37
+ end
38
+
39
+ def navigation(links)
40
+ template = File.expand_path('../../templates/_navigation.html.erb', __FILE__)
41
+ ERB.new(File.new(template).read).result(binding)
42
+ end
43
+
44
+ def link_to(depth, make, model=nil)
45
+ ('../' * depth) + file_identifier(make, model) + '.html'
46
+ end
47
+
48
+ def file_identifier(make, model=nil)
49
+ if model.nil?
50
+ "#{make.to_filename}"
51
+ else
52
+ "#{make.to_filename}/#{model.to_filename}"
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,10 +1,10 @@
1
1
  require 'erb'
2
2
 
3
- require 'images_gallery/view'
3
+ require 'images_gallery/views/base'
4
4
 
5
5
  module ImagesGallery
6
6
  module Views
7
- class Index < ImagesGallery::View
7
+ class Index < Base
8
8
 
9
9
  attr_reader :depth, :links, :sample_images, :title
10
10
  private :depth, :links, :sample_images, :title
@@ -1,10 +1,10 @@
1
1
  require 'erb'
2
2
 
3
- require 'images_gallery/view'
3
+ require 'images_gallery/views/base'
4
4
 
5
5
  module ImagesGallery
6
6
  module Views
7
- class Make < ImagesGallery::View
7
+ class Make < Base
8
8
 
9
9
  attr_reader :depth, :links, :make, :sample_images, :title
10
10
  private :depth, :links, :make, :sample_images, :title
@@ -1,10 +1,10 @@
1
1
  require 'erb'
2
2
 
3
- require 'images_gallery/view'
3
+ require 'images_gallery/views/base'
4
4
 
5
5
  module ImagesGallery
6
6
  module Views
7
- class Model < ImagesGallery::View
7
+ class Model < Base
8
8
 
9
9
  attr_reader :depth, :links, :make, :model, :sample_images, :title
10
10
  private :depth, :links, :make, :model, :sample_images, :title
@@ -32,7 +32,7 @@ describe 'CLI' do
32
32
  stderr = double()
33
33
  allow(command_line_interface).to receive_message_chain(:generator, :run) { raise ImagesGallery::SourceFileNotFoundError }
34
34
 
35
- expect(stderr).to receive_message_chain(:puts).with('Please make sure the specified source file exists.')
35
+ expect(stderr).to receive_message_chain(:puts).with('ERROR: Please make sure the specified source file exists.')
36
36
  command_line_interface.generate('source', 'target', stderr)
37
37
  end
38
38
  end
@@ -43,7 +43,7 @@ describe 'CLI' do
43
43
  stderr = double()
44
44
  allow(command_line_interface).to receive_message_chain(:generator, :run) { raise ImagesGallery::TargetDirectoryNotFoundError }
45
45
 
46
- expect(stderr).to receive_message_chain(:puts).with('Please make sure the specified target directory exists.')
46
+ expect(stderr).to receive_message_chain(:puts).with('ERROR: Please make sure the specified target directory exists.')
47
47
  command_line_interface.generate('source', 'target', stderr)
48
48
  end
49
49
  end
@@ -54,7 +54,7 @@ describe 'CLI' do
54
54
  stderr = double()
55
55
  allow(command_line_interface).to receive_message_chain(:generator, :run) { raise ImagesGallery::SourceFileInvalidError }
56
56
 
57
- expect(stderr).to receive_message_chain(:puts).with('The source file is invalid. Please check it is well-formed XML.')
57
+ expect(stderr).to receive_message_chain(:puts).with('ERROR: The source file is invalid. Please check it is well-formed XML.')
58
58
  command_line_interface.generate('source', 'target', stderr)
59
59
  end
60
60
  end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module ImagesGallery
4
- describe 'Collection' do
4
+ describe 'Models::Collection' do
5
5
 
6
- let(:collection) { Collection.new }
6
+ let(:collection) { Models::Collection.new }
7
7
 
8
8
  it_behaves_like 'a collection'
9
9
 
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module ImagesGallery
4
- describe 'Image' do
4
+ describe 'Models::Image' do
5
5
 
6
- let(:image) { Image.new }
6
+ let(:image) { Models::Image.new }
7
7
 
8
8
  it_behaves_like 'an image'
9
9
 
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module ImagesGallery
4
- describe 'Source' do
4
+ describe 'Models::Source' do
5
5
 
6
- let(:source) { Source.new('spec/fixtures/works.xml') }
6
+ let(:source) { Models::Source.new('spec/fixtures/works.xml') }
7
7
  let(:parser) { source }
8
8
 
9
9
  it_behaves_like 'a parser'
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module ImagesGallery
4
- describe 'View' do
4
+ describe 'Views::Base' do
5
5
 
6
- let(:view) { View.new }
6
+ let(:view) { Views::Base.new }
7
7
 
8
8
  it 'does not define :template' do
9
9
  expect { view.template }.to raise_error NotImplementedError
@@ -3,11 +3,7 @@ require 'spec_helper'
3
3
  module ImagesGallery
4
4
  describe 'Views::Index' do
5
5
 
6
- let(:data) do
7
- data = Collection.new
8
- data << Image.new
9
- end
10
-
6
+ let(:data) { images_collection }
11
7
  let(:view) { Views::Model.new(data) }
12
8
 
13
9
  it_behaves_like 'a view'
@@ -3,11 +3,7 @@ require 'spec_helper'
3
3
  module ImagesGallery
4
4
  describe 'Views::Make' do
5
5
 
6
- let(:data) do
7
- data = Collection.new
8
- data << Image.new
9
- end
10
-
6
+ let(:data) { images_collection }
11
7
  let(:view) { Views::Model.new(data) }
12
8
 
13
9
  it_behaves_like 'a view'
@@ -3,11 +3,7 @@ require 'spec_helper'
3
3
  module ImagesGallery
4
4
  describe 'Views::Model' do
5
5
 
6
- let(:data) do
7
- data = Collection.new
8
- data << Image.new
9
- end
10
-
6
+ let(:data) { images_collection }
11
7
  let(:view) { Views::Model.new(data) }
12
8
 
13
9
  it_behaves_like 'a view'
@@ -12,7 +12,14 @@ module Selectors
12
12
  end
13
13
  end
14
14
 
15
+ module ViewHelpers
16
+ def images_collection
17
+ ImagesGallery::Models::Collection.new << ImagesGallery::Models::Image.new
18
+ end
19
+ end
20
+
15
21
  RSpec.configure do |config|
16
22
  config.extend Selectors
17
23
  config.include Selectors
24
+ config.include ViewHelpers
18
25
  end
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by (Canon) Canon EOS 20D</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by (Canon) Canon EOS 400D DIGITAL</title>
5
6
  <style type="text/css">
6
7
  html, body {
data/spec/tmp/canon.html CHANGED
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by Canon</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by (FUJI PHOTO FILM CO., LTD.) SLP1000SE</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by FUJI PHOTO FILM CO., LTD.</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by (FUJIFILM) FinePix S6500fd</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by FUJIFILM</title>
5
6
  <style type="text/css">
6
7
  html, body {
data/spec/tmp/index.html CHANGED
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Index</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by (LEICA) D-LUX 3</title>
5
6
  <style type="text/css">
6
7
  html, body {
data/spec/tmp/leica.html CHANGED
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by LEICA</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by (NIKON CORPORATION) NIKON D80</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by NIKON CORPORATION</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by (Panasonic) DMC-FZ30</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by Panasonic</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by (Unknown Make) Unknown Model</title>
5
6
  <style type="text/css">
6
7
  html, body {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
+ <meta charset="utf-8">
4
5
  <title>Images by Unknown Make</title>
5
6
  <style type="text/css">
6
7
  html, body {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: images_gallery
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gonzalo Bulnes Guilpain
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-26 00:00:00.000000000 Z
11
+ date: 2015-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: libxml-ruby
@@ -139,17 +139,17 @@ files:
139
139
  - config.ru
140
140
  - lib/images_gallery.rb
141
141
  - lib/images_gallery/cli.rb
142
- - lib/images_gallery/collection.rb
143
142
  - lib/images_gallery/errors.rb
144
143
  - lib/images_gallery/generator.rb
145
- - lib/images_gallery/image.rb
146
- - lib/images_gallery/source.rb
144
+ - lib/images_gallery/models/collection.rb
145
+ - lib/images_gallery/models/image.rb
146
+ - lib/images_gallery/models/source.rb
147
147
  - lib/images_gallery/templates/_navigation.html.erb
148
148
  - lib/images_gallery/templates/_thumbnails.html.erb
149
149
  - lib/images_gallery/templates/layout.html.erb
150
150
  - lib/images_gallery/test_application.rb
151
151
  - lib/images_gallery/version.rb
152
- - lib/images_gallery/view.rb
152
+ - lib/images_gallery/views/base.rb
153
153
  - lib/images_gallery/views/index.rb
154
154
  - lib/images_gallery/views/make.rb
155
155
  - lib/images_gallery/views/model.rb
@@ -162,11 +162,11 @@ files:
162
162
  - spec/fixtures/works.xml
163
163
  - spec/fixtures/works_large.xml
164
164
  - spec/lib/images_gallery/cli_spec.rb
165
- - spec/lib/images_gallery/collection_spec.rb
166
165
  - spec/lib/images_gallery/generator_spec.rb
167
- - spec/lib/images_gallery/image_spec.rb
168
- - spec/lib/images_gallery/source_spec.rb
169
- - spec/lib/images_gallery/view_spec.rb
166
+ - spec/lib/images_gallery/models/collection_spec.rb
167
+ - spec/lib/images_gallery/models/image_spec.rb
168
+ - spec/lib/images_gallery/models/source_spec.rb
169
+ - spec/lib/images_gallery/views/base_spec.rb
170
170
  - spec/lib/images_gallery/views/index_spec.rb
171
171
  - spec/lib/images_gallery/views/make_spec.rb
172
172
  - spec/lib/images_gallery/views/model_spec.rb
@@ -223,15 +223,15 @@ specification_version: 4
223
223
  summary: Generate efficient galleries of thumbnails from large XML representations
224
224
  of EXIF data.
225
225
  test_files:
226
- - spec/lib/images_gallery/view_spec.rb
227
226
  - spec/lib/images_gallery/generator_spec.rb
228
- - spec/lib/images_gallery/image_spec.rb
227
+ - spec/lib/images_gallery/models/image_spec.rb
228
+ - spec/lib/images_gallery/models/source_spec.rb
229
+ - spec/lib/images_gallery/models/collection_spec.rb
229
230
  - spec/lib/images_gallery/cli_spec.rb
230
231
  - spec/lib/images_gallery/views/index_spec.rb
232
+ - spec/lib/images_gallery/views/base_spec.rb
231
233
  - spec/lib/images_gallery/views/model_spec.rb
232
234
  - spec/lib/images_gallery/views/make_spec.rb
233
- - spec/lib/images_gallery/source_spec.rb
234
- - spec/lib/images_gallery/collection_spec.rb
235
235
  - spec/features/index_page_spec.rb
236
236
  - spec/features/models_pages/canon_eos_20d_page_spec.rb
237
237
  - spec/features/models_pages/lux_d_3_page_spec.rb
@@ -1,15 +0,0 @@
1
- require 'images_gallery/image'
2
-
3
- module ImagesGallery
4
- class Collection < Array
5
-
6
- def makes
7
- map { |image| image.make }.uniq.sort
8
- end
9
-
10
- def models
11
- map { |image| image.model }.uniq.sort
12
- end
13
-
14
- end
15
- end
@@ -1,19 +0,0 @@
1
- module ImagesGallery
2
- class Image
3
-
4
- attr_accessor :id, :src, :make, :model
5
-
6
- def make
7
- @make || 'Unknown Make'
8
- end
9
-
10
- def model
11
- @model || 'Unknown Model'
12
- end
13
-
14
- def description
15
- "Image #{@id}"
16
- end
17
-
18
- end
19
- end
@@ -1,104 +0,0 @@
1
- require 'libxml'
2
-
3
- require 'images_gallery/collection'
4
-
5
- module ImagesGallery
6
- class Source
7
-
8
- include LibXML
9
- include XML::SaxParser::Callbacks
10
-
11
- attr_reader :images
12
-
13
- # Provides a collection of images to presenters
14
- #
15
- # Extracts some images attributes from an XML collection of works
16
- # and collects the images as plain Ruby objects so other classes
17
- # can use them with presentational purpose.
18
- #
19
- # This class should be able to parse efficiently large XML files.
20
- #
21
- # file - Path to an XML representation of the images (metadata, EXIF)
22
- #
23
- # Example:
24
- #
25
- # source = ImagesGallery::Source.new('path/to/source.xml')
26
- # source.parse # creates a Collection of Images
27
- # source.images # is available after parsing
28
- #
29
- # Returns a Source object, ready to parse the corresponding XML file.
30
- def initialize(file)
31
- @file = XML::SaxParser.file(file)
32
- @file.callbacks = self
33
- end
34
-
35
- def parse
36
- @images = Collection.new
37
- begin
38
- @file.parse
39
- rescue LibXML::XML::Error
40
- raise SourceFileInvalidError
41
- end
42
- end
43
-
44
- # Callbacks can't be private, yet they are not part of the public API.
45
-
46
- def on_start_element(element, attributes)
47
- @current_element = element
48
-
49
- if element == 'work'
50
- @current_image = Image.new
51
- end
52
-
53
- if element == 'url' && attributes['type'] == 'small'
54
- @current_element = 'thumbnail URL'
55
- end
56
- end
57
-
58
- def on_end_element(element)
59
- if element == 'work'
60
- @images << @current_image
61
- end
62
-
63
- if element == 'id'
64
- @current_image.id = @current_id
65
- end
66
-
67
- if element == 'make'
68
- @current_image.make = @current_make
69
- end
70
-
71
- if element == 'model'
72
- @current_image.model = @current_model
73
- end
74
-
75
- if @current_element == 'thumbnail URL'
76
- @current_image.src = @current_src
77
- end
78
-
79
- @current_element = nil
80
- end
81
-
82
- def on_characters(char)
83
- if @current_element == 'id'
84
- @current_id = char
85
- end
86
-
87
- if @current_element == 'make'
88
- @current_make = char
89
- end
90
-
91
- if @current_element == 'model'
92
- @current_model = char
93
- end
94
-
95
- if @current_element == 'thumbnail URL'
96
- @current_src = char
97
- end
98
- end
99
-
100
- def on_end_document
101
- @current_element = nil
102
- end
103
- end
104
- end
@@ -1,55 +0,0 @@
1
- require 'erb'
2
-
3
- module ImagesGallery
4
- class View
5
-
6
- # Provides context and helpers to the corresponding template
7
- #
8
- # Any variable defined in the context of this class will be accessible
9
- # from the corresponding ERb template.
10
- # See http://ruby-doc.org/stdlib-2.2.2/libdoc/erb/rdoc/ERB.html#method-i-result
11
- #
12
- # Usage:
13
- #
14
- # Do not instanciate this class, define subclasses instead an define their
15
- # template methods as demonstrated in Views::Index.
16
- #
17
- # Conventionally, templates could be stored in images_gallery/templates, but
18
- # there is no obligation to follow the convention.
19
- #
20
- # This class not meant to be instanciated, subclasses do return View instances (kind of).
21
- def initialize
22
- @template = File.new(template)
23
- end
24
-
25
- def template
26
- raise NotImplementedError
27
- end
28
-
29
- def render
30
- ERB.new(File.new(template).read).result(binding)
31
- end
32
-
33
- def thumbnails(images)
34
- template = File.expand_path('../templates/_thumbnails.html.erb', __FILE__)
35
- ERB.new(File.new(template).read).result(binding)
36
- end
37
-
38
- def navigation(links)
39
- template = File.expand_path('../templates/_navigation.html.erb', __FILE__)
40
- ERB.new(File.new(template).read).result(binding)
41
- end
42
-
43
- def link_to(depth, make, model=nil)
44
- ('../' * depth) + file_identifier(make, model) + '.html'
45
- end
46
-
47
- def file_identifier(make, model=nil)
48
- if model.nil?
49
- "#{make.to_filename}"
50
- else
51
- "#{make.to_filename}/#{model.to_filename}"
52
- end
53
- end
54
- end
55
- end