diff --git a/app/models/category.rb b/app/models/category.rb index 4bd71f5be4b..2ef1a7501e1 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -1,9 +1,7 @@ -require_dependency "concern/has_custom_fields" - class Category < ActiveRecord::Base include Positionable - include Concern::HasCustomFields + include HasCustomFields belongs_to :topic, dependent: :destroy belongs_to :topic_only_relative_url, diff --git a/app/models/concerns/has_custom_fields.rb b/app/models/concerns/has_custom_fields.rb new file mode 100644 index 00000000000..c763db04d7d --- /dev/null +++ b/app/models/concerns/has_custom_fields.rb @@ -0,0 +1,87 @@ + +module HasCustomFields + extend ActiveSupport::Concern + + included do + has_many :_custom_fields, dependent: :destroy, :class_name => "#{name}CustomField" + after_save :save_custom_fields + end + + def custom_fields + @custom_fields ||= refresh_custom_fields_from_db.dup + end + + def custom_fields=(data) + custom_fields.replace(data) + end + + def custom_fields_clean? + # Check whether the cached version has been + # changed on this model + !@custom_fields || @custom_fields_orig == @custom_fields + end + + protected + + def refresh_custom_fields_from_db + target = Hash.new + _custom_fields.pluck(:name,:value).each do |key, value| + if target.has_key? key + if !target[key].is_a? Array + target[key] = [target[key]] + end + target[key] << value + else + target[key] = value + end + end + @custom_fields_orig = target + @custom_fields = @custom_fields_orig.dup + end + + def save_custom_fields + if !custom_fields_clean? + dup = @custom_fields.dup + + array_fields = {} + + _custom_fields.each do |f| + if dup[f.name].is_a? Array + # we need to collect Arrays fully before + # we can compare them + if !array_fields.has_key? f.name + array_fields[f.name] = [f] + else + array_fields[f.name] << f + end + else + if dup[f.name] != f.value + f.destroy + else + dup.delete(f.name) + end + end + end + + # let's iterate through our arrays and compare them + array_fields.each do |field_name, fields| + if fields.length == dup[field_name].length && + fields.map{|f| f.value} == dup[field_name] + dup.delete(f.name) + else + fields.each{|f| f.destroy } + end + end + + dup.each do |k,v| + if v.is_a? Array + v.each {|subv| _custom_fields.create(name: k, value: subv)} + else + _custom_fields.create(name: k, value: v) + end + end + + refresh_custom_fields_from_db + end + end +end \ No newline at end of file diff --git a/app/models/group.rb b/app/models/group.rb index 35933da1012..e5cd9dc8a90 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -1,7 +1,5 @@ -require_dependency "concern/has_custom_fields" - class Group < ActiveRecord::Base - include Concern::HasCustomFields + include HasCustomFields has_many :category_groups has_many :group_users, dependent: :destroy diff --git a/app/models/post.rb b/app/models/post.rb index fc38fc40798..cdba83b5c2e 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -6,7 +6,6 @@ require_dependency 'enum' require_dependency 'post_analyzer' require_dependency 'validators/post_validator' require_dependency 'plugin/filter' -require_dependency "concern/has_custom_fields" require 'archetype' require 'digest/sha1' @@ -14,7 +13,7 @@ require 'digest/sha1' class Post < ActiveRecord::Base include RateLimiter::OnCreateRecord include Trashable - include Concern::HasCustomFields + include HasCustomFields rate_limit rate_limit :limit_posts_per_day diff --git a/app/models/topic.rb b/app/models/topic.rb index 0ff99cfc3c0..9360b98477d 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -5,12 +5,11 @@ require_dependency 'rate_limiter' require_dependency 'text_sentinel' require_dependency 'text_cleaner' require_dependency 'archetype' -require_dependency "concern/has_custom_fields" class Topic < ActiveRecord::Base include ActionView::Helpers::SanitizeHelper include RateLimiter::OnCreateRecord - include Concern::HasCustomFields + include HasCustomFields include Trashable extend Forwardable diff --git a/app/models/user.rb b/app/models/user.rb index a7f02c5af86..962d2d3bcde 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,12 +8,11 @@ require_dependency 'post_destroyer' require_dependency 'user_name_suggester' require_dependency 'pretty_text' require_dependency 'url_helper' -require_dependency 'concern/has_custom_fields' class User < ActiveRecord::Base include Roleable include UrlHelper - include Concern::HasCustomFields + include HasCustomFields has_many :posts has_many :notifications, dependent: :destroy diff --git a/lib/concern/has_custom_fields.rb b/lib/concern/has_custom_fields.rb deleted file mode 100644 index b0a61bd74b0..00000000000 --- a/lib/concern/has_custom_fields.rb +++ /dev/null @@ -1,88 +0,0 @@ -module Concern - module HasCustomFields - extend ActiveSupport::Concern - - included do - has_many :_custom_fields, dependent: :destroy, :class_name => "#{name}CustomField" - after_save :save_custom_fields - end - - def custom_fields - @custom_fields ||= refresh_custom_fields_from_db.dup - end - - def custom_fields=(data) - custom_fields.replace(data) - end - - def custom_fields_clean? - # Check whether the cached version has been - # changed on this model - !@custom_fields || @custom_fields_orig == @custom_fields - end - - protected - - def refresh_custom_fields_from_db - target = Hash.new - _custom_fields.pluck(:name,:value).each do |key, value| - if target.has_key? key - if !target[key].is_a? Array - target[key] = [target[key]] - end - target[key] << value - else - target[key] = value - end - end - @custom_fields_orig = target - @custom_fields = @custom_fields_orig.dup - end - - def save_custom_fields - if !custom_fields_clean? - dup = @custom_fields.dup - - array_fields = {} - - _custom_fields.each do |f| - if dup[f.name].is_a? Array - # we need to collect Arrays fully before - # we can compare them - if !array_fields.has_key? f.name - array_fields[f.name] = [f] - else - array_fields[f.name] << f - end - else - if dup[f.name] != f.value - f.destroy - else - dup.delete(f.name) - end - end - end - - # let's iterate through our arrays and compare them - array_fields.each do |field_name, fields| - if fields.length == dup[field_name].length && - fields.map{|f| f.value} == dup[field_name] - dup.delete(f.name) - else - fields.each{|f| f.destroy } - end - end - - dup.each do |k,v| - if v.is_a? Array - v.each {|subv| _custom_fields.create(name: k, value: subv)} - else - _custom_fields.create(name: k, value: v) - end - end - - refresh_custom_fields_from_db - end - end - end -end \ No newline at end of file diff --git a/spec/components/concern/has_custom_fields_spec.rb b/spec/components/concern/has_custom_fields_spec.rb index 9f8ae26aa5b..291af92cb26 100644 --- a/spec/components/concern/has_custom_fields_spec.rb +++ b/spec/components/concern/has_custom_fields_spec.rb @@ -1,7 +1,6 @@ require "spec_helper" -require_dependency "concern/has_custom_fields" -describe Concern::HasCustomFields do +describe HasCustomFields do context "custom_fields" do before do @@ -10,7 +9,7 @@ describe Concern::HasCustomFields do Topic.exec_sql("create temporary table test_item_custom_fields(id SERIAL primary key, test_item_id int, name varchar(256) not null, value text)") class TestItem < ActiveRecord::Base - include Concern::HasCustomFields + include HasCustomFields end class TestItemCustomField < ActiveRecord::Base