Merge pull request #2297 from ligthyear/custom-fields
Custom fields for Topic, Category, Post and Group
This commit is contained in:
commit
f6c22cc299
|
@ -1,6 +1,7 @@
|
||||||
class Category < ActiveRecord::Base
|
class Category < ActiveRecord::Base
|
||||||
|
|
||||||
include Positionable
|
include Positionable
|
||||||
|
include HasCustomFields
|
||||||
|
|
||||||
belongs_to :topic, dependent: :destroy
|
belongs_to :topic, dependent: :destroy
|
||||||
belongs_to :topic_only_relative_url,
|
belongs_to :topic_only_relative_url,
|
||||||
|
|
|
@ -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)
|
||||||
|
#
|
|
@ -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
|
class Group < ActiveRecord::Base
|
||||||
|
include HasCustomFields
|
||||||
|
|
||||||
has_many :category_groups
|
has_many :category_groups
|
||||||
has_many :group_users, dependent: :destroy
|
has_many :group_users, dependent: :destroy
|
||||||
|
|
||||||
|
|
|
@ -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
|
class Post < ActiveRecord::Base
|
||||||
include RateLimiter::OnCreateRecord
|
include RateLimiter::OnCreateRecord
|
||||||
include Trashable
|
include Trashable
|
||||||
|
include HasCustomFields
|
||||||
|
|
||||||
rate_limit
|
rate_limit
|
||||||
rate_limit :limit_posts_per_day
|
rate_limit :limit_posts_per_day
|
||||||
|
|
|
@ -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
|
class Topic < ActiveRecord::Base
|
||||||
include ActionView::Helpers::SanitizeHelper
|
include ActionView::Helpers::SanitizeHelper
|
||||||
include RateLimiter::OnCreateRecord
|
include RateLimiter::OnCreateRecord
|
||||||
|
include HasCustomFields
|
||||||
include Trashable
|
include Trashable
|
||||||
extend Forwardable
|
extend Forwardable
|
||||||
|
|
||||||
|
@ -103,6 +104,7 @@ class Topic < ActiveRecord::Base
|
||||||
attr_accessor :user_data
|
attr_accessor :user_data
|
||||||
attr_accessor :posters # TODO: can replace with posters_summary once we remove old list code
|
attr_accessor :posters # TODO: can replace with posters_summary once we remove old list code
|
||||||
attr_accessor :topic_list
|
attr_accessor :topic_list
|
||||||
|
attr_accessor :meta_data
|
||||||
attr_accessor :include_last_poster
|
attr_accessor :include_last_poster
|
||||||
|
|
||||||
# The regular order
|
# The regular order
|
||||||
|
@ -318,8 +320,16 @@ class Topic < ActiveRecord::Base
|
||||||
topics.where("topics.id NOT IN (?)", featured_topic_ids)
|
topics.where("topics.id NOT IN (?)", featured_topic_ids)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def meta_data=(data)
|
||||||
|
custom_fields.replace(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def meta_data
|
||||||
|
custom_fields
|
||||||
|
end
|
||||||
|
|
||||||
def update_meta_data(data)
|
def update_meta_data(data)
|
||||||
self.meta_data = (self.meta_data || {}).merge(data.stringify_keys)
|
custom_fields.update(data)
|
||||||
save
|
save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -341,8 +351,7 @@ class Topic < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def meta_data_string(key)
|
def meta_data_string(key)
|
||||||
return unless meta_data.present?
|
custom_fields[key.to_s]
|
||||||
meta_data[key.to_s]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.listable_count_per_day(sinceDaysAgo=30)
|
def self.listable_count_per_day(sinceDaysAgo=30)
|
||||||
|
@ -820,7 +829,6 @@ end
|
||||||
# archived :boolean default(FALSE), not null
|
# archived :boolean default(FALSE), not null
|
||||||
# bumped_at :datetime not null
|
# bumped_at :datetime not null
|
||||||
# has_summary :boolean default(FALSE), not null
|
# has_summary :boolean default(FALSE), not null
|
||||||
# meta_data :hstore
|
|
||||||
# vote_count :integer default(0), not null
|
# vote_count :integer default(0), not null
|
||||||
# archetype :string(255) default("regular"), not null
|
# archetype :string(255) default("regular"), not null
|
||||||
# featured_user4_id :integer
|
# featured_user4_id :integer
|
||||||
|
|
|
@ -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
|
class User < ActiveRecord::Base
|
||||||
include Roleable
|
include Roleable
|
||||||
include UrlHelper
|
include UrlHelper
|
||||||
|
include HasCustomFields
|
||||||
|
|
||||||
has_many :posts
|
has_many :posts
|
||||||
has_many :notifications, dependent: :destroy
|
has_many :notifications, dependent: :destroy
|
||||||
|
@ -31,7 +32,6 @@ class User < ActiveRecord::Base
|
||||||
has_many :invites, dependent: :destroy
|
has_many :invites, dependent: :destroy
|
||||||
has_many :topic_links, dependent: :destroy
|
has_many :topic_links, dependent: :destroy
|
||||||
has_many :uploads
|
has_many :uploads
|
||||||
has_many :user_custom_fields, dependent: :destroy
|
|
||||||
|
|
||||||
has_one :facebook_user_info, dependent: :destroy
|
has_one :facebook_user_info, dependent: :destroy
|
||||||
has_one :twitter_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 :update_tracked_topics
|
||||||
after_save :clear_global_notice_if_needed
|
after_save :clear_global_notice_if_needed
|
||||||
after_save :save_custom_fields
|
|
||||||
|
|
||||||
after_create :create_email_token
|
after_create :create_email_token
|
||||||
after_create :create_user_stat
|
after_create :create_user_stat
|
||||||
|
@ -595,35 +594,8 @@ class User < ActiveRecord::Base
|
||||||
nil
|
nil
|
||||||
end
|
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
|
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
|
def cook
|
||||||
if bio_raw.present?
|
if bio_raw.present?
|
||||||
self.bio_cooked = PrettyText.cook(bio_raw, omit_nofollow: self.has_trust_level?(:leader)) if bio_raw_changed?
|
self.bio_cooked = PrettyText.cook(bio_raw, omit_nofollow: self.has_trust_level?(:leader)) if bio_raw_changed?
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
class AddCustomFields < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :category_custom_fields do |t|
|
||||||
|
t.integer :category_id, null: false
|
||||||
|
t.string :name, limit: 256, null: false
|
||||||
|
t.text :value
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table :group_custom_fields do |t|
|
||||||
|
t.integer :group_id, null: false
|
||||||
|
t.string :name, limit: 256, null: false
|
||||||
|
t.text :value
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
create_table :post_custom_fields do |t|
|
||||||
|
t.integer :post_id, null: false
|
||||||
|
t.string :name, limit: 256, null: false
|
||||||
|
t.text :value
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :category_custom_fields, [:category_id, :name]
|
||||||
|
add_index :group_custom_fields, [:group_id, :name]
|
||||||
|
add_index :post_custom_fields, [:post_id, :name]
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,21 @@
|
||||||
|
class AddTopicCustomFields < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :topic_custom_fields do |t|
|
||||||
|
t.integer :topic_id, null: false
|
||||||
|
t.string :name, limit: 256, null: false
|
||||||
|
t.text :value
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :topic_custom_fields, [:topic_id, :name]
|
||||||
|
|
||||||
|
# migrate meta_data into custom fields
|
||||||
|
execute <<-SQL
|
||||||
|
INSERT INTO topic_custom_fields(topic_id, name, value)
|
||||||
|
SELECT id, (each(meta_data)).key, (each(meta_data)).value
|
||||||
|
FROM topics WHERE meta_data <> ''
|
||||||
|
SQL
|
||||||
|
|
||||||
|
remove_column :topics, :meta_data
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,156 @@
|
||||||
|
require "spec_helper"
|
||||||
|
|
||||||
|
|
||||||
|
describe HasCustomFields do
|
||||||
|
|
||||||
|
context "custom_fields" do
|
||||||
|
before do
|
||||||
|
|
||||||
|
Topic.exec_sql("create temporary table custom_fields_test_items(id SERIAL primary key)")
|
||||||
|
Topic.exec_sql("create temporary table custom_fields_test_item_custom_fields(id SERIAL primary key, custom_fields_test_item_id int, name varchar(256) not null, value text)")
|
||||||
|
|
||||||
|
class CustomFieldsTestItem < ActiveRecord::Base
|
||||||
|
include HasCustomFields
|
||||||
|
end
|
||||||
|
|
||||||
|
class CustomFieldsTestItemCustomField < ActiveRecord::Base
|
||||||
|
belongs_to :custom_fields_test_item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
Topic.exec_sql("drop table custom_fields_test_items")
|
||||||
|
Topic.exec_sql("drop table custom_fields_test_item_custom_fields")
|
||||||
|
|
||||||
|
# import is making my life hard, we need to nuke this out of orbit
|
||||||
|
des = ActiveSupport::DescendantsTracker.class_variable_get :@@direct_descendants
|
||||||
|
des[ActiveRecord::Base].delete(CustomFieldsTestItem)
|
||||||
|
des[ActiveRecord::Base].delete(CustomFieldsTestItemCustomField)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "simple modification of custom fields" do
|
||||||
|
test_item = CustomFieldsTestItem.new
|
||||||
|
|
||||||
|
test_item.custom_fields["a"].should == nil
|
||||||
|
|
||||||
|
test_item.custom_fields["bob"] = "marley"
|
||||||
|
test_item.custom_fields["jack"] = "black"
|
||||||
|
|
||||||
|
test_item.save
|
||||||
|
|
||||||
|
test_item = CustomFieldsTestItem.find(test_item.id)
|
||||||
|
|
||||||
|
test_item.custom_fields["bob"].should == "marley"
|
||||||
|
test_item.custom_fields["jack"].should == "black"
|
||||||
|
|
||||||
|
test_item.custom_fields.delete("bob")
|
||||||
|
test_item.custom_fields["jack"] = "jill"
|
||||||
|
|
||||||
|
test_item.save
|
||||||
|
test_item = CustomFieldsTestItem.find(test_item.id)
|
||||||
|
|
||||||
|
test_item.custom_fields.should == {"jack" => "jill"}
|
||||||
|
end
|
||||||
|
|
||||||
|
it "casts integers to string without error" do
|
||||||
|
test_item = CustomFieldsTestItem.new
|
||||||
|
test_item.custom_fields["a"].should == nil
|
||||||
|
test_item.custom_fields["a"] = 0
|
||||||
|
|
||||||
|
test_item.custom_fields["a"].should == 0
|
||||||
|
test_item.save
|
||||||
|
|
||||||
|
# should be casted right after saving
|
||||||
|
test_item.custom_fields["a"].should == "0"
|
||||||
|
|
||||||
|
test_item = CustomFieldsTestItem.find(test_item.id)
|
||||||
|
test_item.custom_fields["a"].should == "0"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "reload loads from database" do
|
||||||
|
test_item = CustomFieldsTestItem.new
|
||||||
|
test_item.custom_fields["a"] = 0
|
||||||
|
|
||||||
|
test_item.custom_fields["a"].should == 0
|
||||||
|
test_item.save
|
||||||
|
|
||||||
|
# should be casted right after saving
|
||||||
|
test_item.custom_fields["a"].should == "0"
|
||||||
|
|
||||||
|
CustomFieldsTestItem.exec_sql("UPDATE custom_fields_test_item_custom_fields SET value='1' WHERE custom_fields_test_item_id=? AND name='a'", test_item.id)
|
||||||
|
|
||||||
|
# still the same, did not load
|
||||||
|
test_item.custom_fields["a"].should == "0"
|
||||||
|
|
||||||
|
# refresh loads from database
|
||||||
|
test_item.reload.custom_fields["a"].should == "1"
|
||||||
|
test_item.custom_fields["a"].should == "1"
|
||||||
|
|
||||||
|
end
|
||||||
|
it "double save actually saves" do
|
||||||
|
|
||||||
|
test_item = CustomFieldsTestItem.new
|
||||||
|
test_item.custom_fields = {"a" => "b"}
|
||||||
|
test_item.save
|
||||||
|
|
||||||
|
test_item.custom_fields["c"] = "d"
|
||||||
|
test_item.save
|
||||||
|
|
||||||
|
db_item = CustomFieldsTestItem.find(test_item.id)
|
||||||
|
db_item.custom_fields.should == {"a" => "b", "c" => "d"}
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
it "handles arrays properly" do
|
||||||
|
|
||||||
|
test_item = CustomFieldsTestItem.new
|
||||||
|
test_item.custom_fields = {"a" => ["b", "c", "d"]}
|
||||||
|
test_item.save
|
||||||
|
|
||||||
|
db_item = CustomFieldsTestItem.find(test_item.id)
|
||||||
|
db_item.custom_fields.should == {"a" => ["b", "c", "d"]}
|
||||||
|
|
||||||
|
db_item.custom_fields["a"] = ["c", "d"]
|
||||||
|
db_item.save
|
||||||
|
db_item.custom_fields.should == {"a" => ["c", "d"]}
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
it "casts integers in arrays properly without error" do
|
||||||
|
|
||||||
|
test_item = CustomFieldsTestItem.new
|
||||||
|
test_item.custom_fields = {"a" => ["b", 10, "d"]}
|
||||||
|
test_item.save
|
||||||
|
test_item.custom_fields.should == {"a" => ["b", "10", "d"]}
|
||||||
|
|
||||||
|
db_item = CustomFieldsTestItem.find(test_item.id)
|
||||||
|
db_item.custom_fields.should == {"a" => ["b", "10", "d"]}
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
it "simple modifications don't interfere" do
|
||||||
|
test_item = CustomFieldsTestItem.new
|
||||||
|
|
||||||
|
test_item.custom_fields["a"].should == nil
|
||||||
|
|
||||||
|
test_item.custom_fields["bob"] = "marley"
|
||||||
|
test_item.custom_fields["jack"] = "black"
|
||||||
|
test_item.save
|
||||||
|
|
||||||
|
test_item2 = CustomFieldsTestItem.new
|
||||||
|
|
||||||
|
test_item2.custom_fields["x"].should == nil
|
||||||
|
|
||||||
|
test_item2.custom_fields["sixto"] = "rodriguez"
|
||||||
|
test_item2.custom_fields["de"] = "la playa"
|
||||||
|
test_item2.save
|
||||||
|
|
||||||
|
test_item = CustomFieldsTestItem.find(test_item.id)
|
||||||
|
test_item2 = CustomFieldsTestItem.find(test_item2.id)
|
||||||
|
|
||||||
|
test_item.custom_fields.should == {"jack" => "black", "bob" => "marley"}
|
||||||
|
test_item2.custom_fields.should == {"sixto" => "rodriguez", "de" => "la playa"}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -133,6 +133,18 @@ describe Category do
|
||||||
Fabricate(:category, name: " blanks ").name.should == "blanks"
|
Fabricate(:category, name: " blanks ").name.should == "blanks"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "has custom fields" do
|
||||||
|
category = Fabricate(:category, name: " music")
|
||||||
|
category.custom_fields["a"].should == nil
|
||||||
|
|
||||||
|
category.custom_fields["bob"] = "marley"
|
||||||
|
category.custom_fields["jack"] = "black"
|
||||||
|
category.save
|
||||||
|
|
||||||
|
category = Category.find(category.id)
|
||||||
|
category.custom_fields.should == {"bob" => "marley", "jack" => "black"}
|
||||||
|
end
|
||||||
|
|
||||||
describe "short name" do
|
describe "short name" do
|
||||||
let!(:category) { Fabricate(:category, name: 'xx') }
|
let!(:category) { Fabricate(:category, name: 'xx') }
|
||||||
|
|
||||||
|
|
|
@ -148,6 +148,19 @@ describe Group do
|
||||||
GroupUser.count.should == original_count
|
GroupUser.count.should == original_count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
it "has custom fields" do
|
||||||
|
group = Fabricate(:group)
|
||||||
|
group.custom_fields["a"].should == nil
|
||||||
|
|
||||||
|
group.custom_fields["hugh"] = "jackman"
|
||||||
|
group.custom_fields["jack"] = "black"
|
||||||
|
group.save
|
||||||
|
|
||||||
|
group = Group.find(group.id)
|
||||||
|
group.custom_fields.should == {"hugh" => "jackman", "jack" => "black"}
|
||||||
|
end
|
||||||
|
|
||||||
it "allows you to lookup a new group by name" do
|
it "allows you to lookup a new group by name" do
|
||||||
group = Fabricate(:group)
|
group = Fabricate(:group)
|
||||||
group.id.should == Group[group.name].id
|
group.id.should == Group[group.name].id
|
||||||
|
|
|
@ -814,4 +814,16 @@ describe Post do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "has custom fields" do
|
||||||
|
post = Fabricate(:post)
|
||||||
|
post.custom_fields["a"].should == nil
|
||||||
|
|
||||||
|
post.custom_fields["Tommy"] = "Hanks"
|
||||||
|
post.custom_fields["Vincent"] = "Vega"
|
||||||
|
post.save
|
||||||
|
|
||||||
|
post = Post.find(post.id)
|
||||||
|
post.custom_fields.should == {"Tommy" => "Hanks", "Vincent" => "Vega"}
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -722,6 +722,21 @@ describe Topic do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'new key' do
|
||||||
|
before do
|
||||||
|
topic.update_meta_data('other' => 'key')
|
||||||
|
topic.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can be loaded" do
|
||||||
|
Topic.find(topic.id).meta_data["other"].should == "key"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is in sync with custom_fields" do
|
||||||
|
Topic.find(topic.id).custom_fields["other"].should == "key"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1380,7 +1395,17 @@ describe Topic do
|
||||||
topic.stubs(:has_topic_embed?).returns(false)
|
topic.stubs(:has_topic_embed?).returns(false)
|
||||||
topic.expandable_first_post?.should be_false
|
topic.expandable_first_post?.should be_false
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "has custom fields" do
|
||||||
|
topic = Fabricate(:topic)
|
||||||
|
topic.custom_fields["a"].should == nil
|
||||||
|
|
||||||
|
topic.custom_fields["bob"] = "marley"
|
||||||
|
topic.custom_fields["jack"] = "black"
|
||||||
|
topic.save
|
||||||
|
|
||||||
|
topic = Topic.find(topic.id)
|
||||||
|
topic.custom_fields.should == {"bob" => "marley", "jack" => "black"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue