govuk_content_models 6.3.0 → 6.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 6.4.0
2
+
3
+ Added SpecialistDocumentEdition
4
+
1
5
  ## 6.1.0
2
6
 
3
7
  makes this gem compatible with gds-sso (9.2.0)
@@ -78,6 +78,7 @@ class Artefact
78
78
  "smartanswers" => ["smart-answer"],
79
79
  "custom-application" => ["custom-application"], # In this case the owning_app is overriden. eg calendars, licencefinder
80
80
  "travel-advice-publisher" => ["travel-advice"],
81
+ "specialist-publisher" => ["specialist-document"],
81
82
  "whitehall" => ["case_study",
82
83
  "consultation",
83
84
  "detailed_guide",
@@ -0,0 +1,16 @@
1
+ class SpecialistDocumentEdition < Edition
2
+ field :summary, type: String
3
+ field :body, type: String
4
+ field :opened_date, type: Date
5
+ field :closed_date, type: Date
6
+ field :case_type, type: String
7
+ field :case_state, type: String
8
+ field :market_sector, type: String
9
+ field :outcome_type, type: String
10
+
11
+ GOVSPEAK_FIELDS = Edition::GOVSPEAK_FIELDS + [:body]
12
+
13
+ def whole_body
14
+ self.body
15
+ end
16
+ end
@@ -1,53 +1,149 @@
1
1
  class SlugValidator < ActiveModel::EachValidator
2
2
  # implement the method called during validation
3
3
  def validate_each(record, attribute, value)
4
- if value.to_s =~ /^done\/(.+)/
5
- parts = [$1]
6
- elsif value.to_s =~ /\Aforeign-travel-advice\/(.+)/ and record.kind == 'travel-advice'
7
- parts = [$1]
8
- elsif record.respond_to?(:kind) and record.kind == 'help_page'
9
- if value.to_s =~ /\Ahelp\/(.+)\z/
10
- parts = [$1]
11
- else
12
- record.errors[attribute] << "Help page slugs must have a help/ prefix"
13
- return
4
+ validators = [
5
+ DonePageValidator,
6
+ ForeignTravelAdvicePageValidator,
7
+ HelpPageValidator,
8
+ DetailedGuidePageValidator,
9
+ GovernmentPageValidator,
10
+ SpecialistDocumentPageValidator,
11
+ DefaultValidator
12
+ ].map { |klass| klass.new(record, attribute, value) }
13
+
14
+ validators.find(&:applicable?).validate!
15
+ end
16
+
17
+ protected
18
+ class InstanceValidator < Struct.new(:record, :attribute, :value)
19
+ def starts_with?(expected_prefix)
20
+ value.to_s[0...expected_prefix.size] == expected_prefix
21
+ end
22
+
23
+ def of_kind?(expected_kind)
24
+ record.respond_to?(:kind) && [*expected_kind].include?(record.kind)
25
+ end
26
+
27
+ def url_after_first_slash
28
+ value.to_s.split('/', 2)[1]
29
+ end
30
+
31
+ def url_after_first_slash_is_valid_slug!
32
+ if !valid_slug?(url_after_first_slash)
33
+ record.errors[attribute] << "must be usable in a url"
14
34
  end
15
- elsif value.to_s =~ /\Agovernment\/(.+)/ and prefixed_inside_government_format_names.include?(record.kind)
16
- parts = $1.split('/')
17
- else
18
- parts = [value.clone]
19
- end
20
-
21
- if record.respond_to?(:kind)
22
- # Inside Government formats use friendly_id to disambiguate clashes, which
23
- # potentially results in a trailing '--1' on the last path segment.
24
- # Rather than overriding the fairly robust parameterize-based validation
25
- # below, we can just fudge the friendly_id added bit
26
- if inside_government_format_names.include?(record.kind) && parts.last.include?('--')
27
- parts.last.sub!('--', '-')
35
+ end
36
+
37
+ def url_parts
38
+ value.to_s.split("/")
39
+ end
40
+
41
+ def valid_slug?(url_part)
42
+ ActiveSupport::Inflector.parameterize(url_part.to_s) == url_part.to_s
43
+ end
44
+ end
45
+
46
+ class DonePageValidator < InstanceValidator
47
+ def applicable?
48
+ starts_with?("done/")
49
+ end
50
+
51
+ def validate!
52
+ url_after_first_slash_is_valid_slug!
53
+ end
54
+ end
55
+
56
+ class ForeignTravelAdvicePageValidator < InstanceValidator
57
+ def applicable?
58
+ starts_with?("foreign-travel-advice/") && of_kind?('travel-advice')
59
+ end
60
+
61
+ def validate!
62
+ url_after_first_slash_is_valid_slug!
63
+ end
64
+ end
65
+
66
+ class HelpPageValidator < InstanceValidator
67
+ def applicable?
68
+ of_kind?('help_page')
69
+ end
70
+
71
+ def validate!
72
+ record.errors[attribute] << "Help page slugs must have a help/ prefix" unless starts_with?("help/")
73
+ url_after_first_slash_is_valid_slug!
74
+ end
75
+ end
76
+
77
+ class WhitehallFormatValidator < InstanceValidator
78
+ def url_parts
79
+ normalize_last_part_for_friendly_id(super)
80
+ end
81
+
82
+ def validate!
83
+ unless url_parts.all? { |url_part| valid_slug?(url_part) }
84
+ record.errors[attribute] << "must be usable in a URL"
28
85
  end
86
+ end
87
+
88
+ protected
29
89
 
30
- if prefixed_inside_government_format_names.include?(record.kind)
31
- unless value.to_s =~ /\Agovernment\/(.+)/
32
- record.errors[attribute] << "Inside Government slugs must have a government/ prefix"
33
- end
90
+ def normalize_last_part_for_friendly_id(url_parts)
91
+ url_parts[0...-1] + url_parts[-1..-1].map do |url_part|
92
+ normalize_for_friendly_id(url_part)
34
93
  end
35
94
  end
36
95
 
37
- parts.each do |part|
38
- unless ActiveSupport::Inflector.parameterize(part.to_s) == part.to_s
96
+ def normalize_for_friendly_id(url_part)
97
+ url_part.sub('--', '-')
98
+ end
99
+
100
+ end
101
+
102
+ class DetailedGuidePageValidator < WhitehallFormatValidator
103
+ def applicable?
104
+ of_kind?('detailed_guide')
105
+ end
106
+ end
107
+
108
+ class GovernmentPageValidator < WhitehallFormatValidator
109
+ def applicable?
110
+ record.respond_to?(:kind) && prefixed_whitehall_format_names.include?(record.kind)
111
+ end
112
+
113
+ def validate!
114
+ record.errors[attribute] << "Inside Government slugs must have a government/ prefix" unless starts_with?('government/')
115
+ super
116
+ end
117
+
118
+ protected
119
+ def prefixed_whitehall_format_names
120
+ Artefact::FORMATS_BY_DEFAULT_OWNING_APP["whitehall"] - ["detailed_guide"]
121
+ end
122
+ end
123
+
124
+ class SpecialistDocumentPageValidator < WhitehallFormatValidator
125
+ def applicable?
126
+ of_kind?('specialist-document')
127
+ end
128
+
129
+ def validate!
130
+ unless url_parts.size == 2
131
+ record.errors[attribute] << "must be of form <finder-slug>/<specialist-document-slug>"
132
+ end
133
+ unless url_parts.all? { |url_part| valid_slug?(url_part) }
39
134
  record.errors[attribute] << "must be usable in a URL"
40
135
  end
41
136
  end
42
137
  end
43
138
 
44
- private
45
- def inside_government_format_names
46
- Artefact::FORMATS_BY_DEFAULT_OWNING_APP["whitehall"]
139
+ class DefaultValidator < InstanceValidator
140
+ def applicable?
141
+ true
47
142
  end
48
143
 
49
- def prefixed_inside_government_format_names
50
- inside_government_format_names - ["detailed_guide"]
144
+ def validate!
145
+ record.errors[attribute] << "must be usable in a url" unless valid_slug?(value)
51
146
  end
147
+ end
52
148
 
53
149
  end
@@ -213,6 +213,12 @@ FactoryGirl.define do
213
213
  end
214
214
  end
215
215
 
216
+ factory :specialist_document_edition do
217
+ sequence(:slug) {|n| "test-specialist-document-#{n}" }
218
+ sequence(:title) {|n| "Test Specialist Document #{n}" }
219
+ summary "My summary"
220
+ end
221
+
216
222
  factory :simple_smart_answer_edition do
217
223
  panopticon_id {
218
224
  a = create(:artefact)
@@ -1,4 +1,4 @@
1
1
  module GovukContentModels
2
2
  # Changing this causes Jenkins to tag and release the gem into the wild
3
- VERSION = "6.3.0"
3
+ VERSION = "6.4.0"
4
4
  end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+
3
+ require "test_helper"
4
+
5
+ class SpecialistDocumentEditionTest < ActiveSupport::TestCase
6
+ should "have correct fields" do
7
+ fields = {
8
+ slug: 'cma-cases/merger-investigation-2014',
9
+ title: "Merger Investigation 2014",
10
+ summary: "This is the summary of stuff going on in the Merger Investigation 2014",
11
+ state: "published"
12
+ }
13
+
14
+ edition = SpecialistDocumentEdition.new(fields)
15
+
16
+ assert_equal fields[:title], edition.title
17
+ end
18
+
19
+ should "be persistable" do
20
+ artefact = FactoryGirl.create(:artefact)
21
+ edition = SpecialistDocumentEdition.create!(
22
+ slug: 'cma-cases/merger-investigation-2014',
23
+ title: "Merger Investigation 2014",
24
+ summary: "This is the summary of stuff going on in the Merger Investigation 2014",
25
+ state: "published",
26
+ panopticon_id: artefact.id
27
+ )
28
+
29
+ found = SpecialistDocumentEdition.where(slug: edition.slug).first
30
+ assert_equal found.attributes, edition.attributes
31
+ end
32
+ end
33
+
@@ -12,31 +12,49 @@ class SlugTest < ActiveSupport::TestCase
12
12
  validates :slug, presence: true, uniqueness: true, slug: true
13
13
  end
14
14
 
15
- context "Slugs are checked" do
16
- should "validate slugs for normal documents" do
17
- record = Dummy.new(name: "Test", slug: "test")
18
- assert record.valid?
19
- end
15
+ def document_with_slug(slug, override_options = {})
16
+ default_options = {
17
+ name: "Test",
18
+ slug: slug
19
+ }
20
+ Dummy.new(default_options.merge(override_options))
21
+ end
20
22
 
21
- should "validate help pages as starting with /help" do
22
- record = Dummy.new(name: "Help 1", slug: "test", kind: "help_page")
23
- assert record.invalid?
23
+ context "default slugs" do
24
+ should "reject url paths" do
25
+ refute document_with_slug("path/not-allowed").valid?
26
+ end
24
27
 
25
- record.slug = "help/test"
26
- assert record.valid?
28
+ should "allow a normal slug" do
29
+ assert document_with_slug("normal-slug").valid?
27
30
  end
31
+ end
28
32
 
29
- should "validate inside government slugs as containing /government" do
30
- record = Dummy.new(name: "Test 2", slug: "test", kind: "policy")
31
- assert record.invalid?
33
+ context "Help pages" do
34
+ should "must start with help/" do
35
+ refute document_with_slug("test", kind: "help_page").valid?
36
+ assert document_with_slug("help/test", kind: "help_page").valid?
37
+ end
38
+ end
32
39
 
33
- record.slug = "government/test"
34
- assert record.valid?
40
+ context "Inside government slugs" do
41
+ should "allow slug starting government/" do
42
+ refute document_with_slug("test", kind: "policy").valid?
43
+ assert document_with_slug("government/test", kind: "policy").valid?
35
44
  end
36
45
 
37
46
  should "allow friendly_id suffixes to pass" do
38
- record = Dummy.new(name: "Test 3", slug: "government/policy/test--3", kind: "policy")
39
- assert record.valid?
47
+ assert document_with_slug("government/policy/test--3", kind: "policy").valid?
48
+ end
49
+ end
50
+
51
+ context "Specialist documents" do
52
+ should "all url nested one level deep" do
53
+ assert document_with_slug("some-finder/my-specialist-document", kind: "specialist-document").valid?
54
+ end
55
+
56
+ should "not allow deeper nesting" do
57
+ refute document_with_slug("some-finder/my-specialist-document/not-allowed", kind: "specialist-document").valid?
40
58
  end
41
59
  end
42
60
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_content_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.3.0
4
+ version: 6.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-06 00:00:00.000000000 Z
12
+ date: 2014-02-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bson_ext
@@ -377,6 +377,7 @@ files:
377
377
  - app/models/simple_smart_answer_edition.rb
378
378
  - app/models/simple_smart_answer_edition/node.rb
379
379
  - app/models/simple_smart_answer_edition/node/option.rb
380
+ - app/models/specialist_document_edition.rb
380
381
  - app/models/tag.rb
381
382
  - app/models/transaction_edition.rb
382
383
  - app/models/travel_advice_edition.rb
@@ -426,6 +427,7 @@ files:
426
427
  - test/models/simple_smart_answer_edition_test.rb
427
428
  - test/models/simple_smart_answer_node_test.rb
428
429
  - test/models/simple_smart_answer_option_test.rb
430
+ - test/models/specialist_document_edition_test.rb
429
431
  - test/models/tag_test.rb
430
432
  - test/models/time_zone_test.rb
431
433
  - test/models/transaction_edition_test.rb
@@ -454,7 +456,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
454
456
  version: '0'
455
457
  segments:
456
458
  - 0
457
- hash: 1683068425110248072
459
+ hash: 2506025069756162727
458
460
  required_rubygems_version: !ruby/object:Gem::Requirement
459
461
  none: false
460
462
  requirements:
@@ -463,7 +465,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
463
465
  version: '0'
464
466
  segments:
465
467
  - 0
466
- hash: 1683068425110248072
468
+ hash: 2506025069756162727
467
469
  requirements: []
468
470
  rubyforge_project:
469
471
  rubygems_version: 1.8.23
@@ -498,6 +500,7 @@ test_files:
498
500
  - test/models/simple_smart_answer_edition_test.rb
499
501
  - test/models/simple_smart_answer_node_test.rb
500
502
  - test/models/simple_smart_answer_option_test.rb
503
+ - test/models/specialist_document_edition_test.rb
501
504
  - test/models/tag_test.rb
502
505
  - test/models/time_zone_test.rb
503
506
  - test/models/transaction_edition_test.rb