govuk_content_models 41.1.1 → 42.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -76,24 +76,6 @@ class SlugTest < ActiveSupport::TestCase
76
76
  end
77
77
  end
78
78
 
79
- context "Specialist sector browse pages" do
80
- should "allow a single path part" do
81
- assert document_with_slug("oil-and-gas", kind: "specialist_sector").valid?
82
- end
83
-
84
- should "allow two path parts" do
85
- assert document_with_slug("oil-and-gas/fields-and-wells", kind: "specialist_sector").valid?
86
- end
87
-
88
- should "not allow three path parts" do
89
- refute document_with_slug("oil-and-gas/fields-and-wells/development", kind: "specialist_sector").valid?
90
- end
91
-
92
- should "not allow invalid path segments" do
93
- refute document_with_slug("oil-and-gas/not.a.valid.slug", kind: "specialist_sector").valid?
94
- end
95
- end
96
-
97
79
  context "Detailed guides slugs" do
98
80
  should "allow a '/' in the slug" do
99
81
  assert document_with_slug("guidance/british-forces-overseas-posting-cyprus", kind: "detailed_guide").valid?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_content_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 41.1.1
4
+ version: 42.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Battley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-24 00:00:00.000000000 Z
11
+ date: 2016-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bson_ext
@@ -335,7 +335,6 @@ files:
335
335
  - app/models/business_support_edition.rb
336
336
  - app/models/campaign_edition.rb
337
337
  - app/models/completed_transaction_edition.rb
338
- - app/models/curated_list.rb
339
338
  - app/models/downtime.rb
340
339
  - app/models/edition.rb
341
340
  - app/models/guide_edition.rb
@@ -353,7 +352,6 @@ files:
353
352
  - app/models/simple_smart_answer_edition.rb
354
353
  - app/models/simple_smart_answer_edition/node.rb
355
354
  - app/models/simple_smart_answer_edition/node/option.rb
356
- - app/models/tag.rb
357
355
  - app/models/transaction_edition.rb
358
356
  - app/models/travel_advice_edition.rb
359
357
  - app/models/user.rb
@@ -361,14 +359,10 @@ files:
361
359
  - app/models/workflow.rb
362
360
  - app/traits/attachable.rb
363
361
  - app/traits/recordable_actions.rb
364
- - app/traits/taggable.rb
365
- - app/validators/browse_page_validator.rb
366
362
  - app/validators/link_validator.rb
367
363
  - app/validators/reviewer_validator.rb
368
364
  - app/validators/safe_html.rb
369
365
  - app/validators/slug_validator.rb
370
- - app/validators/tag_id_validator.rb
371
- - app/validators/topic_validator.rb
372
366
  - config/mongoid.yml
373
367
  - govuk_content_models.gemspec
374
368
  - jenkins.sh
@@ -399,12 +393,10 @@ files:
399
393
  - lib/govuk_content_models/test_helpers/local_services.rb
400
394
  - lib/govuk_content_models/version.rb
401
395
  - lib/mongoid/monkey_patches.rb
402
- - test/fixtures/contactotron_api_response.json
403
396
  - test/fixtures/uploads/image.jpg
404
397
  - test/models/action_test.rb
405
398
  - test/models/artefact_action_test.rb
406
399
  - test/models/artefact_external_link_test.rb
407
- - test/models/artefact_tag_test.rb
408
400
  - test/models/artefact_test.rb
409
401
  - test/models/business_support/business_size_test.rb
410
402
  - test/models/business_support/business_type_test.rb
@@ -416,7 +408,6 @@ files:
416
408
  - test/models/business_support_edition_test.rb
417
409
  - test/models/campaign_edition_test.rb
418
410
  - test/models/completed_transaction_edition_test.rb
419
- - test/models/curated_list_test.rb
420
411
  - test/models/downtime_test.rb
421
412
  - test/models/edition_scheduled_for_publishing_test.rb
422
413
  - test/models/edition_test.rb
@@ -431,7 +422,6 @@ files:
431
422
  - test/models/simple_smart_answer_edition_test.rb
432
423
  - test/models/simple_smart_answer_node_test.rb
433
424
  - test/models/simple_smart_answer_option_test.rb
434
- - test/models/tag_test.rb
435
425
  - test/models/time_zone_test.rb
436
426
  - test/models/transaction_edition_test.rb
437
427
  - test/models/travel_advice_edition_test.rb
@@ -440,13 +430,9 @@ files:
440
430
  - test/models/workflow_test.rb
441
431
  - test/test_helper.rb
442
432
  - test/traits/attachable_test.rb
