mirror of
https://github.com/discourse/discourse.git
synced 2025-06-02 04:08:41 +08:00
Merge pull request #2297 from ligthyear/custom-fields
Custom fields for Topic, Category, Post and Group
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
class Category < ActiveRecord::Base
|
||||
|
||||
include Positionable
|
||||
include HasCustomFields
|
||||
|
||||
belongs_to :topic, dependent: :destroy
|
||||
belongs_to :topic_only_relative_url,
|
||||
|
19
app/models/category_custom_field.rb
Normal file
19
app/models/category_custom_field.rb
Normal file
@ -0,0 +1,19 @@
|
||||
class CategoryCustomField < ActiveRecord::Base
|
||||
belongs_to :category
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: category_custom_fields
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# category_id :integer not null
|
||||
# name :string(256) not null
|
||||
# value :text
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_category_custom_fields_on_category_id_and_name (category_id,name)
|
||||
#
|
93
app/models/concerns/has_custom_fields.rb
Normal file
93
app/models/concerns/has_custom_fields.rb
Normal file
@ -0,0 +1,93 @@
|
||||
|
||||
module HasCustomFields
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
has_many :_custom_fields, dependent: :destroy, :class_name => "#{name}CustomField"
|
||||
after_save :save_custom_fields
|
||||
end
|
||||
|
||||
def reload(options = nil)
|
||||
@custom_fields = nil
|
||||
@custom_fields_orig = nil
|
||||
super
|
||||
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
|
@ -1,4 +1,6 @@
|
||||
class Group < ActiveRecord::Base
|
||||
include HasCustomFields
|
||||
|
||||
has_many :category_groups
|
||||
has_many :group_users, dependent: :destroy
|
||||
|
||||
|
19
app/models/group_custom_field.rb
Normal file
19
app/models/group_custom_field.rb
Normal file
@ -0,0 +1,19 @@
|
||||
class GroupCustomField < ActiveRecord::Base
|
||||
belongs_to :group
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: group_custom_fields
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# group_id :integer not null
|
||||
# name :string(256) not null
|
||||
# value :text
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_group_custom_fields_on_group_id_and_name (group_id,name)
|
||||
#
|
@ -13,6 +13,7 @@ require 'digest/sha1'
|
||||
class Post < ActiveRecord::Base
|
||||
include RateLimiter::OnCreateRecord
|
||||
include Trashable
|
||||
include HasCustomFields
|
||||
|
||||
rate_limit
|
||||
rate_limit :limit_posts_per_day
|
||||
|
19
app/models/post_custom_field.rb
Normal file
19
app/models/post_custom_field.rb
Normal file
@ -0,0 +1,19 @@
|
||||
class PostCustomField < ActiveRecord::Base
|
||||
belongs_to :post
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: post_custom_fields
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# post_id :integer not null
|
||||
# name :string(256) not null
|
||||
# value :text
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_post_custom_fields_on_post_id_and_name (post_id,name)
|
||||
#
|
@ -9,6 +9,7 @@ require_dependency 'archetype'
|
||||
class Topic < ActiveRecord::Base
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
include RateLimiter::OnCreateRecord
|
||||
include HasCustomFields
|
||||
include Trashable
|
||||
extend Forwardable
|
||||
|
||||
@ -103,6 +104,7 @@ class Topic < ActiveRecord::Base
|
||||
attr_accessor :user_data
|
||||
attr_accessor :posters # TODO: can replace with posters_summary once we remove old list code
|
||||
attr_accessor :topic_list
|
||||
attr_accessor :meta_data
|
||||
attr_accessor :include_last_poster
|
||||
|
||||
# The regular order
|
||||
@ -318,8 +320,16 @@ class Topic < ActiveRecord::Base
|
||||
topics.where("topics.id NOT IN (?)", featured_topic_ids)
|
||||
end
|
||||
|
||||
def meta_data=(data)
|
||||
custom_fields.replace(data)
|
||||
end
|
||||
|
||||
def meta_data
|
||||
custom_fields
|
||||
end
|
||||
|
||||
def update_meta_data(data)
|
||||
self.meta_data = (self.meta_data || {}).merge(data.stringify_keys)
|
||||
custom_fields.update(data)
|
||||
save
|
||||
end
|
||||
|
||||
@ -341,8 +351,7 @@ class Topic < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def meta_data_string(key)
|
||||
return unless meta_data.present?
|
||||
meta_data[key.to_s]
|
||||
custom_fields[key.to_s]
|
||||
end
|
||||
|
||||
def self.listable_count_per_day(sinceDaysAgo=30)
|
||||
@ -820,7 +829,6 @@ end
|
||||
# archived :boolean default(FALSE), not null
|
||||
# bumped_at :datetime not null
|
||||
# has_summary :boolean default(FALSE), not null
|
||||
# meta_data :hstore
|
||||
# vote_count :integer default(0), not null
|
||||
# archetype :string(255) default("regular"), not null
|
||||
# featured_user4_id :integer
|
||||
|
19
app/models/topic_custom_field.rb
Normal file
19
app/models/topic_custom_field.rb
Normal file
@ -0,0 +1,19 @@
|
||||
class TopicCustomField < ActiveRecord::Base
|
||||
belongs_to :topic
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: topic_custom_fields
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# topic_id :integer not null
|
||||
# name :string(256) not null
|
||||
# value :text
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_topic_custom_fields_on_topic_id_and_name (topic_id,name)
|
||||
#
|
@ -12,6 +12,7 @@ require_dependency 'url_helper'
|
||||
class User < ActiveRecord::Base
|
||||
include Roleable
|
||||
include UrlHelper
|
||||
include HasCustomFields
|
||||
|
||||
has_many :posts
|
||||
has_many :notifications, dependent: :destroy
|
||||
@ -31,7 +32,6 @@ class User < ActiveRecord::Base
|
||||
has_many :invites, dependent: :destroy
|
||||
has_many :topic_links, dependent: :destroy
|
||||
has_many :uploads
|
||||
has_many :user_custom_fields, dependent: :destroy
|
||||
|
||||
has_one :facebook_user_info, dependent: :destroy
|
||||
has_one :twitter_user_info, dependent: :destroy
|
||||
@ -69,7 +69,6 @@ class User < ActiveRecord::Base
|
||||
|
||||
after_save :update_tracked_topics
|
||||
after_save :clear_global_notice_if_needed
|
||||
after_save :save_custom_fields
|
||||
|
||||
after_create :create_email_token
|
||||
after_create :create_user_stat
|
||||
@ -595,35 +594,8 @@ class User < ActiveRecord::Base
|
||||
nil
|
||||
end
|
||||
|
||||
def custom_fields
|
||||
@custom_fields ||= begin
|
||||
@custom_fields_orig = Hash[*user_custom_fields.pluck(:name,:value).flatten]
|
||||
@custom_fields_orig.dup
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def save_custom_fields
|
||||
if @custom_fields && @custom_fields_orig != @custom_fields
|
||||
dup = @custom_fields.dup
|
||||
|
||||
user_custom_fields.each do |f|
|
||||
if dup[f.name] != f.value
|
||||
f.destroy
|
||||
else
|
||||
dup.remove[f.name]
|
||||
end
|
||||
end
|
||||
|
||||
dup.each do |k,v|
|
||||
user_custom_fields.create(name: k, value: v)
|
||||
end
|
||||
|
||||
@custom_fields_orig = @custom_fields
|
||||
end
|
||||
end
|
||||
|
||||
def cook
|
||||
if bio_raw.present?
|
||||
self.bio_cooked = PrettyText.cook(bio_raw, omit_nofollow: self.has_trust_level?(:leader)) if bio_raw_changed?
|
||||
|
Reference in New Issue
Block a user