richter_catalogue 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a091d1076ac769afcfdbce3e697c86e61b663fda
4
+ data.tar.gz: 0c0254cef4d24e31cd2fbeee1cb0c7fec2e44ba9
5
+ SHA512:
6
+ metadata.gz: 4780e8e861f4b046923a26d85e98aa3965dafa0a9bf470f621d50a8bf58188527a824adc1af232e95d4e8e45f00ec4ab69ac5c481ed8c906d5d3968945e45acd
7
+ data.tar.gz: 021dfdac4c123e61a776a10392c00b77890b5bc0eeb95a332f2dcf4fb7a611412d612ee1f8a00716d5f1aac9dc97e9441adea4269950d7021b6d9bdd9d8af4e2
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,49 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at andresduarte010@gmail.com. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
45
+ version 1.3.0, available at
46
+ [http://contributor-covenant.org/version/1/3/0/][version]
47
+
48
+ [homepage]: http://contributor-covenant.org
49
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in richter_catalogue.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 andresduarte
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # RichterCatalogue
2
+
3
+ richter_catalogue allows users to the search through an abridged version of Gerhard Richter's Painting Catalogue either by the painting's subject, the year in which it was conceived, or directly by its name.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'richter_catalogue'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install richter_catalogue
20
+
21
+ ## Usage
22
+
23
+ Decide wether you want to search by subject, year or name.
24
+
25
+ type 'subject' to search catalogue by subject
26
+ type 'year' to search catalogue by year
27
+ type 'name' to search catalogue by year
28
+
29
+ Subject
30
+ You'll be presented with a numbered list of available subjects.
31
+ You may select one either by number or by name * names written in lowercase yield correct results
32
+ If your selection is invalid you'll be asked to try again
33
+ Once a correct subject has been selected you'll be presented with a number list of paintings that belong to the selected subject.
34
+ If you want information on all the paintings type 'all'
35
+ If you want information on a specific painting you may select which painting either by number or by name
36
+ If a painting is selected by name and there are multiple paintings with the same name information will be return on all said paintings
37
+
38
+ Year
39
+ You'll be presented with a list of available years of which you may select one.
40
+ If your selection is invalid you'll be asked to try again.
41
+ Once a correct year has been selected you'll be presented with a number list of paintings that belong to the selected year.
42
+ If you wish to see information on all the paintings type 'all'.
43
+ If you want information on a specific painting you may select which painting either by number or by name.
44
+ If a painting is selected by name and there are multiple paintings with the same name information will be return on all said paintings
45
+
46
+ Name
47
+ You'll be asked to input a painting's name.
48
+ If your input is invalid you'll be asked to try again.
49
+ Once a correct painting's name has be inputed you'll be returned information on that painting
50
+ If the provided painting name matches multiple paintings you'll be returned information on all said paintings.
51
+
52
+ at any point salve for the original menu you can type 'back' to go back to the previous query
53
+
54
+ at any point you can type 'exit' to exit the gem
55
+
56
+ ## Development
57
+
58
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
59
+
60
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
61
+
62
+ ## Contributing
63
+
64
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/richter_catalogue. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
65
+
66
+
67
+ ## License
68
+
69
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
70
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "richter_catalogue"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "richter_catalogue"
5
+
6
+ RichterCatalogue::CLI.new.call
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,37 @@
1
+ class RichterCatalogue::Artist
2
+ attr_accessor :name, :age, :nationality, :movement, :education, :artist_url, :paintings, :subjects
3
+ @@all = []
4
+
5
+ def initialize(attributes_hash)
6
+ self.add_artist_attributes(attributes_hash)
7
+ @paintings = []
8
+ @@all << self
9
+ end
10
+
11
+ def self.all
12
+ @@all
13
+ end
14
+
15
+ def self.create_from_profile(attributes_hash)
16
+ RichterCatalogue::Artist.new(attributes_hash)
17
+ end
18
+
19
+ def add_artist_attributes(attributes_hash)
20
+ attributes_hash.each {|key, value| self.send("#{key}=", value)}
21
+ self
22
+ end
23
+
24
+ def add_painting(painting)
25
+ painting.artist = self unless painting.artist == self
26
+ @paintings << painting unless @paintings.include?(painting)
27
+ end
28
+
29
+ def subjects
30
+ self.paintings.collect {|painting| painting.subject}.uniq
31
+ end
32
+
33
+ def self.find_by_name(name)
34
+ self.all.detect{|artist| artist.name == name}
35
+ end
36
+
37
+ end
@@ -0,0 +1,244 @@
1
+ class RichterCatalogue::CLI
2
+
3
+ BASE_PATH = "https://www.gerhard-richter.com"
4
+
5
+ def make_artists
6
+ attributes_hash = RichterCatalogue::Scraper.artist_page("https://en.wikipedia.org/wiki/Gerhard_Richter")
7
+ RichterCatalogue::Artist.create_from_profile(attributes_hash)
8
+ end
9
+
10
+ def make_subjects
11
+ subjects_array = RichterCatalogue::Scraper.subjects_page(BASE_PATH + "/en/art/paintings")
12
+ RichterCatalogue::Subject.create_from_subjects(subjects_array)
13
+ end
14
+
15
+ def make_paintings
16
+ RichterCatalogue::Subject.all.each do |subject|
17
+ paintings_array = RichterCatalogue::Scraper.subject_page(BASE_PATH + subject.subject_url)
18
+ RichterCatalogue::Painting.create_from_subject(paintings_array, subject)
19
+ end
20
+ end
21
+
22
+ def add_painting_attributes
23
+ RichterCatalogue::Painting.all.each do |painting|
24
+ attributes = RichterCatalogue::Scraper.painting_page(BASE_PATH + painting.painting_url)
25
+ painting.add_attributes(attributes)
26
+ painting.artist = RichterCatalogue::Artist.find_by_name("Gerhard Richter")
27
+ end
28
+ end
29
+
30
+ def make_catalogue
31
+ make_artists
32
+ make_subjects
33
+ make_paintings
34
+ add_painting_attributes
35
+ end
36
+
37
+ def call
38
+ puts "Retrieving information from the Catalogue..."
39
+ make_catalogue
40
+ search_method
41
+ goodbye
42
+ end
43
+
44
+ def search_method(input = nil)
45
+ if input == "exit"
46
+ else
47
+
48
+ puts "Welcome to Gerhard Richter's Catalogue"
49
+ puts "Search by subject, by year, or by name?"
50
+ puts "type exit to exit"
51
+
52
+ input = gets.strip.downcase
53
+
54
+ case input
55
+ when "subject"
56
+ list_subjects
57
+ subject_paintings
58
+ when "year"
59
+ list_years
60
+ year_paintings
61
+ when "name"
62
+ name_paintings
63
+ when "exit"
64
+ search_method("exit")
65
+ else
66
+ puts "Search method is invalid, please try again"
67
+ search_method
68
+ end
69
+ end
70
+ end
71
+
72
+ def goodbye
73
+ puts "Thank you for visiting Gerhard Richter's Catalogue"
74
+ end
75
+
76
+ def list_subjects
77
+ RichterCatalogue::Subject.all.each_with_index {|subject, i| puts " #{i + 1}. #{subject.name}"}
78
+ end
79
+
80
+ def list_years
81
+ years = []
82
+ RichterCatalogue::Year.all.each {|year, i| years << year.name}
83
+ years = years.sort
84
+ years.each {|year| puts " - #{year}"}
85
+ end
86
+
87
+ def subject_paintings
88
+
89
+ subject_names = RichterCatalogue::Subject.all.collect {|subject| subject.name}
90
+ subject_names_downcase = RichterCatalogue::Subject.all.collect {|subject| subject.name.downcase}
91
+
92
+ puts "Select subject by number or by name"
93
+ puts "type back to go back"
94
+ puts "type exit to exit"
95
+
96
+ input_subject = gets.strip
97
+
98
+ if input_subject.to_i.between?(1, subject_names.size)
99
+ subject_paintings_names(subject_names[input_subject.to_i - 1])
100
+ elsif subject_names.include?(input_subject) || subject_names_downcase.include?(input_subject)
101
+ if subject_names.include?(input_subject)
102
+ subject_paintings_names(input_subject)
103
+ else
104
+ subject_paintings_names(subject_names[subject_names_downcase.index(input_subject)])
105
+ end
106
+ elsif input_subject == "back"
107
+ search_method
108
+ elsif input_subject == "exit"
109
+ search_method("exit")
110
+ else
111
+ puts "Subject is invalid, please try again"
112
+ subject_paintings
113
+ end
114
+ end
115
+
116
+ def subject_paintings_names(subject_name)
117
+
118
+ subject = RichterCatalogue::Subject.find_by_name(subject_name)
119
+ painting_names = subject.paintings.collect {|painting| painting.name}
120
+ painting_names_downcase = subject.paintings.collect {|painting| painting.name.downcase}
121
+ painting_names.each.with_index(1) {|p, i| puts "#{i}. #{p}"}
122
+
123
+ puts "Select painting by number or by name"
124
+ puts "type all to see information on all paintings"
125
+ puts "type back to go back"
126
+ puts "type exit to exit"
127
+
128
+ input = gets.strip
129
+
130
+ if input.to_i.between?(1, painting_names.size)
131
+ RichterCatalogue::Painting.display(subject.paintings[input.to_i - 1])
132
+ subject_paintings_names(subject_name)
133
+ elsif painting_names.include?(input) || painting_names_downcase.include?(input)
134
+ if painting_names.include?(input)
135
+ paintings_matched = subject.paintings.select {|painting| painting.name == input}
136
+ else
137
+ paintings_matched = subject.paintings.select {|painting| painting.name == painting_names[painting_names_downcase.index(input)]}
138
+ end
139
+ paintings_matched.each {|painting| RichterCatalogue::Painting.display(painting)}
140
+ subject_paintings_names(subject_name)
141
+ elsif input == "all"
142
+ subject.paintings.each {|painting| RichterCatalogue::Painting.display(painting)}
143
+ subject_paintings_names(subject_name)
144
+ elsif input == "back"
145
+ list_subjects
146
+ subject_paintings
147
+ elsif input == "exit"
148
+ search_method("exit")
149
+ else
150
+ puts "Painting is invalid, please try again"
151
+ subject_paintings_names(subject_name)
152
+ end
153
+ end
154
+
155
+ def year_paintings
156
+
157
+ puts "Select a year"
158
+ puts "type back to go back"
159
+ puts "type exit to exit"
160
+
161
+ input_year = gets.strip
162
+
163
+ if !RichterCatalogue::Year.find_by_name(input_year).nil?
164
+ year_paintings_names(input_year)
165
+ elsif input_year == "back"
166
+ search_method
167
+ elsif input_year == "exit"
168
+ search_method("exit")
169
+ else
170
+ puts "No paintings found for selected year please select another year"
171
+ year_paintings
172
+ end
173
+ end
174
+
175
+
176
+ def year_paintings_names(year_name)
177
+
178
+ year = RichterCatalogue::Year.find_by_name(year_name)
179
+ painting_names = year.paintings.collect {|painting| painting.name}
180
+ painting_names_downcase = year.paintings.collect {|painting| painting.name.downcase}
181
+ painting_names.each.with_index(1) {|p, i| puts "#{i}. #{p}"}
182
+
183
+ puts "Select painting by number or by name"
184
+ puts "type all to see information on all paintings"
185
+ puts "type back to go back"
186
+ puts "type exit to exit"
187
+
188
+ input = gets.strip
189
+
190
+ if input.to_i.between?(1, painting_names.size)
191
+ RichterCatalogue::Painting.display(year.paintings[input.to_i - 1])
192
+ year_paintings_names(year_name)
193
+ elsif painting_names.include?(input) || painting_names_downcase.include?(input)
194
+ if painting_names.include?(input)
195
+ paintings_matched = year.paintings.select {|painting| painting.name == input}
196
+ else
197
+ paintings_matched = year.paintings.select {|painting| painting.name == painting_names[painting_names_downcase.index(input)]}
198
+ end
199
+ paintings_matched.each {|painting| RichterCatalogue::Painting.display(painting)}
200
+ year_paintings_names(year_name)
201
+ elsif input == "all"
202
+ year.paintings.each {|painting| RichterCatalogue::Painting.display(painting)}
203
+ year_paintings_names(year_name)
204
+ elsif input == "back"
205
+ list_years
206
+ year_paintings
207
+ elsif input == "exit"
208
+ search_method("exit")
209
+ else
210
+ puts "Painting is invalid, please try again"
211
+ year_paintings_names(year_name)
212
+ end
213
+ end
214
+
215
+ def name_paintings
216
+
217
+ painting_names = RichterCatalogue::Painting.all.collect {|painting| painting.name}
218
+ painting_names_downcase = RichterCatalogue::Painting.all.collect {|painting| painting.name.downcase}
219
+
220
+ puts "type name"
221
+ puts "type back to go back"
222
+ puts "type exit to exit"
223
+
224
+ input_name = gets.strip
225
+
226
+ if painting_names.include?(input_name) || painting_names_downcase.include?(input_name)
227
+ if painting_names.include?(input_name)
228
+ RichterCatalogue::Painting.find_by_name(input_name).each {|painting| RichterCatalogue::Painting.display(painting)}
229
+ else
230
+ RichterCatalogue::Painting.find_by_name(painting_names[painting_names_downcase.index(input_name)]).each {|painting| RichterCatalogue::Painting.display(painting)}
231
+ end
232
+ name_paintings
233
+ elsif input_name == "back"
234
+ search_method
235
+ elsif input_name == "exit"
236
+ search_method("exit")
237
+ else
238
+ puts "Painting was not found please try again"
239
+ name_paintings
240
+ end
241
+ end
242
+
243
+ end
244
+
@@ -0,0 +1,72 @@
1
+ class RichterCatalogue::Painting
2
+ attr_accessor :name, :medium, :year, :size, :price, :painting_url
3
+ attr_reader :artist, :subject
4
+
5
+ @@all = []
6
+ @@names_all = []
7
+
8
+ def initialize(attributes_hash)
9
+ attributes_hash.each {|key, value| self.send("#{key}=", value)}
10
+ @@all << self
11
+ end
12
+
13
+
14
+ def self.create_from_subject(paintings_array, subject = nil)
15
+ paintings_array.each do |attributes_hash|
16
+ new_painting = RichterCatalogue::Painting.new(attributes_hash)
17
+ new_painting.subject = subject
18
+ end
19
+ end
20
+
21
+ def add_attributes(attributes_hash)
22
+ attributes_hash.each do |key, value|
23
+ self.send("#{key}=", value)
24
+ end
25
+ self
26
+ end
27
+
28
+ def self.all
29
+ @@all
30
+ end
31
+
32
+ def artist=(artist)
33
+ @artist = artist
34
+ artist.add_painting(self)
35
+ end
36
+
37
+ def subject=(subject)
38
+ @subject = subject
39
+ subject.add_painting(self)
40
+ end
41
+
42
+ def year=(year)
43
+ @year = year
44
+ year.add_painting(self)
45
+ end
46
+
47
+ def self.display_name(painting)
48
+ puts "- #{painting.name}"
49
+ end
50
+
51
+ def self.display(painting)
52
+
53
+ puts " name: #{painting.name}"
54
+ puts " year: #{painting.year.name}"
55
+ puts " size: #{painting.size}"
56
+ puts " medium: #{painting.medium}"
57
+
58
+ if !(painting.price == "")
59
+ puts " price: #{painting.price}"
60
+ end
61
+ puts "------------------------"
62
+ end
63
+
64
+ def self.names
65
+ RichterCatalogue::Painting.all.collect {|painting| painting.name}.uniq
66
+ end
67
+
68
+ def self.find_by_name(name)
69
+ self.all.select{|painting| painting.name == name}
70
+ end
71
+
72
+ end
@@ -0,0 +1,74 @@
1
+ class RichterCatalogue::Scraper
2
+
3
+ def self.artist_page(artist_url)
4
+
5
+ doc = Nokogiri::HTML(open(artist_url))
6
+
7
+ name = doc.css("span.fn").text
8
+ age = doc.css("span.ForceAgeToShow").text.gsub(/[(age )]/, "")
9
+ nationality = doc.css("table tr:nth-of-type(4) td.category").text
10
+ movement = doc.css("tr td.category a").text
11
+ edu_1 = doc.css("div#mw-content-text table tr:nth-of-type(5) td:first-of-type a.mw-redirect").text + ", "
12
+ edu_2 = doc.css("div#mw-content-text table tr:nth-of-type(5) td:first-of-type a.mw-redirect ~ a")
13
+ edu_2.each_with_index {|edu, i| i.between?(1, edu_2.size - 1) ? edu_1 << edu.text + ", " : edu_1 << edu.text + "."}
14
+
15
+ artist = {name: name, age: age, nationality: nationality, movement: movement, education: edu_1, artist_url: artist_url}
16
+
17
+ artist
18
+ end
19
+
20
+ def self.subjects_page(subjects_url)
21
+ doc = Nokogiri::HTML(open(subjects_url))
22
+
23
+ subjects = []
24
+
25
+ doc.css("div.div-section-category div.div-section-category-mobile a.a-lit-cat").each do |subject|
26
+ name = subject.attribute("title").text.strip
27
+ case name
28
+ when "Aeroplanes"
29
+ subjects << {name: name, subject_url: subject.attribute("href").value}
30
+ when "Children"
31
+ subjects << {name: name, subject_url: subject.attribute("href").value}
32
+ when "Mother and Child"
33
+ subjects << {name: name, subject_url: subject.attribute("href").value}
34
+ when "Flowers"
35
+ subjects << {name: name, subject_url: subject.attribute("href").value}
36
+ when "Families"
37
+ subjects << {name: name, subject_url: subject.attribute("href").value}
38
+ when "Skulls"
39
+ subjects << {name: name, subject_url: subject.attribute("href").value}
40
+ else
41
+ end
42
+ end
43
+ subjects
44
+ end
45
+
46
+ def self.subject_page(subject_url)
47
+ doc = Nokogiri::HTML(open(subject_url))
48
+
49
+ paintings = []
50
+
51
+ doc.css("div.div-thumb.div-thumb-with-title a.a-thumb-link").each {|painting| paintings << {painting_url: painting.attribute("href").value }}
52
+
53
+ paintings
54
+ end
55
+
56
+ def self.painting_page(painting_url)
57
+ doc = Nokogiri::HTML(open(painting_url))
58
+
59
+ painting = {medium: doc.css("#div-painting-info-box p.p-painting-info-medium").text.strip,
60
+ year: RichterCatalogue::Year.find_or_create_by_name(doc.css("p.p-painting-info-year-size-etc span.span-painting-info-year").text.strip),
61
+ size: doc.css("p.p-painting-info-year-size-etc span.span-painting-info-size").text.strip}
62
+
63
+ painting[:price] = doc.css("div.info table tr td:first-of-type").text.strip
64
+ if painting[:price] == ""
65
+ painting.delete(:price)
66
+ end
67
+ painting[:name] = doc.css("div#div-painting-info-box span.span-painting-title2").text.strip
68
+ if painting[:name] == ""
69
+ painting[:name] = doc.css("div#div-painting-info-box span.span-painting-title1").text.strip
70
+ end
71
+ painting
72
+ end
73
+
74
+ end
@@ -0,0 +1,34 @@
1
+ class RichterCatalogue::Subject
2
+ attr_accessor :name, :subject_url, :paintings, :artists
3
+ @@all = []
4
+
5
+ def initialize
6
+ @@all << self
7
+ @paintings = []
8
+ end
9
+
10
+ def self.all
11
+ @@all
12
+ end
13
+
14
+ def self.create_from_subjects(subjects_array)
15
+ subjects_array.each do |subject_hash|
16
+ new_subject = RichterCatalogue::Subject.new
17
+ subject_hash.each {|key, value| new_subject.send("#{key}=", value)}
18
+ end
19
+ end
20
+
21
+ def artists
22
+ self.paintings.collect {|painting| painting.artist}.uniq
23
+ end
24
+
25
+ def add_painting(painting)
26
+ painting.artist = self unless painting.artist == self
27
+ @paintings << painting unless @paintings.include?(painting)
28
+ end
29
+
30
+ def self.find_by_name(name)
31
+ self.all.detect{|subject| subject.name == name}
32
+ end
33
+
34
+ end
@@ -0,0 +1,3 @@
1
+ module RichterCatalogue
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,33 @@
1
+ class RichterCatalogue::Year
2
+ attr_accessor :name, :paintings
3
+ @@all = []
4
+
5
+ def initialize(name)
6
+ @name = name
7
+ @paintings = []
8
+ end
9
+
10
+ def self.all
11
+ @@all
12
+ end
13
+
14
+ def self.create(name)
15
+ new_year = RichterCatalogue::Year.new(name)
16
+ self.all << new_year
17
+ new_year
18
+ end
19
+
20
+ def add_painting(painting)
21
+ painting.artist = self unless painting.artist == self
22
+ @paintings << painting unless @paintings.include?(painting)
23
+ end
24
+
25
+ def self.find_by_name(name)
26
+ self.all.detect{|obj| obj.name == name}
27
+ end
28
+
29
+ def self.find_or_create_by_name(name)
30
+ self.find_by_name(name) || self.create(name)
31
+ end
32
+
33
+ end
@@ -0,0 +1,13 @@
1
+ require 'open-uri'
2
+ require 'nokogiri'
3
+ require 'pry'
4
+
5
+ require_relative './richter_catalogue/version'
6
+ require_relative './richter_catalogue/cli'
7
+ require_relative './richter_catalogue/scraper'
8
+ require_relative './richter_catalogue/artist'
9
+ require_relative './richter_catalogue/subject'
10
+ require_relative './richter_catalogue/painting'
11
+ require_relative './richter_catalogue/year'
12
+
13
+
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'richter_catalogue/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "richter_catalogue"
8
+ spec.version = RichterCatalogue::VERSION
9
+ spec.authors = ["andresduarte"]
10
+ spec.email = ["andresduarte010@gmail.com"]
11
+
12
+ spec.summary = %q{CLI gem for searching through Gerhard Richter's Catalogue by year or by subject}
13
+ spec.description = %q{richter_catalogue allows users to the search through an abridged version of Gerhard Richter's Painting Catalogue either by the painting's subject, the year in which it was conceived, or directly by its name.}
14
+ spec.homepage = "https://github.com/andresduarte/richter-catalogue"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
21
+ else
22
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_development_dependency "bundler", "~> 1.12"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "pry", '>= 0'
33
+
34
+ spec.add_runtime_dependency "nokogiri", '>= 0'
35
+ end
data/spec.md ADDED
@@ -0,0 +1,6 @@
1
+ # Specifications for the CLI Assessment
2
+
3
+ Specs:
4
+ - [x] Have a CLI for interfacing with the application
5
+ - [x] Pull data from an external source
6
+ - [x] Implement both list and detail views
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: richter_catalogue
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - andresduarte
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-11-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: nokogiri
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: richter_catalogue allows users to the search through an abridged version
70
+ of Gerhard Richter's Painting Catalogue either by the painting's subject, the year
71
+ in which it was conceived, or directly by its name.
72
+ email:
73
+ - andresduarte010@gmail.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - ".gitignore"
79
+ - CODE_OF_CONDUCT.md
80
+ - Gemfile
81
+ - LICENSE.txt
82
+ - README.md
83
+ - Rakefile
84
+ - bin/console
85
+ - bin/richter-catalogue
86
+ - bin/setup
87
+ - lib/richter_catalogue.rb
88
+ - lib/richter_catalogue/artist.rb
89
+ - lib/richter_catalogue/cli.rb
90
+ - lib/richter_catalogue/painting.rb
91
+ - lib/richter_catalogue/scraper.rb
92
+ - lib/richter_catalogue/subject.rb
93
+ - lib/richter_catalogue/version.rb
94
+ - lib/richter_catalogue/year.rb
95
+ - richter_catalogue.gemspec
96
+ - spec.md
97
+ homepage: https://github.com/andresduarte/richter-catalogue
98
+ licenses:
99
+ - MIT
100
+ metadata:
101
+ allowed_push_host: https://rubygems.org
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.4.5.1
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: CLI gem for searching through Gerhard Richter's Catalogue by year or by subject
122
+ test_files: []