443
- - test/traits/taggable_test.rb
444
- - test/validators/browse_page_validator_test.rb
445
433
  - test/validators/link_validator_test.rb
446
434
  - test/validators/safe_html_validator_test.rb
447
435
  - test/validators/slug_validator_test.rb
448
- - test/validators/tag_id_validator_test.rb
449
- - test/validators/topic_validator_test.rb
450
436
  homepage: https://github.com/alphagov/govuk_content_models
451
437
  licenses: []
452
438
  metadata: {}
@@ -472,12 +458,10 @@ signing_key:
472
458
  specification_version: 4
473
459
  summary: Shared models for Panopticon and Publisher, as a Rails Engine
474
460
  test_files:
475
- - test/fixtures/contactotron_api_response.json
476
461
  - test/fixtures/uploads/image.jpg
477
462
  - test/models/action_test.rb
478
463
  - test/models/artefact_action_test.rb
479
464
  - test/models/artefact_external_link_test.rb
480
- - test/models/artefact_tag_test.rb
481
465
  - test/models/artefact_test.rb
482
466
  - test/models/business_support/business_size_test.rb
483
467
  - test/models/business_support/business_type_test.rb
@@ -489,7 +473,6 @@ test_files:
489
473
  - test/models/business_support_edition_test.rb
490
474
  - test/models/campaign_edition_test.rb
491
475
  - test/models/completed_transaction_edition_test.rb
492
- - test/models/curated_list_test.rb
493
476
  - test/models/downtime_test.rb
494
477
  - test/models/edition_scheduled_for_publishing_test.rb
495
478
  - test/models/edition_test.rb
@@ -504,7 +487,6 @@ test_files:
504
487
  - test/models/simple_smart_answer_edition_test.rb
505
488
  - test/models/simple_smart_answer_node_test.rb
506
489
  - test/models/simple_smart_answer_option_test.rb
507
- - test/models/tag_test.rb
508
490
  - test/models/time_zone_test.rb
509
491
  - test/models/transaction_edition_test.rb
510
492
  - test/models/travel_advice_edition_test.rb
@@ -513,10 +495,6 @@ test_files:
513
495
  - test/models/workflow_test.rb
514
496
  - test/test_helper.rb
515
497
  - test/traits/attachable_test.rb
516
- - test/traits/taggable_test.rb
517
- - test/validators/browse_page_validator_test.rb
518
498
  - test/validators/link_validator_test.rb
519
499
  - test/validators/safe_html_validator_test.rb
520
500
  - test/validators/slug_validator_test.rb
