diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/public_body.rb | 14 | ||||
-rw-r--r-- | app/models/public_body_category.rb | 90 | ||||
-rw-r--r-- | app/models/public_body_category/category_collection.rb | 54 | ||||
-rw-r--r-- | app/models/public_body_category_link.rb | 34 | ||||
-rw-r--r-- | app/models/public_body_heading.rb | 75 |
5 files changed, 260 insertions, 7 deletions
diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 87b5c2227..f61a3f449 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -132,14 +132,14 @@ class PublicBody < ActiveRecord::Base end def translated_versions=(translation_attrs) - def skip?(attrs) - valueless = attrs.inject({}) { |h, (k, v)| h[k] = v if v != '' and k != 'locale'; h } # because we want to fall back to alternative translations where there are empty values - return valueless.length == 0 + def empty_translation?(attrs) + attrs_with_values = attrs.select{ |key, value| value != '' and key != 'locale' } + attrs_with_values.empty? end if translation_attrs.respond_to? :each_value # Hash => updating translation_attrs.each_value do |attrs| - next if skip?(attrs) + next if empty_translation?(attrs) t = translation_for(attrs[:locale]) || PublicBody::Translation.new t.attributes = attrs calculate_cached_fields(t) @@ -147,7 +147,7 @@ class PublicBody < ActiveRecord::Base end else # Array => creating translation_attrs.each do |attrs| - next if skip?(attrs) + next if empty_translation?(attrs) new_translation = PublicBody::Translation.new(attrs) calculate_cached_fields(new_translation) translations << new_translation @@ -335,8 +335,8 @@ class PublicBody < ActiveRecord::Base types = [] first = true for tag in self.tags - if PublicBodyCategories::get().by_tag().include?(tag.name) - desc = PublicBodyCategories::get().singular_by_tag()[tag.name] + if PublicBodyCategory.get().by_tag().include?(tag.name) + desc = PublicBodyCategory.get().singular_by_tag()[tag.name] if first # terrible that Ruby/Rails doesn't have an equivalent of ucfirst # (capitalize shockingly converts later characters to lowercase) diff --git a/app/models/public_body_category.rb b/app/models/public_body_category.rb new file mode 100644 index 000000000..8eaecd596 --- /dev/null +++ b/app/models/public_body_category.rb @@ -0,0 +1,90 @@ +# == Schema Information +# +# Table name: public_body_categories +# +# id :integer not null, primary key +# title :text not null +# category_tag :text not null +# description :text not null +# display_order :integer +# + +require 'forwardable' + +class PublicBodyCategory < ActiveRecord::Base + attr_accessible :locale, :category_tag, :title, :description, + :translated_versions, :display_order + + has_many :public_body_category_links, :dependent => :destroy + has_many :public_body_headings, :through => :public_body_category_links + + translates :title, :description + validates_uniqueness_of :category_tag, :message => N_('Tag is already taken') + validates_presence_of :title, :message => N_("Title can't be blank") + validates_presence_of :category_tag, :message => N_("Tag can't be blank") + + def self.get + locale = I18n.locale.to_s || default_locale.to_s || "" + categories = CategoryCollection.new + I18n.with_locale(locale) do + headings = PublicBodyHeading.all + headings.each do |heading| + categories << heading.name + heading.public_body_categories.each do |category| + categories << [ + category.category_tag, + category.title, + category.description + ] + end + end + end + categories + end + + def self.without_headings + sql = %Q| SELECT * FROM public_body_categories pbc + WHERE pbc.id NOT IN ( + SELECT public_body_category_id AS id + FROM public_body_category_links + ) | + PublicBodyCategory.find_by_sql(sql) + end + + # Called from the old-style public_body_categories_[locale].rb data files + def self.add(locale, data_list) + CategoryAndHeadingMigrator.add_categories_and_headings_from_list(locale, data_list) + end + + # Convenience methods for creating/editing translations via forms + def find_translation_by_locale(locale) + translations.find_by_locale(locale) + end + + def translated_versions + translations + end + + def translated_versions=(translation_attrs) + def empty_translation?(attrs) + attrs_with_values = attrs.select{ |key, value| value != '' and key != 'locale' } + attrs_with_values.empty? + end + if translation_attrs.respond_to? :each_value # Hash => updating + translation_attrs.each_value do |attrs| + next if empty_translation?(attrs) + t = translation_for(attrs[:locale]) || PublicBodyCategory::Translation.new + t.attributes = attrs + t.save! + end + else # Array => creating + translation_attrs.each do |attrs| + next if empty_translation?(attrs) + new_translation = PublicBodyCategory::Translation.new(attrs) + translations << new_translation + end + end + end +end + + diff --git a/app/models/public_body_category/category_collection.rb b/app/models/public_body_category/category_collection.rb new file mode 100644 index 000000000..8286e2710 --- /dev/null +++ b/app/models/public_body_category/category_collection.rb @@ -0,0 +1,54 @@ +# replicate original file-based PublicBodyCategories functionality +class PublicBodyCategory::CategoryCollection + include Enumerable + extend Forwardable + def_delegators :@categories, :each, :<< + + def initialize + @categories = [] + end + + def with_headings + @categories + end + + def with_description + @categories.select() { |a| a.instance_of?(Array) } + end + + def tags + tags = with_description.map() { |a| a[0] } + end + + def by_tag + Hash[*with_description.map() { |a| a[0..1] }.flatten] + end + + def singular_by_tag + Hash[*with_description.map() { |a| [a[0],a[2]] }.flatten] + end + + def by_heading + output = {} + heading = nil + @categories.each do |row| + if row.is_a?(Array) + output[heading] << row[0] + else + heading = row + output[heading] = [] + end + end + output + end + + def headings + output = [] + @categories.each do |row| + unless row.is_a?(Array) + output << row + end + end + output + end +end diff --git a/app/models/public_body_category_link.rb b/app/models/public_body_category_link.rb new file mode 100644 index 000000000..eb233b56f --- /dev/null +++ b/app/models/public_body_category_link.rb @@ -0,0 +1,34 @@ +# == Schema Information +# +# Table name: public_body_category_link +# +# public_body_category_id :integer not null +# public_body_heading_id :integer not null +# category_display_order :integer +# + +class PublicBodyCategoryLink < ActiveRecord::Base + attr_accessible :public_body_category_id, :public_body_heading_id, :category_display_order + + belongs_to :public_body_category + belongs_to :public_body_heading + validates_presence_of :public_body_category + validates_presence_of :public_body_heading + validates :category_display_order, :numericality => { :only_integer => true, + :message => N_('Display order must be a number') } + + before_validation :on => :create do + unless self.category_display_order + self.category_display_order = PublicBodyCategoryLink.next_display_order(public_body_heading_id) + end + end + + def self.next_display_order(heading_id) + if last = where(:public_body_heading_id => heading_id).order(:category_display_order).last + last.category_display_order + 1 + else + 0 + end + end + +end diff --git a/app/models/public_body_heading.rb b/app/models/public_body_heading.rb new file mode 100644 index 000000000..c38800561 --- /dev/null +++ b/app/models/public_body_heading.rb @@ -0,0 +1,75 @@ +# == Schema Information +# +# Table name: public_body_headings +# +# id :integer not null, primary key +# name :text not null +# display_order :integer +# + +class PublicBodyHeading < ActiveRecord::Base + attr_accessible :name, :display_order, :translated_versions + + has_many :public_body_category_links, :dependent => :destroy + has_many :public_body_categories, :order => :category_display_order, :through => :public_body_category_links + default_scope order('display_order ASC') + + translates :name + + validates_uniqueness_of :name, :message => N_('Name is already taken') + validates_presence_of :name, :message => N_('Name can\'t be blank') + validates :display_order, :numericality => { :only_integer => true, + :message => N_('Display order must be a number') } + + before_validation :on => :create do + unless self.display_order + self.display_order = PublicBodyHeading.next_display_order + end + end + + # Convenience methods for creating/editing translations via forms + def find_translation_by_locale(locale) + translations.find_by_locale(locale) + end + + def translated_versions + translations + end + + def translated_versions=(translation_attrs) + def empty_translation?(attrs) + attrs_with_values = attrs.select{ |key, value| value != '' and key != 'locale' } + attrs_with_values.empty? + end + + if translation_attrs.respond_to? :each_value # Hash => updating + translation_attrs.each_value do |attrs| + next if empty_translation?(attrs) + t = translation_for(attrs[:locale]) || PublicBodyHeading::Translation.new + t.attributes = attrs + t.save! + end + else # Array => creating + translation_attrs.each do |attrs| + next if empty_translation?(attrs) + new_translation = PublicBodyHeading::Translation.new(attrs) + translations << new_translation + end + end + end + + def add_category(category) + unless public_body_categories.include?(category) + public_body_categories << category + end + end + + def self.next_display_order + if max = maximum(:display_order) + max + 1 + else + 0 + end + end + +end |