super_settings 1.0.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +34 -2
- data/README.md +121 -16
- data/VERSION +1 -1
- data/app/helpers/super_settings/settings_helper.rb +13 -3
- data/app/views/layouts/super_settings/settings.html.erb +1 -1
- data/config/routes.rb +1 -1
- data/db/migrate/20210414004553_create_super_settings.rb +1 -7
- data/lib/super_settings/application/api.js +4 -1
- data/lib/super_settings/application/helper.rb +56 -17
- data/lib/super_settings/application/images/arrow-down-short.svg +3 -0
- data/lib/super_settings/application/images/arrow-up-short.svg +3 -0
- data/lib/super_settings/application/images/info-circle.svg +4 -0
- data/lib/super_settings/application/images/pencil-square.svg +4 -0
- data/lib/super_settings/application/images/plus.svg +3 -1
- data/lib/super_settings/application/images/trash3.svg +3 -0
- data/lib/super_settings/application/images/x-circle.svg +4 -0
- data/lib/super_settings/application/index.html.erb +54 -37
- data/lib/super_settings/application/layout.html.erb +5 -2
- data/lib/super_settings/application/layout_styles.css +7 -151
- data/lib/super_settings/application/layout_vars.css.erb +21 -0
- data/lib/super_settings/application/scripts.js +100 -21
- data/lib/super_settings/application/style_vars.css.erb +62 -0
- data/lib/super_settings/application/styles.css +183 -14
- data/lib/super_settings/application.rb +18 -11
- data/lib/super_settings/attributes.rb +1 -8
- data/lib/super_settings/configuration.rb +9 -0
- data/lib/super_settings/context/current.rb +33 -0
- data/lib/super_settings/context.rb +3 -0
- data/lib/super_settings/controller_actions.rb +2 -2
- data/lib/super_settings/engine.rb +1 -3
- data/lib/super_settings/history_item.rb +1 -1
- data/lib/super_settings/http_client.rb +165 -0
- data/lib/super_settings/local_cache.rb +0 -15
- data/lib/super_settings/rack_application.rb +3 -3
- data/lib/super_settings/rest_api.rb +5 -4
- data/lib/super_settings/setting.rb +14 -3
- data/lib/super_settings/storage/active_record_storage/models.rb +28 -0
- data/lib/super_settings/storage/active_record_storage.rb +10 -20
- data/lib/super_settings/storage/history_attributes.rb +31 -0
- data/lib/super_settings/storage/http_storage.rb +60 -184
- data/lib/super_settings/storage/json_storage.rb +201 -0
- data/lib/super_settings/storage/mongodb_storage.rb +238 -0
- data/lib/super_settings/storage/redis_storage.rb +50 -111
- data/lib/super_settings/storage/s3_storage.rb +165 -0
- data/lib/super_settings/storage/storage_attributes.rb +64 -0
- data/lib/super_settings/storage/test_storage.rb +3 -5
- data/lib/super_settings/storage/transaction.rb +67 -0
- data/lib/super_settings/storage.rb +17 -8
- data/lib/super_settings/time_precision.rb +36 -0
- data/lib/super_settings.rb +48 -13
- data/super_settings.gemspec +11 -2
- metadata +30 -12
- data/lib/super_settings/application/images/edit.svg +0 -1
- data/lib/super_settings/application/images/info.svg +0 -1
- data/lib/super_settings/application/images/slash.svg +0 -1
- data/lib/super_settings/application/images/trash.svg +0 -1
- /data/{MIT-LICENSE → MIT-LICENSE.txt} +0 -0
@@ -122,7 +122,7 @@ module SuperSettings
|
|
122
122
|
#
|
123
123
|
# @return [Boolean]
|
124
124
|
def web_ui_enabled?
|
125
|
-
|
125
|
+
SuperSettings.configuration.controller.web_ui_enabled?
|
126
126
|
end
|
127
127
|
|
128
128
|
private
|
@@ -159,7 +159,7 @@ module SuperSettings
|
|
159
159
|
|
160
160
|
def handle_root_request(request)
|
161
161
|
response = check_authorization(request, write_required: true) do |user|
|
162
|
-
[200, {"content-type" => "text/html; charset=utf-8", "cache-control" => "no-cache"}, [Application.new(:default, add_to_head(request)
|
162
|
+
[200, {"content-type" => "text/html; charset=utf-8", "cache-control" => "no-cache"}, [Application.new(layout: :default, add_to_head: add_to_head(request), color_scheme: SuperSettings.configuration.controller.color_scheme).render]]
|
163
163
|
end
|
164
164
|
|
165
165
|
if [401, 403].include?(response.first)
|
@@ -236,7 +236,7 @@ module SuperSettings
|
|
236
236
|
|
237
237
|
def post_params(request)
|
238
238
|
if request.content_type.to_s.match?(/\Aapplication\/json/i) && request.body
|
239
|
-
request.params.merge(JSON.parse(request.body.
|
239
|
+
request.params.merge(JSON.parse(request.body.read))
|
240
240
|
else
|
241
241
|
request.params
|
242
242
|
end
|
@@ -23,7 +23,7 @@ module SuperSettings
|
|
23
23
|
# ...
|
24
24
|
# ]
|
25
25
|
def index
|
26
|
-
settings = Setting.active.sort_by(&:key)
|
26
|
+
settings = Setting.active.reject(&:deleted?).sort_by(&:key)
|
27
27
|
{settings: settings.collect(&:as_json)}
|
28
28
|
end
|
29
29
|
|
@@ -46,7 +46,8 @@ module SuperSettings
|
|
46
46
|
# updated_at: iso8601 string
|
47
47
|
# }
|
48
48
|
def show(key)
|
49
|
-
Setting.find_by_key(key)
|
49
|
+
setting = Setting.find_by_key(key)
|
50
|
+
setting.as_json if setting && !setting.deleted?
|
50
51
|
end
|
51
52
|
|
52
53
|
# The update operation uses a transaction to atomically update all settings.
|
@@ -156,7 +157,7 @@ module SuperSettings
|
|
156
157
|
#
|
157
158
|
# @example
|
158
159
|
# GET /last_updated_at
|
159
|
-
#
|
160
|
+
#
|
160
161
|
# The response payload is:
|
161
162
|
# {
|
162
163
|
# last_updated_at: iso8601 string
|
@@ -188,7 +189,7 @@ module SuperSettings
|
|
188
189
|
# ]
|
189
190
|
def updated_since(time)
|
190
191
|
time = Coerce.time(time)
|
191
|
-
settings = Setting.updated_since(time)
|
192
|
+
settings = Setting.updated_since(time).reject(&:deleted?)
|
192
193
|
{settings: settings.collect(&:as_json)}
|
193
194
|
end
|
194
195
|
end
|
@@ -54,7 +54,7 @@ module SuperSettings
|
|
54
54
|
# @api private
|
55
55
|
def storage
|
56
56
|
if @storage == NOT_SET
|
57
|
-
if defined?(::SuperSettings::Storage::ActiveRecordStorage)
|
57
|
+
if defined?(ActiveRecord) && defined?(::SuperSettings::Storage::ActiveRecordStorage)
|
58
58
|
::SuperSettings::Storage::ActiveRecordStorage
|
59
59
|
else
|
60
60
|
raise ArgumentError.new("No storage class defined for #{name}")
|
@@ -109,6 +109,7 @@ module SuperSettings
|
|
109
109
|
# @param time [Time]
|
110
110
|
# @return [Array<Setting>]
|
111
111
|
def updated_since(time)
|
112
|
+
time = SuperSettings::Coerce.time(time)
|
112
113
|
storage.with_connection do
|
113
114
|
storage.updated_since(time).collect { |record| new(record) }
|
114
115
|
end
|
@@ -219,6 +220,16 @@ module SuperSettings
|
|
219
220
|
next if Coerce.blank?(setting_params["key"])
|
220
221
|
next if ["value_type", "value", "description", "deleted"].all? { |name| Coerce.blank?(setting_params[name]) }
|
221
222
|
|
223
|
+
key_was = setting_params["key_was"]
|
224
|
+
if key_was && !changed.include?(key_was)
|
225
|
+
old_setting = Setting.find_by_key(key_was)
|
226
|
+
if old_setting
|
227
|
+
old_setting.deleted = true
|
228
|
+
old_setting.changed_by = changed_by
|
229
|
+
changed[old_setting.key] = old_setting
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
222
233
|
key = setting_params["key"]
|
223
234
|
setting = changed[key] || Setting.find_by_key(key)
|
224
235
|
unless setting
|
@@ -372,7 +383,7 @@ module SuperSettings
|
|
372
383
|
#
|
373
384
|
# @param val [Time, DateTime]
|
374
385
|
def created_at=(val)
|
375
|
-
val =
|
386
|
+
val = TimePrecision.new(val).time
|
376
387
|
will_change!(:created_at, val) unless created_at == val
|
377
388
|
@record.created_at = val
|
378
389
|
end
|
@@ -388,7 +399,7 @@ module SuperSettings
|
|
388
399
|
#
|
389
400
|
# @param val [Time, DateTime]
|
390
401
|
def updated_at=(val)
|
391
|
-
val =
|
402
|
+
val = TimePrecision.new(val).time
|
392
403
|
will_change!(:updated_at, val) unless updated_at == val
|
393
404
|
@record.updated_at = val
|
394
405
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SuperSettings
|
4
|
+
module Storage
|
5
|
+
class ActiveRecordStorage
|
6
|
+
# Base class that the models extend from.
|
7
|
+
class ApplicationRecord < ActiveRecord::Base
|
8
|
+
self.abstract_class = true
|
9
|
+
end
|
10
|
+
|
11
|
+
class Model < ApplicationRecord
|
12
|
+
self.table_name = "super_settings"
|
13
|
+
|
14
|
+
has_many :history_items, class_name: "SuperSettings::Storage::ActiveRecordStorage::HistoryModel", foreign_key: :key, primary_key: :key
|
15
|
+
end
|
16
|
+
|
17
|
+
class HistoryModel < ApplicationRecord
|
18
|
+
self.table_name = "super_settings_histories"
|
19
|
+
|
20
|
+
# Since these models are created automatically on a callback, ensure that the data will
|
21
|
+
# fit into the database columns since we can't handle any validation errors.
|
22
|
+
before_validation do
|
23
|
+
self.changed_by = changed_by.to_s[0, 150] if changed_by.present?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -10,26 +10,9 @@ module SuperSettings
|
|
10
10
|
# @example
|
11
11
|
# rake app:super_settings:install:migrations
|
12
12
|
class ActiveRecordStorage
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
class Model < ApplicationRecord
|
19
|
-
self.table_name = "super_settings"
|
20
|
-
|
21
|
-
has_many :history_items, class_name: "SuperSettings::Storage::ActiveRecordStorage::HistoryModel", foreign_key: :key, primary_key: :key
|
22
|
-
end
|
23
|
-
|
24
|
-
class HistoryModel < ApplicationRecord
|
25
|
-
self.table_name = "super_settings_histories"
|
26
|
-
|
27
|
-
# Since these models are created automatically on a callback, ensure that the data will
|
28
|
-
# fit into the database columns since we can't handle any validation errors.
|
29
|
-
before_validation do
|
30
|
-
self.changed_by = changed_by.to_s[0, 150] if changed_by.present?
|
31
|
-
end
|
32
|
-
end
|
13
|
+
autoload :ApplicationRecord, File.join(__dir__, "active_record_storage/models")
|
14
|
+
autoload :Model, File.join(__dir__, "active_record_storage/models")
|
15
|
+
autoload :HistoryModel, File.join(__dir__, "active_record_storage/models")
|
33
16
|
|
34
17
|
include Storage
|
35
18
|
|
@@ -77,6 +60,13 @@ module SuperSettings
|
|
77
60
|
Model.transaction(&block)
|
78
61
|
end
|
79
62
|
|
63
|
+
def destroy_all
|
64
|
+
ApplicationRecord.transaction do
|
65
|
+
Model.delete_all
|
66
|
+
HistoryModel.delete_all
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
80
70
|
protected
|
81
71
|
|
82
72
|
# Only load settings asynchronously if there is an extra database connection left in the
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SuperSettings
|
4
|
+
module Storage
|
5
|
+
# Generic class that can be extended to represent a history record for a setting in memory.
|
6
|
+
class HistoryAttributes
|
7
|
+
include SuperSettings::Attributes
|
8
|
+
|
9
|
+
attr_accessor :key, :value, :changed_by
|
10
|
+
attr_writer :deleted
|
11
|
+
attr_reader :created_at
|
12
|
+
|
13
|
+
def initialize(*)
|
14
|
+
@key = nil
|
15
|
+
@value = nil
|
16
|
+
@changed_by = nil
|
17
|
+
@created_at = nil
|
18
|
+
@deleted = false
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def created_at=(val)
|
23
|
+
@created_at = TimePrecision.new(val).time
|
24
|
+
end
|
25
|
+
|
26
|
+
def deleted?
|
27
|
+
!!@deleted
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,59 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "json"
|
4
|
-
require "net/http"
|
5
|
-
|
6
3
|
module SuperSettings
|
7
4
|
module Storage
|
8
5
|
# SuperSettings::Storage model that reads from a remote service running the SuperSettings REST API.
|
9
6
|
# This storage engine is read only. It is intended to allow microservices to read settings from a
|
10
7
|
# central application that exposes the SuperSettings::RestAPI.
|
11
|
-
|
8
|
+
#
|
9
|
+
# You must the the base_url class attribute to the base URL of a SuperSettings REST API endpoint.
|
10
|
+
# You can also set the timeout, headers, and query_params used in reqeusts to the API.
|
11
|
+
class HttpStorage < StorageAttributes
|
12
12
|
include Storage
|
13
|
+
include Transaction
|
13
14
|
|
14
15
|
DEFAULT_HEADERS = {"Accept" => "application/json"}.freeze
|
15
16
|
DEFAULT_TIMEOUT = 5.0
|
16
17
|
|
18
|
+
@base_url = nil
|
19
|
+
@timeout = nil
|
17
20
|
@headers = {}
|
18
21
|
@query_params = {}
|
22
|
+
@http_client = nil
|
23
|
+
@http_client_hash = nil
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
class Error < StandardError
|
23
|
-
end
|
24
|
-
|
25
|
-
class NotFoundError < Error
|
25
|
+
class HistoryStorage < HistoryAttributes
|
26
26
|
end
|
27
27
|
|
28
|
-
class
|
29
|
-
|
30
|
-
|
31
|
-
def initialize(message, errors:)
|
32
|
-
super(message)
|
33
|
-
@errors = errors
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class HistoryStorage
|
38
|
-
include SuperSettings::Attributes
|
39
|
-
|
40
|
-
attr_accessor :key, :value, :changed_by, :deleted
|
28
|
+
class << self
|
29
|
+
# Set the base URL for the SuperSettings REST API.
|
30
|
+
attr_accessor :base_url
|
41
31
|
|
42
|
-
|
43
|
-
|
44
|
-
super
|
45
|
-
end
|
32
|
+
# Set the timeout for requests to the SuperSettings REST API.
|
33
|
+
attr_accessor :timeout
|
46
34
|
|
47
|
-
|
48
|
-
|
49
|
-
|
35
|
+
# Add headers to this hash to add them to all requests to the SuperSettings REST API.
|
36
|
+
#
|
37
|
+
# @example
|
38
|
+
#
|
39
|
+
# SuperSettings::HttpStorage.headers["Authorization"] = "Bearer 12345"
|
40
|
+
attr_reader :headers
|
50
41
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
42
|
+
# Add query parameters to this hash to add them to all requests to the SuperSettings REST API.
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
#
|
46
|
+
# SuperSettings::HttpStorage.query_params["access_token"] = "12345"
|
47
|
+
attr_reader :query_params
|
55
48
|
|
56
|
-
class << self
|
57
49
|
def all
|
58
50
|
call_api(:get, "/settings")["settings"].collect do |attributes|
|
59
51
|
new(attributes)
|
@@ -68,9 +60,9 @@ module SuperSettings
|
|
68
60
|
|
69
61
|
def find_by_key(key)
|
70
62
|
record = new(call_api(:get, "/setting", key: key))
|
71
|
-
record.
|
63
|
+
record.persisted = true
|
72
64
|
record
|
73
|
-
rescue NotFoundError
|
65
|
+
rescue HttpClient::NotFoundError
|
74
66
|
nil
|
75
67
|
end
|
76
68
|
|
@@ -79,13 +71,30 @@ module SuperSettings
|
|
79
71
|
SuperSettings::Coerce.time(value)
|
80
72
|
end
|
81
73
|
|
82
|
-
|
74
|
+
def save_all(changes)
|
75
|
+
payload = []
|
76
|
+
changes.each do |setting|
|
77
|
+
setting_payload = {key: setting.key}
|
83
78
|
|
84
|
-
|
79
|
+
if setting.deleted?
|
80
|
+
setting_payload[:deleted] = true
|
81
|
+
else
|
82
|
+
setting_payload[:value] = setting.value
|
83
|
+
setting_payload[:value_type] = setting.value_type
|
84
|
+
setting_payload[:description] = setting.description
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
+
payload << setting_payload
|
88
|
+
end
|
87
89
|
|
88
|
-
|
90
|
+
begin
|
91
|
+
call_api(:post, "/settings", settings: payload)
|
92
|
+
rescue HttpClient::InvalidRecordError
|
93
|
+
return false
|
94
|
+
end
|
95
|
+
|
96
|
+
true
|
97
|
+
end
|
89
98
|
|
90
99
|
protected
|
91
100
|
|
@@ -96,115 +105,21 @@ module SuperSettings
|
|
96
105
|
private
|
97
106
|
|
98
107
|
def call_api(method, path, params = {})
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
request_headers = DEFAULT_HEADERS.merge(headers)
|
104
|
-
if method == :post && !params&.empty?
|
105
|
-
body = params.to_json
|
106
|
-
request_headers["content-type"] = "application/json; charset=utf8-"
|
107
|
-
end
|
108
|
-
|
109
|
-
response = http_request(method: method, uri: uri, headers: request_headers, body: body)
|
110
|
-
|
111
|
-
begin
|
112
|
-
response.value # raises exception unless response is a success
|
113
|
-
JSON.parse(response.body)
|
114
|
-
rescue Net::ProtocolError
|
115
|
-
if [404, 410].include?(response.code.to_i)
|
116
|
-
raise NotFoundError.new("#{response.code} #{response.message}")
|
117
|
-
elsif response.code.to_i == 422
|
118
|
-
raise InvalidRecordError.new("#{response.code} #{response.message}", errors: JSON.parse(response.body)["errors"])
|
119
|
-
else
|
120
|
-
raise Error.new("#{response.code} #{response.message}")
|
121
|
-
end
|
122
|
-
rescue JSON::JSONError => e
|
123
|
-
raise Error.new(e.message)
|
108
|
+
if method == :post
|
109
|
+
http_client.post(path, params)
|
110
|
+
else
|
111
|
+
http_client.get(path, params)
|
124
112
|
end
|
125
113
|
end
|
126
114
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
http.open_timeout = (timeout || DEFAULT_TIMEOUT)
|
133
|
-
if uri.scheme == "https"
|
134
|
-
http.use_ssl = true
|
135
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
136
|
-
end
|
137
|
-
|
138
|
-
request = ((method == :post) ? Net::HTTP::Post.new(uri.request_uri) : Net::HTTP::Get.new(uri.request_uri))
|
139
|
-
set_headers(request, headers)
|
140
|
-
request.body = body if body
|
141
|
-
|
142
|
-
response = http.request(request)
|
143
|
-
ensure
|
144
|
-
begin
|
145
|
-
http.finish if http.started?
|
146
|
-
rescue IOError
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
if response.is_a?(Net::HTTPRedirection)
|
151
|
-
location = resp["location"]
|
152
|
-
if redirect_count < 5 && SuperSettings::Coerce.present?(location)
|
153
|
-
return http_request(method: :get, uri: URI(location), headers: headers, body: body, redirect_count: redirect_count + 1)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
response
|
158
|
-
end
|
159
|
-
|
160
|
-
def api_uri(path, params)
|
161
|
-
uri = URI("#{base_url.chomp("/")}#{path}")
|
162
|
-
if params && !params.empty?
|
163
|
-
q = []
|
164
|
-
q << uri.query unless uri.query.to_s.empty?
|
165
|
-
params.each do |name, value|
|
166
|
-
q << "#{URI.encode_www_form_component(name.to_s)}=#{URI.encode_www_form_component(value.to_s)}"
|
167
|
-
end
|
168
|
-
uri.query = q.join("&")
|
115
|
+
def http_client
|
116
|
+
hash = [base_url, timeout, headers, query_params].hash
|
117
|
+
if @http_client.nil? || @http_client_hash != hash
|
118
|
+
@http_client = HttpClient.new(base_url, headers: headers, params: query_params, timeout: timeout)
|
119
|
+
@http_client_hash = hash
|
169
120
|
end
|
170
|
-
|
171
|
-
end
|
172
|
-
|
173
|
-
def set_headers(request, headers)
|
174
|
-
headers.each do |name, value|
|
175
|
-
name = name.to_s
|
176
|
-
values = Array(value)
|
177
|
-
request[name] = values[0].to_s
|
178
|
-
values[1, values.length].each do |val|
|
179
|
-
request.add_field(name, val.to_s)
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def initialize(*)
|
186
|
-
@persisted = false
|
187
|
-
@deleted = false
|
188
|
-
super
|
189
|
-
end
|
190
|
-
|
191
|
-
def save!
|
192
|
-
payload = {key: key}
|
193
|
-
if deleted?
|
194
|
-
payload[:deleted] = true
|
195
|
-
else
|
196
|
-
payload[:value] = value
|
197
|
-
payload[:value_type] = value_type
|
198
|
-
payload[:description] = description
|
199
|
-
end
|
200
|
-
|
201
|
-
begin
|
202
|
-
call_api(:post, "/settings", settings: [payload])
|
203
|
-
set_persisted!
|
204
|
-
rescue InvalidRecordError
|
205
|
-
return false
|
121
|
+
@http_client
|
206
122
|
end
|
207
|
-
true
|
208
123
|
end
|
209
124
|
|
210
125
|
def history(limit: nil, offset: 0)
|
@@ -227,50 +142,11 @@ module SuperSettings
|
|
227
142
|
self
|
228
143
|
end
|
229
144
|
|
230
|
-
def key=(value)
|
231
|
-
@key = (Coerce.blank?(value) ? nil : value.to_s)
|
232
|
-
end
|
233
|
-
|
234
|
-
def raw_value=(value)
|
235
|
-
@raw_value = (Coerce.blank?(value) ? nil : value.to_s)
|
236
|
-
end
|
237
145
|
alias_method :value=, :raw_value=
|
238
146
|
alias_method :value, :raw_value
|
239
147
|
|
240
|
-
def value_type=(value)
|
241
|
-
@value_type = (Coerce.blank?(value) ? nil : value.to_s)
|
242
|
-
end
|
243
|
-
|
244
|
-
def description=(value)
|
245
|
-
@description = (Coerce.blank?(value) ? nil : value.to_s)
|
246
|
-
end
|
247
|
-
|
248
|
-
def deleted=(value)
|
249
|
-
@deleted = Coerce.boolean(value)
|
250
|
-
end
|
251
|
-
|
252
|
-
def created_at=(value)
|
253
|
-
@created_at = SuperSettings::Coerce.time(value)
|
254
|
-
end
|
255
|
-
|
256
|
-
def updated_at=(value)
|
257
|
-
@updated_at = SuperSettings::Coerce.time(value)
|
258
|
-
end
|
259
|
-
|
260
|
-
def deleted?
|
261
|
-
!!@deleted
|
262
|
-
end
|
263
|
-
|
264
|
-
def persisted?
|
265
|
-
!!@persisted
|
266
|
-
end
|
267
|
-
|
268
148
|
private
|
269
149
|
|
270
|
-
def set_persisted!
|
271
|
-
@persisted = true
|
272
|
-
end
|
273
|
-
|
274
150
|
def call_api(method, path, params = {})
|
275
151
|
self.class.send(:call_api, method, path, params)
|
276
152
|
end
|