521
- - test/validators/tag_id_validator_test.rb
522
- - test/validators/topic_validator_test.rb
@@ -1,28 +0,0 @@
1
- require "traits/taggable"
2
- require_dependency "safe_html"
3
-
4
- class CuratedList
5
- include Mongoid::Document
6
- include Mongoid::Timestamps
7
-
8
- include Taggable
9
- stores_tags_for :sections
10
-
11
- field "slug", type: String
12
- has_and_belongs_to_many :artefacts, class_name: "Artefact"
13
-
14
- index slug: 1
15
-
16
- validates :slug, presence: true, uniqueness: true, slug: true
17
-
18
- def self.find_by_slug(slug)
19
- where(slug: slug).first
20
- end
21
-
22
- # Returns the artefacts in order, skipping missing artefacts
23
- def artefacts
24
- Artefact.where(:_id.in => artefact_ids).sort_by do |artefact|
25
- artefact_ids.index(artefact.id)
26
- end
27
- end
28
- end
data/app/models/tag.rb DELETED
@@ -1,113 +0,0 @@
1
- require_dependency "safe_html"
2
- require 'tag_id_validator'
3
- require 'state_machines-mongoid'
4
-
5
- class Tag
6
- include Mongoid::Document
7
-
8
- field :tag_id, type: String
9
- field :title, type: String
10
- field :tag_type, type: String #TODO: list of accepted types?
11
- field :description, type: String
12
- field :short_description, type: String
13
- field :parent_id, type: String
14
- field :state, type: String, default: 'draft'
15
- field :content_id, type: String
16
-
17
- STATES = ['draft', 'live']
18
-
19
- index tag_id: 1
20
- index({ tag_id: 1, tag_type: 1 }, unique: true)
21
- index tag_type: 1
22
-
23
- validates_presence_of :tag_id, :title, :tag_type
24
- validates_uniqueness_of :tag_id, scope: :tag_type
25
- validates_with TagIdValidator
26
-
27
- validates :state, inclusion: { in: STATES }
28
-
29
- class MissingTags < RuntimeError
30
- attr_reader :tag_ids
31
-
32
- def initialize(tag_ids)
33
- super("Missing tags: #{tag_ids.join(", ")}")
34
- @tag_ids = tag_ids
35
- end
36
- end
37
-
38
- # This doesn't get set automatically: the code that loads tags
39
- # should go through them and set this attribute manually
40
- attr_accessor :uniquely_named
41
-
42
- state_machine initial: :draft do
43
- event :publish do
44
- transition draft: :live
45
- end
46
- end
47
-
48
- def as_json(options = {})
49
- {
50
- id: self.tag_id,
51
- title: self.title,
52
- type: self.tag_type,
53
- description: self.description,
54
- short_description: self.short_description
55
- }
56
- end
57
-
58
- def has_parent?
59
- parent_id.present?
60
- end
61
-
62
- def parent
63
- Tag.by_tag_id(parent_id, type: self.tag_type, draft: true) if has_parent?
64
- end
65
-
66
- def unique_title
67
- self.uniquely_named ? self.title : "#{self.title} [#{self.tag_id}]"
68
- end
69
-
70
- def to_s
71
- title
72
- end
73
-
74
- def self.by_tag_id(tag_id, tag_type_or_options = nil)
75
- by_tag_ids([tag_id], tag_type_or_options).first
76
- end
77
-
78
- def self.by_tag_ids(tag_id_list, tag_type_or_options = nil)
79
- if tag_type_or_options.is_a?(String)
80
- # Providing the type as a string argument is deprecated in favour of providing the type as an option
81
- options = {type: tag_type_or_options}
82
- else
83
- options = tag_type_or_options || {}
84
- end
85
-
86
- tag_scope = options[:type] ? Tag.where(tag_type: options[:type]) : Tag
87
-
88
- unless options[:draft]
89
- tag_scope = tag_scope.where(:state.ne => 'draft')
90
- end
91
-
92
- tag_scope = tag_scope.any_in(tag_id: tag_id_list)
93
-
94
- # Sort by id list because MongoID 2.x doesn't preserve order
95
- tags_by_id = tag_scope.each_with_object({}) do |tag, hash|
96
- hash[tag.tag_id] = tag
97
- end
98
- tag_id_list.map { |tag_id| tags_by_id[tag_id] }.compact
99
- end
100
-
101
- def self.by_tag_types_and_ids(tag_types_and_ids)
102
- list = tag_types_and_ids.map {|hash| hash.slice(:tag_id, :tag_type) }
103
- any_of(list)
104
- end
105
-
106
- # Validate a list of tags by tag ID. Any missing tags raise an exception.
107
- # Draft tags are considered present for internal validation.
108
- def self.validate_tag_ids(tag_id_list, tag_type = nil)
109
- found_tags = by_tag_ids(tag_id_list, type: tag_type, draft: true)
110
- missing_tag_ids = tag_id_list - found_tags.map(&:tag_id)
111
- raise MissingTags.new(missing_tag_ids) if missing_tag_ids.any?
112
- end
113
- end
@@ -1,99 +0,0 @@
1
- module Taggable
2
- module ClassMethods
3
- def stores_tags_for(*tag_types)
4
- tag_types = tag_types.map {|tag_type|
5
- raise ArgumentError.new("Please provide tag types as symbols") unless tag_type.is_a?(Symbol)
6
- tag_type.to_s
7
- }
8
-
9
- class_attribute :tag_types
10
- self.tag_types = tag_types
11
-
12
- tag_types.each do |tag_type|
13
- define_method("#{tag_type}=") do |tag_ids|
14
- set_tags_of_type(tag_type, tag_ids)
15
- end
16
- alias_method :"#{tag_type.singularize}_ids=", :"#{tag_type}="
17
-
18
- define_method(tag_type) do |*args|
19
- include_draft = args.first
20
- tags_of_type(tag_type.singularize, include_draft)
21
- end
22
-
23
- define_method("#{tag_type.singularize}_ids") do |*args|
24
- send(tag_type, *args).map(&:tag_id)
25
- end
26
- end
27
- end
28
-
29
- def has_primary_tag_for(*tag_types)
30
- tag_types = tag_types.map {|tag_type|
31
- raise ArgumentError.new("Please provide tag types as symbols") unless tag_type.is_a?(Symbol)
32
- tag_type.to_s
33
- }
34
-
35
- class_attribute :primary_tag_types
36
- self.primary_tag_types = tag_types
37
-
38
- tag_types.each do |tag_type|
39
- define_method("primary_#{tag_type}=") do |tag_id|
40
- set_primary_tag_of_type(tag_type, tag_id)
41
- end
42
-
43
- define_method("primary_#{tag_type}") do
44
- tags_of_type(tag_type).first
45
- end
46
- end
47
- end
48
- end
49
-
50
- def self.included(klass)
51
- klass.extend ClassMethods
52
- klass.field :tag_ids, type: Array, default: []
53
- klass.field :tags, type: Array, default: []
54
-
55
- klass.index tag_ids: 1
56
- klass.__send__ :private, :tag_ids=
57
- end
58
-
59
- def set_tags_of_type(collection_name, tag_ids)
60
- tag_type = collection_name.singularize
61
- tag_ids = Array(tag_ids)
62
-
63
- Tag.validate_tag_ids(tag_ids, tag_type)
64
-
65
- current_tags = attributes['tags'].reject {|t| t['tag_type'] == tag_type }
66
-
67
- self.tags = current_tags + tag_ids.map {|tag_id|
68
- {'tag_id' => tag_id, 'tag_type' => tag_type}
69
- }
70
- end
71
-
72
- # The primary tag is simply the first one of its
73
- # type. If that tag is already applied this method
74
- # moves it to the start of the list. If it's not then
75
- # we add it at the start of the list.
76
- def set_primary_tag_of_type(tag_type, tag_id)
77
- Tag.validate_tag_ids([tag_id], tag_type)
78
-
79
- tag_tuple = {'tag_id' => tag_id, 'tag_type' => tag_type}
80
-
81
- current_tags = attributes['tags'].dup
82
- current_tags.delete(tag_tuple)
83
-
84
- self.tags = current_tags.unshift(tag_tuple)
85
- end
86
-
87
- def tags_of_type(tag_type, include_draft = false)
88
- tags(include_draft).select { |t| t.tag_type == tag_type }
89
- end
90
-
91
- def tags=(new_tag_tuples)
92
- self.tag_ids = new_tag_tuples.map {|tuple| tuple['tag_id'] }
93
- super(new_tag_tuples)
94
- end
95
-
96
- def tags(include_draft = false)
97
- Tag.by_tag_ids(tag_ids, draft: include_draft)
98
- end
99
- end
@@ -1,9 +0,0 @@
1
- class BrowsePageValidator < ActiveModel::Validator
2
- def validate(record)
3
- if (browse_pages = record.browse_pages)
4
- if browse_pages.uniq.count < browse_pages.count
5
- record.errors.add(:browse_pages, "can't have duplicates")
6
- end
7
- end
8
- end
9
- end
@@ -1,37 +0,0 @@
1
- class TagIdValidator < ActiveModel::Validator
2
-
3
- def validate(record)
4
- unless valid_tag_id?(record)
5
- record.errors[:tag_id] << "ID must be valid in a URL and have no more than one slash"
6
- end
7
- end
8
-
9
- private
10
-
11
- def valid_tag_id?(tag)
12
- tag_contains_correct_characters(tag.tag_id) &&
13
- tag_doesnt_end_with_slash(tag.tag_id) &&
14
- tag_contains_correct_number_of_slashes(tag.tag_id, child?: tag_is_child_tag?(tag))
15
- end
16
-
17
- def tag_contains_correct_characters(tag_id)
18
- tag_id =~ %r{^[a-z0-9/-]+$}
19
- end
20
-
21
- def tag_doesnt_end_with_slash(tag_id)
22
- !tag_id.end_with?('/')
23
- end
24
-
25
- def tag_contains_correct_number_of_slashes(tag_id, options = {})
26
- if options[:child?]
27
- tag_id.count('/') <= 1
28
- else
29
- tag_id.count('/') == 0
30
- end
31
- end
32
-
33
- def tag_is_child_tag?(tag)
34
- tag.respond_to?(:parent_id) && tag.parent_id.present?
35
- end
36
-
37
- end
@@ -1,14 +0,0 @@
1
- class TopicValidator < ActiveModel::Validator
2
- def validate(record)
3
- if (additional_topics = record.additional_topics)
4
- if additional_topics.uniq.count < additional_topics.count
5
- record.errors.add(:additional_topics, "can't have duplicates")
6
- end
7
-
8
- if additional_topics.include?(record.primary_topic)
9
- record.errors.add(:base, "You can't have the primary topic set as an additional topic")
10
- record.errors.add(:additional_topics, "can't have the primary topic set as an additional topic")
11
- end
12
- end
13
- end
14
- end
@@ -1 +0,0 @@
1
- {"created_at":"2011-12-02T12:02:43Z","email_address":"contact@example.com","id":189,"name":"Contact Name","opening_hours":null,"postal_address":"1 High Street\nTown","updated_at":"2011-12-02T12:02:43Z","website_url":"http://www.example.com/","phone_numbers":[{"contact_id":189,"created_at":"2011-12-02T12:02:43Z","id":447,"kind":"phone","label":null,"updated_at":"2011-12-02T12:02:43Z","value":"0113 496 0123"},{"contact_id":189,"created_at":"2011-12-02T12:02:43Z","id":448,"kind":"fax","label":null,"updated_at":"2011-12-02T12:02:43Z","value":"028 9018 1337"}]}
@@ -1,50 +0,0 @@
1
- require "test_helper"
2
-
3
- class ArtefactTagTest < ActiveSupport::TestCase
4
-
5
- TEST_KEYWORDS = [['cheese', 'Cheese'], ['bacon', 'Bacon']]
6
-
7
- setup do
8
- parent_section = FactoryGirl.create(:live_tag, :tag_id => 'crime', :tag_type => 'section', :title => 'Crime')
9
- FactoryGirl.create(:live_tag, :tag_id => 'crime/the-police', :tag_type => 'section', :title => 'The Police', :parent_id => parent_section.id)
10
- FactoryGirl.create(:live_tag, :tag_id => 'crime/batman', :tag_type => 'section', :title => 'Batman', :parent_id => parent_section.id)
11
-
12
- TEST_KEYWORDS.each do |tag_id, title|
13
- FactoryGirl.create(:live_tag, :tag_id => tag_id, :tag_type => 'keyword', :title => title)
14
- end
15
- end
16
-
17
- test "return primary section title when asked for its section" do
18
- a = FactoryGirl.create(:artefact)
19
- a.sections = ['crime', 'crime/the-police']
20
- a.primary_section = 'crime'
21
-
22
- assert_equal 'Crime', a.section
23
- end
24
-
25
- test "returns title of parent and child tags when its primary section has a parent" do
26
- parent = Tag.by_tag_id('crime', 'section')
27
- child = Tag.by_tag_id('crime/batman', 'section')
28
- child.update_attributes parent_id: parent.tag_id
29
-
30
- a = FactoryGirl.create(:artefact)
31
- a.primary_section = child.tag_id
32
-
33
- assert_equal "#{parent.title}:#{child.title}", a.section
34
- end
35
-
36
- test "stores the tag type and tag id for each tag" do
37
- a = FactoryGirl.create(:artefact)
38
-
39
- a.sections = ['crime', 'crime/the-police']
40
- a.keywords = ['bacon']
41
-
42
- expected_tags = [
43
- { "tag_id" => "crime", "tag_type" => "section" },
44
- { "tag_id" => "crime/the-police", "tag_type" => "section" },
45
- { "tag_id" => "bacon", "tag_type" => "keyword" },
46
- ]
47
- assert_equal ["crime", "crime/the-police", "bacon"], a.tag_ids
48
- assert_equal expected_tags, a.attributes["tags"]
49
- end
50
- end
@@ -1,32 +0,0 @@
1
- require "test_helper"
2
-
3
- class CuratedListTest < ActiveSupport::TestCase
4
- test "should validate format of slug" do
5
- cl = CuratedList.new(slug: 'I am not a valid slug')
6
- assert !cl.valid?
7
- assert cl.errors[:slug].any?, "Doesn't have error on slug"
8
- end
9
-
10
- test "should include ability to have a section tag" do
11
- cl = FactoryGirl.create(:curated_list)
12
- tag = FactoryGirl.create(:live_tag, tag_id: 'batman', title: 'Batman', tag_type: 'section')
13
-
14
- cl.sections = ['batman']
15
- cl.save
16
-
17
- assert_equal [tag], cl.sections
18
- end
19
-
20
- test "should return artefacts in relationship order, not their natural order" do
21
- a = FactoryGirl.create(:artefact, name: "A")
22
- b = FactoryGirl.create(:artefact, name: "B")
23
- cl = FactoryGirl.create(:curated_list, artefact_ids: [b._id, a._id])
24
- assert_equal ["B", "A"], cl.artefacts.map(&:name)
25
- end
26
-
27
- test "should translate string IDs to BSON::ObjectIds for artefacts set via artefact_ids" do
28
- a = FactoryGirl.create(:artefact, name: "A")
29
- cl = FactoryGirl.create(:curated_list, artefact_ids: [a.id.to_s])
30
- assert cl.artefact_ids.first.is_a?(BSON::ObjectId)
31
- end
32
- end