Permalink
Browse files

Merge commit 'eecbd479106ac166360697886e6f44cecfd622dd' into HEAD

  • Loading branch information...
2 parents a9ee009 + eecbd47 commit cb868976db6c26c7ff489d0113ce28c1263fea34 Jenkins committed May 3, 2012
View
19 app/controllers/tags_controller.rb
@@ -0,0 +1,19 @@
+class TagsController < ApplicationController
+ respond_to :json
+
+ def index
+ @tags = TagRepository.load_all
+ # TODO: links: [next_page, prev_page]
+ respond_with(:status => 'ok', :total => @tags.count, :from => 0, :to => @tags.count - 1,
+ :pagesize => @tags.count, :results => @tags)
+ end
+
+ def show
+ @tag = TagRepository.load(params[:id])
+ if not @tag
+ head :not_found and return
+ end
+ respond_with(:status=>'ok', :tag => @tag)
+ end
+
+end
View
27 app/models/artefact.rb
@@ -21,6 +21,7 @@ class Artefact
field "relatedness_done", type: Boolean, default: false
field "publication_id", type: String
field "business_proposition", type: Boolean, default: false
+ field "tag_ids", type: Array
MAXIMUM_RELATED_ITEMS = 8
@@ -52,6 +53,8 @@ class Artefact
validates :kind, :inclusion => { :in => FORMATS }
validates_presence_of :owning_app
+ before_save :save_section_as_tags
+
# TODO: Remove this 'unless' hack after importing. It's only here because
# some old entries in Panopticon lack a need_id.
validates_presence_of :need_id, :unless => lambda { defined? IMPORTING_LEGACY_DATA }
@@ -64,6 +67,24 @@ def self.find_by_slug(s)
where(slug: s).first
end
+
+ def save_section_as_tags
+ return if self.section.blank?
+
+ # goes from 'Crime and Justice:The police'
+ # to 'crime-and-justice', 'the-police'
+ # tag_ids: 'crime-and-justice', 'crime-and-justice/the-police'
+ section, sub_section = self.section.downcase.gsub(' ', '-').split(':')
+
+ tag_ids = [section]
+ tag_ids.push "#{section}/#{sub_section}" unless sub_section.blank?
+
+ tag_ids.each do |tag_id|
+ raise "missing tag #{tag_id}" unless TagRepository.load(tag_id)
+ end
+ self.tag_ids = tag_ids
+ end
+
def normalise
return unless kind.present?
self.kind = KIND_TRANSLATIONS[kind.to_s.downcase.strip]
@@ -79,6 +100,12 @@ def as_json(options={})
super(options.merge(
include: {contact: {}}
)).tap { |hash|
+ if hash['tag_ids']
+ hash['tag_ids'] = hash['tag_ids'].map { |tag_id| TagRepository.load(tag_id).as_json }
+ else
+ hash.delete 'tag_ids'
+ end
+
unless options[:ignore_related_artefacts]
hash["related_items"] = related_artefacts.map { |a| {"artefact" => a.as_json(ignore_related_artefacts: true)} }
end
View
18 app/models/tag.rb
@@ -0,0 +1,18 @@
+class Tag
+ include Mongoid::Document
+ field :tag_id, :type => String
+ field :title, :type => String
+ field :tag_type, :type => String #TODO: list of accepted types?
+
+ index :tag_id, :unique => true
+
+ validates_presence_of :tag_id, :title, :tag_type
+
+ def as_json(options={})
+ {
+ :id => self.tag_id,
+ :title => self.title,
+ :type => self.tag_type
+ }
+ end
+end
View
3 app/models/user.rb
@@ -10,10 +10,13 @@ class User
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :name, :uid, :version
+ # GDS::SSO specifically looks for find_by_uid within warden
+ # when loading authentication user from session
def self.find_by_uid(uid)
where(uid: uid).first
end
+ # GDS::SSO override for first time authentication of the app
def self.find_for_gds_oauth(auth_hash)
find_by_uid(auth_hash["uid"]) || create_from_auth_hash(auth_hash)
end
View
19 app/repositories/tag_repository.rb
@@ -0,0 +1,19 @@
+module TagRepository
+
+ def self.load_all
+ Tag.all
+ end
+
+ def self.load(id)
+ Tag.where(:tag_id => id).first
+ end
+
+ def self.put(tag)
+ t = Tag.where(:tag_id => tag[:tag_id]).first
+ unless t
+ Tag.create! tag
+ else
+ t.update_attributes! tag
+ end
+ end
+end
View
2 config/application.rb
@@ -19,7 +19,7 @@ class Application < Rails::Application
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.
- # config.autoload_paths += %W(#{config.root}/extras)
+ # config.autoload_paths += %W(#{config.root}/app/repositories)
# Only load the plugins named here, in the order given (default is alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
View
3 config/routes.rb
@@ -1,6 +1,9 @@
Panopticon::Application.routes.draw do
resources :artefacts
+ resources :tags, :defaults => {:format => 'json'}
+ match 'tags/:id' => 'tags#show', :id => /[^\.]+/, :defaults => {:format => 'json'}
+
match 'google_insight' => 'seo#show'
root :to => redirect("/artefacts")
View
40 lib/tasks/migrate_sections_to_tags.rake
@@ -0,0 +1,40 @@
+namespace :sections do
+
+ desc "Copy sections to be tags"
+ task :migrate_to_tags => :environment do
+
+ # for each section
+ Section.all.map do |s|
+ # split on :
+ section, sub = s.slug.split(':')
+ tagified_section = section.downcase.gsub(' ', '-')
+ t = TagRepository.load(tagified_section)
+ unless t
+ new_tag = {:tag_id => tagified_section, :title => section, :tag_type => 'section'}
+ TagRepository.put(new_tag)
+ end
+
+ tagfied_sub = "#{tagified_section}/#{sub.downcase.gsub(' ', '-')}"
+ sub_t = TagRepository.load(tagfied_sub)
+ unless sub_t
+ new_tag = {:tag_id => tagfied_sub, :title => sub, :tag_type => 'section'}
+ TagRepository.put(new_tag)
+ end
+ end
+
+ Artefact.all.each_with_index do |a, index|
+ puts index if index % 100 == 0
+ next if a.need_id.blank?
+
+ # HACK: correct the one section that was hard-coded, then changed
+ a.section = 'Work:Time off work' if a.section == 'Work:Time off'
+
+ begin
+ a.save!
+ rescue RuntimeError
+ puts "Failed to migrate section '#{a.section}' to tags"
+ end
+ end
+
+ end
+end
View
40 test/functional/tags_controller_test.rb
@@ -0,0 +1,40 @@
+require 'test_helper'
+
+class TagsControllerTest < ActionController::TestCase
+ setup do
+ login_as_stub_user
+ TagRepository.put(:tag_id => "crime", :title => "Crime", :tag_type => "section")
+ TagRepository.put(:tag_id => "crime/the-police", :title => "The Police", :tag_type => "section")
+ @tag_count = 2
+ end
+
+ context "GET /tags/:id" do
+ should "return tag" do
+ get :show, :id => "crime/the-police", :format => "json"
+ parsed = JSON.parse(response.body)
+ assert_response :success
+ assert_equal parsed["status"], "ok"
+ assert_equal parsed["tag"]["type"], "section"
+ assert_equal parsed["tag"]["id"], "crime/the-police"
+ assert_equal parsed["tag"]["title"], "The Police"
+ end
+
+ should "return 404" do
+ get :show, :id => "crime/the-mafia", :format => "json"
+ assert_response :not_found
+ end
+ end
+
+ context "GET /tags" do
+ should "return all the tags" do
+ get :index, :format => "json"
+ parsed = JSON.parse(response.body)
+ assert_response :success
+ assert_equal parsed["status"], "ok"
+ assert_equal parsed["total"], @tag_count
+ assert_equal parsed["results"].count, @tag_count
+
+ end
+ end
+
+end
View
18 test/unit/artefact_test.rb
@@ -48,4 +48,22 @@ class ArtefactTest < ActiveSupport::TestCase
Artefact.from_param('something-fake')
end
end
+
+ test "should save section as tags" do
+ TagRepository.put(:tag_id => "crime", :tag_type => "section", :title => "Crime")
+ TagRepository.put(:tag_id => "crime/the-police", :tag_type => "section", :title => "The Police")
+
+ a = Artefact.create!(:slug => "a", :name => "a", :kind => "answer", :need_id => 1,
+ :owning_app => "x", :section => "Crime:The Police")
+ assert_equal a.tag_ids, ["crime", "crime/the-police"]
+ end
+
+ test "should save top level section as tag" do
+ TagRepository.put(:tag_id => "crime", :tag_type => "section", :title => "Crime")
+
+ a = Artefact.create!(:slug => "a", :name => "a", :kind => "answer", :need_id => 1,
+ :owning_app => "x", :section => "Crime")
+ assert_equal a.tag_ids, ["crime"]
+ end
+
end

0 comments on commit cb86897

Please sign in to comment.