Skip to content

Commit 73dfdc5

Browse files
committed
Release #793
2 parents 1fe5825 + afa4988 commit 73dfdc5

27 files changed

+1108
-55
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ executors:
44
rails_executor:
55
working_directory: ~/web-monitoring-db
66
docker:
7-
- image: circleci/ruby:2.6.5-node
7+
- image: circleci/ruby:2.6.6-node
88
environment:
99
RAILS_ENV: test
1010
RACK_ENV: test

.ruby-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.6.5
1+
2.6.6

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# https://docs.docker.com/engine/userguide/eng-image/multistage-build
33

44
### BASE ENVIRONMENT STAGE ###
5-
FROM ruby:2.6.5-slim as base
5+
FROM ruby:2.6.6-slim as base
66
LABEL maintainer="enviroDGI@gmail.com"
77

88
# Install apt based dependencies required to run Rails as

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ git_source(:github) do |repo_name|
55
"https://github.com/#{repo_name}.git"
66
end
77

8-
ruby '2.6.5'
8+
ruby '2.6.6'
99

1010
gem 'aws-sdk-s3', '~> 1.85'
1111
gem 'concurrent-ruby', '~> 1.1'

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ DEPENDENCIES
381381
webmock (~> 3.10)
382382

383383
RUBY VERSION
384-
ruby 2.6.5p114
384+
ruby 2.6.6p146
385385

386386
BUNDLED WITH
387387
2.1.4

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ We maintain a publicly available *staging server* at https://api-staging.monitor
2222

2323
## Installation
2424

25-
1. Ensure you have Ruby 2.6.5+.
25+
1. Ensure you have Ruby 2.6.6+.
2626

