ledermann-rails-settings 1.2.0 → 2.0.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.
- checksums.yaml +7 -0
- data/.travis.yml +2 -3
- data/Changelog.md +22 -1
- data/Gemfile +1 -1
- data/MIT-LICENSE +6 -5
- data/README.md +133 -158
- data/Rakefile +4 -9
- data/ci/Gemfile.rails-3.1.x +4 -3
- data/ci/Gemfile.rails-3.2.x +4 -3
- data/lib/generators/rails_settings/migration/migration_generator.rb +23 -0
- data/lib/generators/rails_settings/migration/templates/migration.rb +15 -0
- data/lib/rails-settings.rb +14 -5
- data/lib/rails-settings/base.rb +36 -0
- data/lib/rails-settings/configuration.rb +32 -0
- data/lib/rails-settings/scopes.rb +33 -0
- data/lib/rails-settings/setting_object.rb +64 -0
- data/lib/rails-settings/version.rb +2 -2
- data/rails-settings.gemspec +18 -21
- data/spec/configuration_spec.rb +108 -0
- data/spec/queries_spec.rb +108 -0
- data/spec/scopes_spec.rb +31 -0
- data/spec/serialize_spec.rb +40 -0
- data/spec/setting_object_spec.rb +119 -0
- data/spec/settings_spec.rb +206 -0
- data/spec/spec_helper.rb +90 -0
- data/spec/support/matchers/perform_queries.rb +18 -0
- data/spec/support/query_counter.rb +17 -0
- metadata +100 -121
- data/ci/Gemfile.rails-2.3.x +0 -5
- data/ci/Gemfile.rails-3.0.x +0 -5
- data/init.rb +0 -1
- data/lib/rails-settings/active_record.rb +0 -38
- data/lib/rails-settings/null_store.rb +0 -48
- data/lib/rails-settings/scoped_settings.rb +0 -14
- data/lib/rails-settings/settings.rb +0 -142
- data/test/settings_test.rb +0 -252
- data/test/test_helper.rb +0 -34
@@ -0,0 +1,18 @@
|
|
1
|
+
RSpec::Matchers.define :perform_queries do |expected|
|
2
|
+
match do |block|
|
3
|
+
query_count(&block) == expected
|
4
|
+
end
|
5
|
+
|
6
|
+
failure_message_for_should do |actual|
|
7
|
+
"Expected to run #{expected} queries, got #{@counter.query_count}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def query_count(&block)
|
11
|
+
@counter = ActiveRecord::QueryCounter.new
|
12
|
+
ActiveSupport::Notifications.subscribe('sql.active_record', @counter.to_proc)
|
13
|
+
yield
|
14
|
+
ActiveSupport::Notifications.unsubscribe(@counter.to_proc)
|
15
|
+
|
16
|
+
@counter.query_count
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class QueryCounter
|
3
|
+
attr_reader :query_count
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@query_count = 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_proc
|
10
|
+
lambda(&method(:callback))
|
11
|
+
end
|
12
|
+
|
13
|
+
def callback(name, start, finish, message_id, values)
|
14
|
+
@query_count += 1 unless %w(CACHE SCHEMA).include?(values[:name]) || values[:sql] == 'begin transaction' || values[:sql] == 'commit transaction'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,103 +1,78 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ledermann-rails-settings
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 2
|
9
|
-
- 0
|
10
|
-
version: 1.2.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Georg Ledermann
|
14
8
|
autorequire:
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
21
|
-
name: rake
|
22
|
-
prerelease: false
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
-
none: false
|
25
|
-
requirements:
|
26
|
-
- - ">="
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
hash: 3
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
version: "0"
|
32
|
-
type: :development
|
33
|
-
version_requirements: *id001
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: sqlite3
|
36
|
-
prerelease: false
|
37
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
-
none: false
|
39
|
-
requirements:
|
40
|
-
- - ">="
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
hash: 3
|
43
|
-
segments:
|
44
|
-
- 0
|
45
|
-
version: "0"
|
46
|
-
type: :development
|
47
|
-
version_requirements: *id002
|
48
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2013-03-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
49
14
|
name: activerecord
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
hash: 5
|
57
|
-
segments:
|
58
|
-
- 2
|
59
|
-
- 3
|
60
|
-
version: "2.3"
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.1'
|
61
20
|
type: :runtime
|
62
|
-
version_requirements: *id003
|
63
|
-
- !ruby/object:Gem::Dependency
|
64
|
-
name: rake
|
65
21
|
prerelease: false
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
75
34
|
type: :development
|
76
|
-
|
77
|
-
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
78
42
|
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
79
49
|
prerelease: false
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.13'
|
89
62
|
type: :development
|
90
|
-
|
91
|
-
|
92
|
-
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.13'
|
69
|
+
description: Settings gem for Ruby on Rails
|
70
|
+
email:
|
93
71
|
- mail@georg-ledermann.de
|
94
72
|
executables: []
|
95
|
-
|
96
73
|
extensions: []
|
97
|
-
|
98
74
|
extra_rdoc_files: []
|
99
|
-
|
100
|
-
files:
|
75
|
+
files:
|
101
76
|
- .gitignore
|
102
77
|
- .travis.yml
|
103
78
|
- Changelog.md
|
@@ -105,53 +80,57 @@ files:
|
|
105
80
|
- MIT-LICENSE
|
106
81
|
- README.md
|
107
82
|
- Rakefile
|
108
|
-
- ci/Gemfile.rails-2.3.x
|
109
|
-
- ci/Gemfile.rails-3.0.x
|
110
83
|
- ci/Gemfile.rails-3.1.x
|
111
84
|
- ci/Gemfile.rails-3.2.x
|
112
|
-
-
|
85
|
+
- lib/generators/rails_settings/migration/migration_generator.rb
|
86
|
+
- lib/generators/rails_settings/migration/templates/migration.rb
|
113
87
|
- lib/rails-settings.rb
|
114
|
-
- lib/rails-settings/
|
115
|
-
- lib/rails-settings/
|
116
|
-
- lib/rails-settings/
|
117
|
-
- lib/rails-settings/
|
88
|
+
- lib/rails-settings/base.rb
|
89
|
+
- lib/rails-settings/configuration.rb
|
90
|
+
- lib/rails-settings/scopes.rb
|
91
|
+
- lib/rails-settings/setting_object.rb
|
118
92
|
- lib/rails-settings/version.rb
|
119
93
|
- rails-settings.gemspec
|
120
|
-
-
|
121
|
-
-
|
94
|
+
- spec/configuration_spec.rb
|
95
|
+
- spec/queries_spec.rb
|
96
|
+
- spec/scopes_spec.rb
|
97
|
+
- spec/serialize_spec.rb
|
98
|
+
- spec/setting_object_spec.rb
|
99
|
+
- spec/settings_spec.rb
|
100
|
+
- spec/spec_helper.rb
|
101
|
+
- spec/support/matchers/perform_queries.rb
|
102
|
+
- spec/support/query_counter.rb
|
122
103
|
homepage: https://github.com/ledermann/rails-settings
|
123
104
|
licenses: []
|
124
|
-
|
105
|
+
metadata: {}
|
125
106
|
post_install_message:
|
126
107
|
rdoc_options: []
|
127
|
-
|
128
|
-
require_paths:
|
108
|
+
require_paths:
|
129
109
|
- lib
|
130
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
none: false
|
141
|
-
requirements:
|
142
|
-
- - ">="
|
143
|
-
- !ruby/object:Gem::Version
|
144
|
-
hash: 3
|
145
|
-
segments:
|
146
|
-
- 0
|
147
|
-
version: "0"
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
148
120
|
requirements: []
|
149
|
-
|
150
|
-
|
151
|
-
rubygems_version: 1.8.24
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 2.0.2
|
152
123
|
signing_key:
|
153
|
-
specification_version:
|
154
|
-
summary:
|
155
|
-
|
156
|
-
|
157
|
-
-
|
124
|
+
specification_version: 4
|
125
|
+
summary: 'Handling settings for ActiveRecord objects by storing them as serialized
|
126
|
+
Hash in a separate database table. Optional: Defaults and Namespaces.'
|
127
|
+
test_files:
|
128
|
+
- spec/configuration_spec.rb
|
129
|
+
- spec/queries_spec.rb
|
130
|
+
- spec/scopes_spec.rb
|
131
|
+
- spec/serialize_spec.rb
|
132
|
+
- spec/setting_object_spec.rb
|
133
|
+
- spec/settings_spec.rb
|
134
|
+
- spec/spec_helper.rb
|
135
|
+
- spec/support/matchers/perform_queries.rb
|
136
|
+
- spec/support/query_counter.rb
|
data/ci/Gemfile.rails-2.3.x
DELETED
data/ci/Gemfile.rails-3.0.x
DELETED
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'rails-settings'
|
@@ -1,38 +0,0 @@
|
|
1
|
-
ActiveRecord::Base.class_eval do
|
2
|
-
def self.has_settings
|
3
|
-
class_eval do
|
4
|
-
def settings
|
5
|
-
ScopedSettings.for_target(self)
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.settings
|
9
|
-
ScopedSettings.for_target(self)
|
10
|
-
end
|
11
|
-
|
12
|
-
def settings=(hash)
|
13
|
-
hash.each { |k,v| settings[k] = v }
|
14
|
-
end
|
15
|
-
|
16
|
-
after_destroy { |user| user.settings.target_scoped.delete_all }
|
17
|
-
|
18
|
-
scope_method = ActiveRecord::VERSION::MAJOR < 3 ? :named_scope : :scope
|
19
|
-
|
20
|
-
send scope_method, :with_settings, :joins => "JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
|
21
|
-
settings.target_type = '#{self.base_class.name}')",
|
22
|
-
:select => "DISTINCT #{self.table_name}.*"
|
23
|
-
|
24
|
-
send scope_method, :with_settings_for, lambda { |var| { :joins => "JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
|
25
|
-
settings.target_type = '#{self.base_class.name}') AND
|
26
|
-
settings.var = '#{var}'" } }
|
27
|
-
|
28
|
-
send scope_method, :without_settings, :joins => "LEFT JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
|
29
|
-
settings.target_type = '#{self.base_class.name}')",
|
30
|
-
:conditions => 'settings.id IS NULL'
|
31
|
-
|
32
|
-
send scope_method, :without_settings_for, lambda { |var| { :joins => "LEFT JOIN settings ON (settings.target_id = #{self.table_name}.#{self.primary_key} AND
|
33
|
-
settings.target_type = '#{self.base_class.name}') AND
|
34
|
-
settings.var = '#{var}'",
|
35
|
-
:conditions => 'settings.id IS NULL' } }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
unless defined?(ActiveSupport::Cache::NullStore)
|
2
|
-
# Copied from Rails 3
|
3
|
-
# https://github.com/rails/rails/blob/master/activesupport/lib/active_support/cache/null_store.rb
|
4
|
-
module ActiveSupport
|
5
|
-
module Cache
|
6
|
-
# A cache store implementation which doesn't actually store anything. Useful in
|
7
|
-
# development and test environments where you don't want caching turned on but
|
8
|
-
# need to go through the caching interface.
|
9
|
-
#
|
10
|
-
# This cache does implement the local cache strategy, so values will actually
|
11
|
-
# be cached inside blocks that utilize this strategy. See
|
12
|
-
# ActiveSupport::Cache::Strategy::LocalCache for more details.
|
13
|
-
class NullStore < Store
|
14
|
-
def initialize(options = nil)
|
15
|
-
super()
|
16
|
-
extend Strategy::LocalCache
|
17
|
-
end
|
18
|
-
|
19
|
-
def clear(options = nil)
|
20
|
-
end
|
21
|
-
|
22
|
-
def cleanup(options = nil)
|
23
|
-
end
|
24
|
-
|
25
|
-
def increment(name, amount = 1, options = nil)
|
26
|
-
end
|
27
|
-
|
28
|
-
def decrement(name, amount = 1, options = nil)
|
29
|
-
end
|
30
|
-
|
31
|
-
def delete_matched(matcher, options = nil)
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
def read_entry(key, options) # :nodoc:
|
36
|
-
end
|
37
|
-
|
38
|
-
def write_entry(key, entry, options) # :nodoc:
|
39
|
-
true
|
40
|
-
end
|
41
|
-
|
42
|
-
def delete_entry(key, options) # :nodoc:
|
43
|
-
false
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
class ScopedSettings < Settings
|
2
|
-
def self.for_target(target)
|
3
|
-
@target = target
|
4
|
-
self
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.target_id
|
8
|
-
@target.is_a?(Class) ? nil : @target.id
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.target_type
|
12
|
-
@target.is_a?(Class) ? @target.name : @target.class.base_class.to_s
|
13
|
-
end
|
14
|
-
end
|
@@ -1,142 +0,0 @@
|
|
1
|
-
class Settings < ActiveRecord::Base
|
2
|
-
class SettingNotFound < RuntimeError; end
|
3
|
-
|
4
|
-
cattr_accessor :defaults
|
5
|
-
self.defaults = {}.with_indifferent_access
|
6
|
-
|
7
|
-
# cache must follow the contract of ActiveSupport::Cache. Defaults to no-op.
|
8
|
-
cattr_accessor :cache
|
9
|
-
self.cache = ActiveSupport::Cache::NullStore.new
|
10
|
-
|
11
|
-
# options passed to cache.fetch() and cache.write(). example: {:expires_in => 5.minutes}
|
12
|
-
cattr_accessor :cache_options
|
13
|
-
self.cache_options = {}
|
14
|
-
|
15
|
-
def self.cache_key(var_name)
|
16
|
-
[target_id, target_type, var_name].compact.join("::")
|
17
|
-
end
|
18
|
-
|
19
|
-
# Support old plugin
|
20
|
-
if defined?(SettingsDefaults::DEFAULTS)
|
21
|
-
self.defaults = SettingsDefaults::DEFAULTS.with_indifferent_access
|
22
|
-
end
|
23
|
-
|
24
|
-
#get or set a variable with the variable as the called method
|
25
|
-
def self.method_missing(method, *args)
|
26
|
-
if self.respond_to?(method)
|
27
|
-
super
|
28
|
-
else
|
29
|
-
method_name = method.to_s
|
30
|
-
|
31
|
-
#set a value for a variable
|
32
|
-
if method_name =~ /=$/
|
33
|
-
var_name = method_name.gsub('=', '')
|
34
|
-
value = args.first
|
35
|
-
self[var_name] = value
|
36
|
-
|
37
|
-
#retrieve a value
|
38
|
-
else
|
39
|
-
self[method_name]
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
#destroy the specified settings record
|
46
|
-
def self.destroy(var_name)
|
47
|
-
var_name = var_name.to_s
|
48
|
-
begin
|
49
|
-
target(var_name).destroy
|
50
|
-
cache.delete(cache_key(var_name))
|
51
|
-
true
|
52
|
-
rescue NoMethodError
|
53
|
-
raise SettingNotFound, "Setting variable \"#{var_name}\" not found"
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.delete_all(conditions = nil)
|
58
|
-
cache.clear
|
59
|
-
super
|
60
|
-
end
|
61
|
-
|
62
|
-
#retrieve all settings as a hash (optionally starting with a given namespace)
|
63
|
-
def self.all(starting_with=nil)
|
64
|
-
options = starting_with ? { :conditions => "var LIKE '#{starting_with}%'"} : {}
|
65
|
-
vars = target_scoped.find(:all, {:select => 'var, value'}.merge(options))
|
66
|
-
|
67
|
-
result = {}
|
68
|
-
vars.each do |record|
|
69
|
-
result[record.var] = record.value
|
70
|
-
end
|
71
|
-
defaults = @@defaults.select{ |k, v| k =~ /^#{starting_with}/ }
|
72
|
-
defaults = Hash[defaults] if defaults.is_a?(Array)
|
73
|
-
defaults.merge(result).with_indifferent_access
|
74
|
-
end
|
75
|
-
|
76
|
-
#get a setting value by [] notation
|
77
|
-
def self.[](var_name)
|
78
|
-
cache.fetch(cache_key(var_name), cache_options) do
|
79
|
-
if var = target(var_name)
|
80
|
-
var.value
|
81
|
-
else
|
82
|
-
if target_id.nil?
|
83
|
-
@@defaults[var_name.to_s]
|
84
|
-
else
|
85
|
-
target_type.constantize.settings[var_name.to_s]
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
#set a setting value by [] notation
|
92
|
-
def self.[]=(var_name, value)
|
93
|
-
record = target_scoped.find_or_initialize_by_var(var_name.to_s)
|
94
|
-
record.value = value
|
95
|
-
record.save!
|
96
|
-
cache.write(cache_key(var_name), value, cache_options)
|
97
|
-
value
|
98
|
-
end
|
99
|
-
|
100
|
-
def self.merge!(var_name, hash_value)
|
101
|
-
raise ArgumentError unless hash_value.is_a?(Hash)
|
102
|
-
|
103
|
-
old_value = self[var_name] || {}
|
104
|
-
raise TypeError, "Existing value is not a hash, can't merge!" unless old_value.is_a?(Hash)
|
105
|
-
|
106
|
-
new_value = old_value.merge(hash_value)
|
107
|
-
self[var_name] = new_value if new_value != old_value
|
108
|
-
|
109
|
-
new_value
|
110
|
-
end
|
111
|
-
|
112
|
-
def self.target(var_name)
|
113
|
-
target_scoped.find_by_var(var_name.to_s)
|
114
|
-
end
|
115
|
-
|
116
|
-
#get the value field, YAML decoded
|
117
|
-
def value
|
118
|
-
YAML::load(self[:value])
|
119
|
-
end
|
120
|
-
|
121
|
-
#set the value field, YAML encoded
|
122
|
-
def value=(new_value)
|
123
|
-
self[:value] = new_value.to_yaml
|
124
|
-
end
|
125
|
-
|
126
|
-
def self.target_scoped
|
127
|
-
Settings.scoped_by_target_type_and_target_id(target_type, target_id)
|
128
|
-
end
|
129
|
-
|
130
|
-
#Deprecated!
|
131
|
-
def self.reload # :nodoc:
|
132
|
-
self
|
133
|
-
end
|
134
|
-
|
135
|
-
def self.target_id
|
136
|
-
nil
|
137
|
-
end
|
138
|
-
|
139
|
-
def self.target_type
|
140
|
-
nil
|
141
|
-
end
|
142
|
-
end
|