property 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +8 -0
- data/Rakefile +1 -1
- data/lib/property/column.rb +19 -5
- data/lib/property/db.rb +13 -4
- data/lib/property/index.rb +19 -10
- data/lib/property/role_module.rb +3 -9
- data/lib/property/serialization/json.rb +13 -9
- data/lib/property/serialization/marshal.rb +17 -10
- data/lib/property/serialization/yaml.rb +15 -7
- data/lib/property/stored_role.rb +1 -1
- data/lib/property/version.rb +3 -0
- data/lib/property.rb +0 -2
- data/property.gemspec +8 -3
- data/test/database.rb +103 -0
- data/test/fixtures.rb +23 -103
- data/test/shoulda_macros/index.rb +12 -23
- data/test/shoulda_macros/role.rb +4 -0
- data/test/shoulda_macros/serialization.rb +17 -1
- data/test/test_helper.rb +4 -0
- data/test/unit/property/attribute_test.rb +5 -5
- data/test/unit/property/column_test.rb +66 -0
- data/test/unit/property/declaration_test.rb +4 -4
- data/test/unit/property/index_complex_test.rb +26 -32
- data/test/unit/property/index_foreign_test.rb +21 -33
- data/test/unit/property/index_simple_test.rb +22 -22
- data/test/unit/property/validation_test.rb +3 -3
- metadata +8 -3
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
== 1.1.0 2010-07-22
|
2
|
+
|
3
|
+
* Major enhancements
|
4
|
+
* Storing original role in column.
|
5
|
+
* Using 'idx_' as prefix by default instead of 'i_'.
|
6
|
+
* Pluralizing index table names.
|
7
|
+
* Added 'index_group' setting to use with Proc indexes on properties.
|
8
|
+
|
1
9
|
== 1.0.0 2010-05-27
|
2
10
|
|
3
11
|
* Major enhancements
|
data/Rakefile
CHANGED
data/lib/property/column.rb
CHANGED
@@ -15,6 +15,7 @@ module Property
|
|
15
15
|
if type.kind_of?(Class)
|
16
16
|
@klass = type
|
17
17
|
end
|
18
|
+
|
18
19
|
super(name, default, type, options)
|
19
20
|
extract_property_options(options)
|
20
21
|
end
|
@@ -44,10 +45,16 @@ module Property
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
# Return the class related to the type of property stored (String, Integer, etc).
|
47
49
|
def klass
|
48
50
|
@klass || super
|
49
51
|
end
|
50
52
|
|
53
|
+
# Return the role in which the column was originally defined.
|
54
|
+
def role
|
55
|
+
@role
|
56
|
+
end
|
57
|
+
|
51
58
|
# Property type used instead of 'type' when column is stored
|
52
59
|
alias ptype type
|
53
60
|
|
@@ -62,16 +69,23 @@ module Property
|
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
72
|
+
# Return the Proc to use to build index (usually nil).
|
73
|
+
def index_proc
|
74
|
+
@index_proc
|
75
|
+
end
|
76
|
+
|
65
77
|
private
|
66
78
|
def extract_property_options(options)
|
67
79
|
@index = options.delete(:index) || options.delete(:indexed)
|
80
|
+
@role = options.delete(:role)
|
68
81
|
if @index == true
|
69
|
-
@index = ptype
|
70
|
-
|
71
|
-
|
72
|
-
|
82
|
+
@index = (options.delete(:index_group) || ptype).to_s
|
83
|
+
elsif @index.kind_of?(Proc)
|
84
|
+
@index_proc = @index
|
85
|
+
@index = (options.delete(:index_group) || ptype).to_s
|
86
|
+
elsif @index.blank?
|
73
87
|
@index = nil
|
74
|
-
|
88
|
+
else
|
75
89
|
@index = @index.to_s
|
76
90
|
end
|
77
91
|
end
|
data/lib/property/db.rb
CHANGED
@@ -28,24 +28,33 @@ module Property
|
|
28
28
|
ActiveRecord::Base.connection
|
29
29
|
end
|
30
30
|
|
31
|
+
def quote(value)
|
32
|
+
connection.quote(value)
|
33
|
+
end
|
34
|
+
|
31
35
|
# Insert a list of values (multicolumn insert). The values should be properly escaped before
|
32
36
|
# being passed to this method.
|
33
37
|
def insert_many(table, columns, values)
|
34
|
-
values = values.compact.uniq
|
38
|
+
values = values.compact.uniq.map do |list|
|
39
|
+
list.map {|e| quote(e)}
|
40
|
+
end
|
41
|
+
|
42
|
+
columns = columns.map {|e| connection.quote_column_name(e)}.join(',')
|
43
|
+
|
35
44
|
case adapter
|
36
45
|
when 'sqlite3'
|
37
|
-
pre_query = "INSERT INTO #{table} (#{columns
|
46
|
+
pre_query = "INSERT INTO #{table} (#{columns}) VALUES "
|
38
47
|
values.each do |v|
|
39
48
|
execute pre_query + "(#{v.join(',')})"
|
40
49
|
end
|
41
50
|
else
|
42
51
|
values = values.map {|v| "(#{v.join(',')})"}.join(', ')
|
43
|
-
execute "INSERT INTO #{table} (#{columns
|
52
|
+
execute "INSERT INTO #{table} (#{columns}) VALUES #{values}"
|
44
53
|
end
|
45
54
|
end
|
46
55
|
|
47
56
|
def fetch_attributes(attributes, table_name, sql)
|
48
|
-
sql = "SELECT #{attributes.map{|a| connection.quote_column_name(a)}.join(',')} FROM #{table_name} WHERE #{sql}"
|
57
|
+
sql = "SELECT #{attributes.map {|a| connection.quote_column_name(a)}.join(',')} FROM #{table_name} WHERE #{sql}"
|
49
58
|
connection.select_all(sql)
|
50
59
|
end
|
51
60
|
end # Db
|
data/lib/property/index.rb
CHANGED
@@ -3,6 +3,7 @@ module Property
|
|
3
3
|
# Property::Declaration module is used to declare property definitions in a Class. The module
|
4
4
|
# also manages property inheritence in sub-classes.
|
5
5
|
module Index
|
6
|
+
KEY = Property::Db.connection.quote_column_name('key')
|
6
7
|
|
7
8
|
def self.included(base)
|
8
9
|
base.class_eval do
|
@@ -14,16 +15,25 @@ module Property
|
|
14
15
|
end
|
15
16
|
|
16
17
|
module ClassMethods
|
18
|
+
|
19
|
+
# Return the table name for the given index group. Produces something like 'idx_pages_strings'.
|
20
|
+
def index_table_name(group_name)
|
21
|
+
"idx_#{table_name}_#{group_name}s"
|
22
|
+
end
|
17
23
|
end
|
18
24
|
|
19
25
|
module InstanceMethods
|
20
26
|
|
27
|
+
def rebuild_index!
|
28
|
+
property_index
|
29
|
+
end
|
30
|
+
|
21
31
|
private
|
22
32
|
# Retrieve the current indices for a given group (:string, :text, etc)
|
23
33
|
def get_indices(group_name)
|
24
34
|
return {} if new_record?
|
25
35
|
res = {}
|
26
|
-
Property::Db.fetch_attributes(
|
36
|
+
Property::Db.fetch_attributes(%w{key value}, index_table_name(group_name), index_reader_sql(group_name)).each do |row|
|
27
37
|
res[row['key']] = row['value']
|
28
38
|
end
|
29
39
|
res
|
@@ -34,13 +44,13 @@ module Property
|
|
34
44
|
if k == :with
|
35
45
|
v.map do |subk, subv|
|
36
46
|
if subv.kind_of?(Array)
|
37
|
-
"
|
47
|
+
"#{subk} IN (#{subv.map {|ssubv| connection.quote(ssubv)}.join(',')})"
|
38
48
|
else
|
39
|
-
"
|
49
|
+
"#{subk} = #{self.class.connection.quote(subv)}"
|
40
50
|
end
|
41
51
|
end.join(' AND ')
|
42
52
|
else
|
43
|
-
"
|
53
|
+
"#{k} = #{self.class.connection.quote(v)}"
|
44
54
|
end
|
45
55
|
end.join(' AND ')
|
46
56
|
end
|
@@ -54,7 +64,7 @@ module Property
|
|
54
64
|
end
|
55
65
|
|
56
66
|
def index_table_name(group_name)
|
57
|
-
|
67
|
+
self.class.index_table_name(group_name)
|
58
68
|
end
|
59
69
|
|
60
70
|
def index_foreign_key
|
@@ -90,12 +100,11 @@ module Property
|
|
90
100
|
end
|
91
101
|
|
92
102
|
values = new_keys.map do |key|
|
93
|
-
[
|
103
|
+
[key, cur_indices[key]]
|
94
104
|
end
|
95
105
|
|
96
106
|
res = []
|
97
107
|
foreign_values.each do |list|
|
98
|
-
list = list.map {|k| connection.quote(k)}
|
99
108
|
values.each do |value|
|
100
109
|
res << (list + value)
|
101
110
|
end
|
@@ -127,12 +136,12 @@ module Property
|
|
127
136
|
|
128
137
|
# Update an index entry
|
129
138
|
def update_index(group_name, key, value)
|
130
|
-
self.class.connection.execute "UPDATE #{index_table_name(group_name)} SET
|
139
|
+
self.class.connection.execute "UPDATE #{index_table_name(group_name)} SET value = #{connection.quote(value)} WHERE #{index_reader_sql(group_name)} AND #{KEY} = #{connection.quote(key)}"
|
131
140
|
end
|
132
141
|
|
133
142
|
# Delete a list of indices (value became blank).
|
134
143
|
def delete_indices(group_name, keys)
|
135
|
-
self.class.connection.execute "DELETE FROM #{index_table_name(group_name)} WHERE #{index_reader_sql(group_name)} AND
|
144
|
+
self.class.connection.execute "DELETE FROM #{index_table_name(group_name)} WHERE #{index_reader_sql(group_name)} AND #{KEY} IN (#{keys.map{|key| connection.quote(key)}.join(',')})"
|
136
145
|
end
|
137
146
|
|
138
147
|
# This method prepares the index
|
@@ -202,7 +211,7 @@ module Property
|
|
202
211
|
if group_name.kind_of?(Class)
|
203
212
|
group_name.delete_property_index(self)
|
204
213
|
else
|
205
|
-
connection.execute "DELETE FROM #{index_table_name(group_name)} WHERE
|
214
|
+
connection.execute "DELETE FROM #{index_table_name(group_name)} WHERE #{foreign_key} = #{current_id}"
|
206
215
|
end
|
207
216
|
end
|
208
217
|
end
|
data/lib/property/role_module.rb
CHANGED
@@ -39,13 +39,7 @@ module Property
|
|
39
39
|
columns.values.select do |c|
|
40
40
|
c.indexed?
|
41
41
|
end.map do |c|
|
42
|
-
|
43
|
-
[c.type.to_sym, c.name]
|
44
|
-
elsif c.index.kind_of?(Proc)
|
45
|
-
[c.type.to_sym, c.name, c.index]
|
46
|
-
else
|
47
|
-
[c.index, c.name]
|
48
|
-
end
|
42
|
+
[c.index, c.name, c.index_proc]
|
49
43
|
end + @group_indices
|
50
44
|
end
|
51
45
|
|
@@ -132,7 +126,7 @@ module Property
|
|
132
126
|
options = args.extract_options!
|
133
127
|
column_names = args.flatten
|
134
128
|
default = options.delete(:default)
|
135
|
-
column_names.each { |name| role.add_column(Property::Column.new(name, default, '#{column_type}', options)) }
|
129
|
+
column_names.each { |name| role.add_column(Property::Column.new(name, default, '#{column_type}', options.merge(:role => role))) }
|
136
130
|
end
|
137
131
|
EOV
|
138
132
|
end
|
@@ -141,7 +135,7 @@ module Property
|
|
141
135
|
# p.serialize 'pet', Dog
|
142
136
|
def serialize(name, klass, options = {})
|
143
137
|
Property.validate_property_class(klass)
|
144
|
-
role.add_column(Property::Column.new(name, nil, klass, options))
|
138
|
+
role.add_column(Property::Column.new(name, nil, klass, options.merge(:role => role)))
|
145
139
|
end
|
146
140
|
|
147
141
|
# This is used to create complex indices with the following syntax:
|
@@ -21,18 +21,22 @@ module Property
|
|
21
21
|
|
22
22
|
def self.included(base)
|
23
23
|
Property.validators << Validator
|
24
|
+
base.extend Encoder
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
properties
|
29
|
-
|
30
|
-
|
31
|
-
# Decode Marshal encoded properties
|
32
|
-
def decode_properties(string)
|
33
|
-
::JSON.parse(string)
|
34
|
-
end
|
27
|
+
module Encoder
|
28
|
+
# Encode properties with JSON
|
29
|
+
def encode_properties(properties)
|
30
|
+
properties.to_json
|
31
|
+
end
|
35
32
|
|
33
|
+
# Decode Marshal encoded properties
|
34
|
+
def decode_properties(string)
|
35
|
+
::JSON.parse(string)
|
36
|
+
end
|
37
|
+
end # Encoder
|
38
|
+
include Encoder
|
39
|
+
extend Encoder
|
36
40
|
end # JSON
|
37
41
|
end # Serialization
|
38
42
|
end # Property
|
@@ -7,18 +7,25 @@ module Property
|
|
7
7
|
# * no corruption risk if the version of Marshal changes
|
8
8
|
# * it can be accessed by other languages then ruby
|
9
9
|
module Marshal
|
10
|
-
|
11
|
-
|
12
|
-
def encode_properties(properties)
|
13
|
-
# we limit dump depth to 0 (object only: no instance variables)
|
14
|
-
# we have to protect Marshal from serializing instance variables by making a copy
|
15
|
-
[::Marshal::dump(Properties[properties])].pack('m*')
|
10
|
+
def self.included(base)
|
11
|
+
base.extend Encoder
|
16
12
|
end
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
module Encoder
|
15
|
+
# Encode properties with Marhsal
|
16
|
+
def encode_properties(properties)
|
17
|
+
# we limit dump depth to 0 (object only: no instance variables)
|
18
|
+
# we have to protect Marshal from serializing instance variables by making a copy
|
19
|
+
[::Marshal::dump(Properties[properties])].pack('m*')
|
20
|
+
end
|
21
|
+
|
22
|
+
# Decode Marshal encoded properties
|
23
|
+
def decode_properties(string)
|
24
|
+
::Marshal::load(string.unpack('m')[0])
|
25
|
+
end
|
26
|
+
end # Encoder
|
27
|
+
include Encoder
|
28
|
+
extend Encoder
|
22
29
|
|
23
30
|
end # Marshal
|
24
31
|
end # Serialization
|
@@ -3,15 +3,23 @@ module Property
|
|
3
3
|
# Use YAML to encode properties. This method is the slowest of all
|
4
4
|
# and you should use JSON if you haven't got good reasons not to.
|
5
5
|
module YAML
|
6
|
-
|
7
|
-
|
8
|
-
::YAML.dump(properties)
|
6
|
+
def self.included(base)
|
7
|
+
base.extend Encoder
|
9
8
|
end
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
module Encoder
|
11
|
+
# Encode properties with Marhsal
|
12
|
+
def encode_properties(properties)
|
13
|
+
::YAML.dump(properties)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Decode Marshal encoded properties
|
17
|
+
def decode_properties(string)
|
18
|
+
::YAML::load(string)
|
19
|
+
end
|
20
|
+
end # Encoder
|
21
|
+
include Encoder
|
22
|
+
extend Encoder
|
15
23
|
|
16
24
|
end # Yaml
|
17
25
|
end # Serialization
|
data/lib/property/stored_role.rb
CHANGED
@@ -69,7 +69,7 @@ module Property
|
|
69
69
|
@original_columns = {}
|
70
70
|
stored_columns.each do |column|
|
71
71
|
@original_columns[column.name] = column
|
72
|
-
add_column(Property::Column.new(column.name, column.default, column.ptype, column.options))
|
72
|
+
add_column(Property::Column.new(column.name, column.default, column.ptype, column.options.merge(:role => self)))
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
data/lib/property.rb
CHANGED
data/property.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{property}
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Renaud Kern", "Gaspard Bucher"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-07-22}
|
13
13
|
s.description = %q{Wrap model properties into a single database column and declare properties from within the model.}
|
14
14
|
s.email = %q{gaspard@teti.ch}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -43,7 +43,9 @@ Gem::Specification.new do |s|
|
|
43
43
|
"lib/property/serialization/yaml.rb",
|
44
44
|
"lib/property/stored_column.rb",
|
45
45
|
"lib/property/stored_role.rb",
|
46
|
+
"lib/property/version.rb",
|
46
47
|
"property.gemspec",
|
48
|
+
"test/database.rb",
|
47
49
|
"test/fixtures.rb",
|
48
50
|
"test/shoulda_macros/index.rb",
|
49
51
|
"test/shoulda_macros/role.rb",
|
@@ -51,6 +53,7 @@ Gem::Specification.new do |s|
|
|
51
53
|
"test/test_helper.rb",
|
52
54
|
"test/unit/property/attribute_test.rb",
|
53
55
|
"test/unit/property/base_test.rb",
|
56
|
+
"test/unit/property/column_test.rb",
|
54
57
|
"test/unit/property/declaration_test.rb",
|
55
58
|
"test/unit/property/dirty_test.rb",
|
56
59
|
"test/unit/property/index_complex_test.rb",
|
@@ -71,13 +74,15 @@ Gem::Specification.new do |s|
|
|
71
74
|
s.rubygems_version = %q{1.3.6}
|
72
75
|
s.summary = %q{model properties wrap into a single database column}
|
73
76
|
s.test_files = [
|
74
|
-
"test/
|
77
|
+
"test/database.rb",
|
78
|
+
"test/fixtures.rb",
|
75
79
|
"test/shoulda_macros/index.rb",
|
76
80
|
"test/shoulda_macros/role.rb",
|
77
81
|
"test/shoulda_macros/serialization.rb",
|
78
82
|
"test/test_helper.rb",
|
79
83
|
"test/unit/property/attribute_test.rb",
|
80
84
|
"test/unit/property/base_test.rb",
|
85
|
+
"test/unit/property/column_test.rb",
|
81
86
|
"test/unit/property/declaration_test.rb",
|
82
87
|
"test/unit/property/dirty_test.rb",
|
83
88
|
"test/unit/property/index_complex_test.rb",
|
data/test/database.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
|
2
|
+
begin
|
3
|
+
class PropertyMigration < ActiveRecord::Migration
|
4
|
+
def self.down
|
5
|
+
drop_table 'employees'
|
6
|
+
drop_table 'versions'
|
7
|
+
drop_table 'string_index'
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.up
|
11
|
+
create_table 'employees' do |t|
|
12
|
+
t.string 'type'
|
13
|
+
t.text 'properties'
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table 'versions' do |t|
|
17
|
+
t.integer 'employee_id'
|
18
|
+
t.string 'properties'
|
19
|
+
t.string 'title'
|
20
|
+
t.string 'comment'
|
21
|
+
t.string 'lang'
|
22
|
+
t.timestamps
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table 'dummies' do |t|
|
26
|
+
t.text 'properties'
|
27
|
+
end
|
28
|
+
|
29
|
+
# index strings in employees
|
30
|
+
create_table 'idx_employees_strings' do |t|
|
31
|
+
t.integer 'employee_id'
|
32
|
+
t.integer 'version_id'
|
33
|
+
t.string 'key'
|
34
|
+
t.string 'value'
|
35
|
+
end
|
36
|
+
|
37
|
+
# multilingual index strings in employees
|
38
|
+
create_table 'idx_employees_ml_strings' do |t|
|
39
|
+
t.integer 'employee_id'
|
40
|
+
t.integer 'version_id'
|
41
|
+
t.string 'lang'
|
42
|
+
t.integer 'site_id'
|
43
|
+
t.string 'key'
|
44
|
+
t.string 'value'
|
45
|
+
end
|
46
|
+
|
47
|
+
# index strings in employees
|
48
|
+
create_table 'idx_employees_specials' do |t|
|
49
|
+
t.integer 'id'
|
50
|
+
t.integer 'employee_id'
|
51
|
+
t.string 'key'
|
52
|
+
t.string 'value'
|
53
|
+
end
|
54
|
+
|
55
|
+
# index integer in employees
|
56
|
+
create_table 'idx_employees_integers' do |t|
|
57
|
+
t.integer 'employee_id'
|
58
|
+
t.integer 'version_id'
|
59
|
+
t.string 'key'
|
60
|
+
t.integer 'value'
|
61
|
+
end
|
62
|
+
|
63
|
+
# index text in employees
|
64
|
+
create_table 'idx_employees_texts' do |t|
|
65
|
+
t.integer 'employee_id'
|
66
|
+
t.string 'key'
|
67
|
+
t.text 'value'
|
68
|
+
end
|
69
|
+
|
70
|
+
# custom or legacy index table
|
71
|
+
create_table 'contacts' do |t|
|
72
|
+
t.integer 'employee_id'
|
73
|
+
t.string 'name'
|
74
|
+
t.string 'other_name'
|
75
|
+
end
|
76
|
+
|
77
|
+
# Database stored role
|
78
|
+
create_table 'roles' do |t|
|
79
|
+
t.integer 'id'
|
80
|
+
t.string 'name'
|
81
|
+
end
|
82
|
+
|
83
|
+
create_table 'columns' do |t|
|
84
|
+
t.integer 'id'
|
85
|
+
t.integer 'role_id'
|
86
|
+
t.string 'name'
|
87
|
+
# Property Type
|
88
|
+
t.string 'ptype'
|
89
|
+
# Indexed (we store an integer so that we can have multiple index types)
|
90
|
+
t.string 'index'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
ActiveRecord::Base.establish_connection(:adapter=>'sqlite3', :database=>':memory:')
|
96
|
+
log_path = Pathname(__FILE__).dirname + '../log/test.log'
|
97
|
+
Dir.mkdir(log_path.dirname) unless File.exist?(log_path.dirname)
|
98
|
+
ActiveRecord::Base.logger = Logger.new(File.open(log_path, 'wb'))
|
99
|
+
ActiveRecord::Migration.verbose = false
|
100
|
+
#PropertyMigration.migrate(:down)
|
101
|
+
PropertyMigration.migrate(:up)
|
102
|
+
ActiveRecord::Migration.verbose = true
|
103
|
+
end
|
data/test/fixtures.rb
CHANGED
@@ -28,122 +28,42 @@ class Version < ActiveRecord::Base
|
|
28
28
|
end
|
29
29
|
|
30
30
|
# To test custom class serialization
|
31
|
-
class
|
31
|
+
class Cat
|
32
32
|
attr_accessor :name, :toy
|
33
33
|
def self.json_create(data)
|
34
|
-
|
34
|
+
Cat.new(data['name'], data['toy'])
|
35
35
|
end
|
36
|
+
|
36
37
|
def initialize(name, toy)
|
37
38
|
@name, @toy = name, toy
|
38
39
|
end
|
40
|
+
|
39
41
|
def to_json(*args)
|
40
42
|
{ 'json_class' => self.class.to_s,
|
41
43
|
'name' => @name, 'toy' => @toy
|
42
44
|
}.to_json(*args)
|
43
45
|
end
|
46
|
+
|
44
47
|
def ==(other)
|
45
|
-
other.kind_of?(
|
48
|
+
other.kind_of?(Cat) && @name == other.name && @toy == other.toy
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
49
|
-
begin
|
50
|
-
class PropertyMigration < ActiveRecord::Migration
|
51
|
-
def self.down
|
52
|
-
drop_table 'employees'
|
53
|
-
drop_table 'versions'
|
54
|
-
drop_table 'string_index'
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.up
|
58
|
-
create_table 'employees' do |t|
|
59
|
-
t.string 'type'
|
60
|
-
t.text 'properties'
|
61
|
-
end
|
62
|
-
|
63
|
-
create_table 'versions' do |t|
|
64
|
-
t.integer 'employee_id'
|
65
|
-
t.string 'properties'
|
66
|
-
t.string 'title'
|
67
|
-
t.string 'comment'
|
68
|
-
t.string 'lang'
|
69
|
-
t.timestamps
|
70
|
-
end
|
71
|
-
|
72
|
-
create_table 'dummies' do |t|
|
73
|
-
t.text 'properties'
|
74
|
-
end
|
75
|
-
|
76
|
-
# index strings in employees
|
77
|
-
create_table 'i_string_employees' do |t|
|
78
|
-
t.integer 'employee_id'
|
79
|
-
t.integer 'version_id'
|
80
|
-
t.string 'key'
|
81
|
-
t.string 'value'
|
82
|
-
end
|
83
|
-
|
84
|
-
# multilingual index strings in employees
|
85
|
-
create_table 'i_ml_string_employees' do |t|
|
86
|
-
t.integer 'employee_id'
|
87
|
-
t.integer 'version_id'
|
88
|
-
t.string 'lang'
|
89
|
-
t.integer 'site_id'
|
90
|
-
t.string 'key'
|
91
|
-
t.string 'value'
|
92
|
-
end
|
93
|
-
|
94
|
-
# index strings in employees
|
95
|
-
create_table 'i_special_employees' do |t|
|
96
|
-
t.integer 'employee_id'
|
97
|
-
t.string 'key'
|
98
|
-
t.string 'value'
|
99
|
-
end
|
100
|
-
|
101
|
-
# index integer in employees
|
102
|
-
create_table 'i_integer_employees' do |t|
|
103
|
-
t.integer 'employee_id'
|
104
|
-
t.integer 'version_id'
|
105
|
-
t.string 'key'
|
106
|
-
t.integer 'value'
|
107
|
-
end
|
108
|
-
|
109
|
-
# index text in employees
|
110
|
-
create_table 'i_text_employees' do |t|
|
111
|
-
t.integer 'employee_id'
|
112
|
-
t.string 'key'
|
113
|
-
t.text 'value'
|
114
|
-
end
|
115
|
-
|
116
|
-
# custom or legacy index table
|
117
|
-
create_table 'contacts' do |t|
|
118
|
-
t.integer 'employee_id'
|
119
|
-
t.string 'name'
|
120
|
-
t.string 'other_name'
|
121
|
-
end
|
122
|
-
|
123
|
-
# Database stored role
|
124
|
-
create_table 'roles' do |t|
|
125
|
-
t.integer 'id'
|
126
|
-
t.string 'name'
|
127
|
-
end
|
128
|
-
|
129
|
-
create_table 'columns' do |t|
|
130
|
-
t.integer 'id'
|
131
|
-
t.integer 'role_id'
|
132
|
-
t.string 'name'
|
133
|
-
# Property Type
|
134
|
-
t.string 'ptype'
|
135
|
-
# Indexed (we store an integer so that we can have multiple index types)
|
136
|
-
t.string 'index'
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
52
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
53
|
+
class IdxEmployeesString < ActiveRecord::Base
|
54
|
+
end
|
55
|
+
|
56
|
+
class IdxEmployeesString < ActiveRecord::Base
|
57
|
+
end
|
58
|
+
|
59
|
+
class IdxEmployeesMlString < ActiveRecord::Base
|
60
|
+
end
|
61
|
+
|
62
|
+
class IdxEmployeesInteger < ActiveRecord::Base
|
63
|
+
end
|
64
|
+
|
65
|
+
class IdxEmployeesText < ActiveRecord::Base
|
66
|
+
end
|
67
|
+
|
68
|
+
class IdxEmployeesSpecial < ActiveRecord::Base
|
69
|
+
end
|