diff options
-rw-r--r-- | app/controllers/public_body_controller.rb | 18 | ||||
-rw-r--r-- | app/models/public_body.rb | 3 | ||||
-rw-r--r-- | app/models/public_body_tag.rb | 48 | ||||
-rw-r--r-- | db/migrate/093_move_to_has_tag_string.rb | 23 | ||||
-rw-r--r-- | db/schema.rb | 24 | ||||
-rw-r--r-- | spec/models/has_tag_string_tag_spec.rb (renamed from spec/models/public_body_tag_spec.rb) | 2 | ||||
-rw-r--r-- | todo.txt | 4 | ||||
-rw-r--r-- | vendor/plugins/has_tag_string/lib/has_tag_string.rb | 93 |
8 files changed, 124 insertions, 91 deletions
diff --git a/app/controllers/public_body_controller.rb b/app/controllers/public_body_controller.rb index 5f51948ee..560206900 100644 --- a/app/controllers/public_body_controller.rb +++ b/app/controllers/public_body_controller.rb @@ -65,24 +65,28 @@ class PublicBodyController < ApplicationController end def list + # XXX move some of these tag SQL queries into has_tag_string.rb @tag = params[:tag] if @tag.nil? @tag = "all" conditions = [] elsif @tag == 'other' category_list = PublicBodyCategories::CATEGORIES.map{|c| "'"+c+"'"}.join(",") - conditions = ['(select count(*) from public_body_tags where public_body_tags.public_body_id = public_bodies.id - and public_body_tags.name in (' + category_list + ')) = 0'] + conditions = ['(select count(*) from has_tag_string_tags where has_tag_string_tags.model_id = public_bodies.id + and has_tag_string_tags.model = \'PublicBody\' + and has_tag_string_tags.name in (' + category_list + ')) = 0'] elsif @tag.size == 1 @tag.upcase! conditions = ['first_letter = ?', @tag] elsif @tag.include?(":") - name, value = PublicBodyTag.split_tag_into_name_value(@tag) - conditions = ['(select count(*) from public_body_tags where public_body_tags.public_body_id = public_bodies.id - and public_body_tags.name = ? and public_body_tags.value = ?) > 0', name, value] + name, value = HasTagString::HasTagStringTag.split_tag_into_name_value(@tag) + conditions = ['(select count(*) from has_tag_string_tags where has_tag_string_tags.model_id = public_bodies.id + and has_tag_string_tags.model = \'PublicBody\' + and has_tag_string_tags.name = ? and has_tag_string_tags.value = ?) > 0', name, value] else - conditions = ['(select count(*) from public_body_tags where public_body_tags.public_body_id = public_bodies.id - and public_body_tags.name = ?) > 0', @tag] + conditions = ['(select count(*) from has_tag_string_tags where has_tag_string_tags.model_id = public_bodies.id + and has_tag_string_tags.model = \'PublicBody\' + and has_tag_string_tags.name = ?) > 0', @tag] end @public_bodies = PublicBody.paginate( :order => "public_bodies.name", :page => params[:page], :per_page => 1000, # fit all councils on one page diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 491ffe989..1bd9dcc94 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -42,7 +42,6 @@ class PublicBody < ActiveRecord::Base has_many :info_requests, :order => 'created_at desc' has_many :track_things, :order => 'created_at desc' - has_many :public_body_tags has_tag_string # like find_by_url_name but also search historic url_name if none found @@ -190,7 +189,7 @@ class PublicBody < ActiveRecord::Base def type_of_authority(html = false) types = [] first = true - for tag in self.public_body_tags + for tag in self.tags if PublicBodyCategories::CATEGORIES_BY_TAG.include?(tag.name) desc = PublicBodyCategories::CATEGORY_SINGULAR_BY_TAG[tag.name] if first diff --git a/app/models/public_body_tag.rb b/app/models/public_body_tag.rb deleted file mode 100644 index e24ace7d7..000000000 --- a/app/models/public_body_tag.rb +++ /dev/null @@ -1,48 +0,0 @@ -# == Schema Information -# Schema version: 92 -# -# Table name: public_body_tags -# -# id :integer not null, primary key -# public_body_id :integer not null -# name :text not null -# created_at :datetime not null -# value :text -# - -# models/public_body_tag.rb: -# Categories for public bodies. -# -# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved. -# Email: francis@mysociety.org; WWW: http://www.mysociety.org/ -# -# $Id: public_body_tag.rb,v 1.29 2009-09-17 21:10:05 francis Exp $ - -class PublicBodyTag < ActiveRecord::Base - strip_attributes! - - validates_presence_of :public_body - validates_presence_of :name - - belongs_to :public_body - - def name_and_value - ret = self.name - if !self.value.nil? - ret += ":" + self.value - end - return ret - end - - def PublicBodyTag.split_tag_into_name_value(tag) - sections = tag.split(/:/) - name = sections[0] - if sections[1] - value = sections[1,sections.size].join(":") - else - value = nil - end - return name, value - end -end - diff --git a/db/migrate/093_move_to_has_tag_string.rb b/db/migrate/093_move_to_has_tag_string.rb new file mode 100644 index 000000000..58f36c224 --- /dev/null +++ b/db/migrate/093_move_to_has_tag_string.rb @@ -0,0 +1,23 @@ +class MoveToHasTagString < ActiveRecord::Migration + def self.up + rename_table :public_body_tags, :has_tag_string_tags + + # we rename existing column: + rename_column :has_tag_string_tags, :public_body_id, :model_id + # if using has_tag_string afresh in another project, can use this: + # add_column :has_tag_string_tags, :model_id, :integer, :null => false + + # the model needs a default value, so build in stages: + add_column :has_tag_string_tags, :model, :string + HasTagString::HasTagStringTag.update_all "model = 'PublicBody'" + change_column :has_tag_string_tags, :model, :string, :null => false + # just use this for a fresh project: + # add_column :has_tag_string_tags, :model, :string, :null => false + + add_index :has_tag_string_tags, [:model, :model_id] + end + + def self.down + raise "no reverse migration" + end +end diff --git a/db/schema.rb b/db/schema.rb index 0c90be6b1..6df97a137 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 92) do +ActiveRecord::Schema.define(:version => 93) do create_table "acts_as_xapian_jobs", :force => true do |t| t.string "model", :null => false @@ -65,6 +65,18 @@ ActiveRecord::Schema.define(:version => 92) do add_index "exim_logs", ["exim_log_done_id"], :name => "index_exim_logs_on_exim_log_done_id" + create_table "has_tag_string_tags", :force => true do |t| + t.integer "model_id", :null => false + t.text "name", :null => false + t.datetime "created_at", :null => false + t.text "value" + t.string "model", :null => false + end + + add_index "has_tag_string_tags", ["model", "model_id"], :name => "index_has_tag_string_tags_on_model_and_model_id" + add_index "has_tag_string_tags", ["model_id", "name", "value"], :name => "index_public_body_tags_on_public_body_id_and_name_and_value", :unique => true + add_index "has_tag_string_tags", ["name"], :name => "index_public_body_tags_on_name" + create_table "holidays", :force => true do |t| t.date "day" t.text "description" @@ -173,16 +185,6 @@ ActiveRecord::Schema.define(:version => 92) do add_index "public_bodies", ["first_letter"], :name => "index_public_bodies_on_first_letter" add_index "public_bodies", ["url_name"], :name => "index_public_bodies_on_url_name", :unique => true - create_table "public_body_tags", :force => true do |t| - t.integer "public_body_id", :null => false - t.text "name", :null => false - t.datetime "created_at", :null => false - t.text "value" - end - - add_index "public_body_tags", ["name", "public_body_id", "value"], :name => "index_public_body_tags_on_public_body_id_and_name_and_value", :unique => true - add_index "public_body_tags", ["name"], :name => "index_public_body_tags_on_name" - create_table "public_body_versions", :force => true do |t| t.integer "public_body_id" t.integer "version" diff --git a/spec/models/public_body_tag_spec.rb b/spec/models/has_tag_string_tag_spec.rb index 09a597bd0..c85f64b14 100644 --- a/spec/models/public_body_tag_spec.rb +++ b/spec/models/has_tag_string_tag_spec.rb @@ -1,6 +1,6 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -describe PublicBodyTag, " when fiddling with public body tags " do +describe PublicBodyTag, " when fiddling with tag strings " do fixtures :public_bodies it "should be able to make a new tag and save it" do @@ -1,3 +1,7 @@ +PublicBodyTag +public_body_tags + + Next (things that will reduce admin time mainly) ==== diff --git a/vendor/plugins/has_tag_string/lib/has_tag_string.rb b/vendor/plugins/has_tag_string/lib/has_tag_string.rb index ca147ba27..b13803d23 100644 --- a/vendor/plugins/has_tag_string/lib/has_tag_string.rb +++ b/vendor/plugins/has_tag_string/lib/has_tag_string.rb @@ -1,5 +1,5 @@ # lib/has_tag_string.rb: -# Lets a model have tags, represented as space separate strings in a public # +# Lets a model have tags, represented as space separate strings in a public # interface, but stored in the database as keys. Each tag can have a value # followed by a colon - e.g. url:http://www.flourish.org # @@ -7,6 +7,39 @@ # Email: francis@mysociety.org; WWW: http://www.mysociety.org/ module HasTagString + # Represents one tag of one model. + # The migration to make this is currently only in WDTK code. + class HasTagStringTag < ActiveRecord::Base + # XXX strip_attributes! + + validates_presence_of :name + + # Return instance of the model that this tag tags + def tagged_model + return self.model.constantize.find(self.model_id) + end + + def name_and_value + ret = self.name + if !self.value.nil? + ret += ":" + self.value + end + return ret + end + + def HasTagStringTag.split_tag_into_name_value(tag) + sections = tag.split(/:/) + name = sections[0] + if sections[1] + value = sections[1,sections.size].join(":") + else + value = nil + end + return name, value + end + end + + # Methods which are added to the model instances being tagged module InstanceMethods # Given an input string of tags, sets all tags to that string. # XXX This immediately saves the new tags. @@ -16,41 +49,51 @@ module HasTagString tags = tag_string.split(/\s+/).uniq ActiveRecord::Base.transaction do - for public_body_tag in self.public_body_tags - public_body_tag.destroy + for tag in self.tags + tag.destroy end - self.public_body_tags = [] + self.tags = [] for tag in tags # see if is a machine tags (i.e. a tag which has a value) - name, value = PublicBodyTag.split_tag_into_name_value(tag) + name, value = HasTagStringTag.split_tag_into_name_value(tag) - public_body_tag = PublicBodyTag.new(:name => name, :value => value) - self.public_body_tags << public_body_tag - public_body_tag.public_body = self + tag = HasTagStringTag.new( + :model => self.class.base_class.to_s, + :model_id => self.id, + :name => name, :value => value + ) + self.tags << tag end end end + + # Returns the tags the model has, as a space separated string def tag_string - return self.public_body_tags.map { |t| t.name_and_value }.join(' ') + return self.tags.map { |t| t.name_and_value }.join(' ') end - def has_tag?(tag) - for public_body_tag in self.public_body_tags - if public_body_tag.name == tag + + # Test to see if class is tagged with the given tag + def has_tag?(tag_as_string) + for tag in self.tags + if tag.name == tag_as_string return true end end return false end + class TagNotFound < StandardError end - def get_tag_values(tag) + + # If the tag is a machine tag, returns array of its values + def get_tag_values(tag_as_string) found = false results = [] - for public_body_tag in self.public_body_tags - if public_body_tag.name == tag + for tag in self.tags + if tag.name == tag_as_string found = true - if !public_body_tag.value.nil? - results << public_body_tag.value + if !tag.value.nil? + results << tag.value end end end @@ -59,16 +102,20 @@ module HasTagString end return results end - def add_tag_if_not_already_present(tag) - self.tag_string = self.tag_string + " " + tag - end + # Adds a new tag to the model, if it isn't already there + def add_tag_if_not_already_present(tag_as_string) + self.tag_string = self.tag_string + " " + tag_as_string + end end + # Methods which are added to the model class being tagged module ClassMethods # Find all public bodies with a particular tag - def find_by_tag(tag) - return PublicBodyTag.find(:all, :conditions => ['name = ?', tag] ).map { |t| t.public_body }.sort { |a,b| a.name <=> b.name } + def find_by_tag(tag_as_string) + return HasTagStringTag.find(:all, :conditions => + ['name = ? and model = ?', tag_as_string, self.to_s ] + ).map { |t| t.tagged_model }.sort { |a,b| a.name <=> b.name } end end @@ -76,6 +123,8 @@ module HasTagString # Main entry point, add has_tag_string to your model. module HasMethods def has_tag_string() + has_many :tags, :conditions => "model = '" + self.to_s + "'", :foreign_key => "model_id", :class_name => 'HasTagString::HasTagStringTag' + include InstanceMethods self.class.send :include, ClassMethods end |