2727
You can use [rbenv](https://github.com/rbenv/rbenv) to manage multiple Ruby versions
2828

app/controllers/api/v0/pages_controller.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,16 @@ def index
7171
end
7272

7373
def show
74-
page = Page.find(params[:id])
74+
begin
75+
page = Page.find(params[:id])
76+
rescue ActiveRecord::RecordNotFound
77+
merge = MergedPage.find(params[:id])
78+
redirect_to(
79+
api_v0_page_url(merge.target_uuid),
80+
status: :permanent_redirect
81+
) and return
82+
end
83+
7584
data = page.as_json(include: [:maintainers, :tags])
7685
if should_allow_versions
7786
data['versions'] = page.versions.where(different: true).as_json
@@ -155,11 +164,12 @@ def page_collection
155164

156165
if params[:url]
157166
query = params[:url]
167+
collection = collection.joins(:urls)
158168
if query.include? '*'
159169
query = query.gsub('%', '\%').gsub('_', '\_').tr('*', '%')
160-
collection = collection.where('url LIKE ?', query)
170+
collection = collection.where('page_urls.url LIKE ?', query)
161171
else
162-
collection = collection.where(url: query)
172+
collection = collection.where('page_urls.url = ?', query)
163173
end
164174
end
165175

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
class Api::V0::UrlsController < Api::V0::ApiController
2+
def index
3+
urls = page.urls.order('page_urls.to_time DESC')
4+
5+
render json: {
6+
links: { page: api_v0_page_url(page) },
7+
data: urls
8+
}
9+
end
10+
11+
def show
12+
@page_url ||= page.urls.find(params[:id])
13+
render json: {
14+
links: {
15+
page: api_v0_page_url(page),
16+
page_urls: api_v0_page_urls_url(page)
17+
},
18+
data: @page_url
19+
}
20+
end
21+
22+
def create
23+
@page_url = page.urls.create!(url_params)
24+
show
25+
rescue ActiveRecord::RecordNotUnique
26+
raise Api::ResourceExistsError, 'This page already has the given URL and timeframe'
27+
end
28+
29+
def update
30+
updates = url_params
31+
if updates.key?(:url)
32+
raise Api::UnprocessableError, 'You cannot change a URL\'s `url`'
33+
end
34+
35+
@page_url ||= page.urls.find(params[:id])
36+
@page_url.update(url_params)
37+
show
38+
end
39+
40+
def destroy
41+
@page_url ||= page.urls.find(params[:id])
42+
# You cannot delete the canonical URL.
43+
if @page_url.url == page.url
44+
raise Api::UnprocessableError, 'You cannot remove the page\'s canonical URL'
45+
else
46+
@page_url.destroy
47+
redirect_to(api_v0_page_urls_url(page))
48+
end
49+
end
50+
51+
protected
52+
53+
def page
54+
@page ||= Page.find(params[:page_id])
55+
end
56+
57+
def url_params
58+
result = params
59+
.require(:page_url)
60+
.permit(:url, :from_time, :to_time, :notes)
61+
62+
result.slice('from_time', 'to_time').each do |key, value|
63+
result[key] = parse_time(key, value)
64+
end
65+
66+
result
67+
end
68+
69+
def parse_time(field, time_input)
70+
return if time_input.nil?
71+
72+
Time.parse(time_input)
73+
rescue ArgumentError
74+
raise Api::UnprocessableError, "`#{field}` was not a valid time or `null`"
75+
end
76+
end

app/jobs/import_versions_job.rb

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,13 @@ def page_for_record(record, create: true, row:)
173173
validate_kind!([String], record, 'page_url')
174174
validate_kind!([Array, NilClass], record, 'page_maintainers')
175175
validate_kind!([Array, NilClass], record, 'page_tags')
176+
validate_present!(record, 'capture_time')
177+
validate_kind!([String], record, 'capture_time')
176178

177179
url = record['page_url']
178180

179-
existing_page = Page.find_by_url(url)
181+
capture_time = Time.parse(record['capture_time'])
182+
existing_page = Page.find_by_url(url, at_time: capture_time)
180183
page = if existing_page
181184
log(object: existing_page, operation: :found, row: row)
182185
existing_page
@@ -191,6 +194,20 @@ def page_for_record(record, create: true, row:)
191194
(record['page_maintainers'] || []).each {|name| page.add_maintainer(name)}
192195
(record['page_tags'] || []).each {|name| page.add_tag(name)}
193196

197+
# If the page was not an *exact* URL match, add the URL to the page.
198+
# (`page.find_by_url` used above will match by `url_key`, too.)
199+
page.urls.find_or_create_by(url: url)
200+
# TODO: Add URLs from redirects automatically. The main blocker for
201+
# this at the moment is the following situation:
202+
#
203+
# Two pages, A=https://example.com/about
204+
# B=https://example.com/about/locations
205+
# Page B is removed, but instead of returning a 404 or 403 status
206+
# code, it starts redirecting to Page A.
207+
#
208+
# This is unfortunately not uncommon, so we need some heuristics to
209+
# account for it, e.g. URL does not already belong to another page.
210+
194211
page
195212
end
196213

app/models/concerns/taggable.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ module Taggable
22
extend ActiveSupport::Concern
33

44
included do
5-
has_many :taggings, as: :taggable, foreign_key: 'taggable_uuid'
6-
has_many :tags, through: :taggings
5+
has_many :taggings, as: :taggable, foreign_key: 'taggable_uuid', dependent: :delete_all
6+
has_many :tags, through: :taggings, dependent: nil
77
end
88

99
def add_tag(tag)

app/models/merged_page.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# MergedPage keeps track of pages that were merged into others so we can
2+
# support old links by redirecting to the page they were merged into.
3+
# - The primary key is the ID of the page that was merged and removed
4+
# - `target_uuid` is the ID of the page it was merged into
5+
# - `audit_data` is any useful JSON data about the page (usually a frozen
6+
# copy of its attributes).
7+
class MergedPage < ApplicationRecord
8+
include UuidPrimaryKey
9+
10+
belongs_to :target,
11+
class_name: 'Page',
12+
foreign_key: :target_uuid,
13+
required: true
14+
end

0 commit comments

Comments
 (0)