choron_support 0.1.9 → 0.1.11
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 +4 -4
- data/.rubocop.yml +138 -6
- data/.rubocop_todo.yml +1 -0
- data/CHANGELOG.md +11 -3
- data/Gemfile.lock +1 -1
- data/README.md +2 -6
- data/choron_support.gemspec +8 -7
- data/docs/props.md +17 -217
- data/lib/choron_support/as_props.rb +34 -24
- data/lib/choron_support/domain_delegate.rb +1 -3
- data/lib/choron_support/helper.rb +7 -9
- data/lib/choron_support/props/attributes.rb +186 -349
- data/lib/choron_support/props/base.rb +12 -26
- data/lib/choron_support/props/ext/hash.rb +1 -1
- data/lib/choron_support/props/ext/relation.rb +1 -1
- data/lib/choron_support/props/private/setting.rb +40 -0
- data/lib/choron_support/queries/base.rb +1 -1
- data/lib/choron_support/scope_query.rb +3 -3
- data/lib/choron_support/set_mask_for.rb +5 -5
- data/lib/choron_support/version.rb +1 -1
- data/lib/choron_support.rb +7 -1
- metadata +15 -12
@@ -1,381 +1,218 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
# include ChoronSupport::Props::Attributes
|
7
|
-
# attributes :amount, :amount_with_unit, to: :self
|
8
|
-
# def initialize(amount)
|
9
|
-
# @amount = amount.to_i
|
10
|
-
# end
|
11
|
-
# def amount
|
12
|
-
# @amount
|
13
|
-
# end
|
14
|
-
# def amount_with_unit
|
15
|
-
# "#{amount}円"
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
# Choronではデフォルトで以下のようなBaseクラスが作成されて、読み込みがされています
|
19
|
-
# @example
|
20
|
-
# class Props::Base < ChoronSupport::Props::Base
|
21
|
-
# include ChoronSupport::Props::Attributes
|
22
|
-
# end
|
23
|
-
# [使い方]
|
24
|
-
# @example 最も簡単な例
|
25
|
-
# [app/models/props/user.rb]
|
26
|
-
# class Props::User < Props::Base
|
27
|
-
# # id, full_name, ageを出力させる
|
28
|
-
# # retult: { id: 1, fullName: "John Smith", age: 20 }
|
29
|
-
# attributes :id, :full_name, :age
|
30
|
-
# end
|
31
|
-
# @example メソッドのデリゲート先を指定する
|
32
|
-
# [app/models/props/user.rb]
|
33
|
-
# class Props::User < Props::Base
|
34
|
-
# # result: { fullName: "John Smith" }
|
35
|
-
# attributes :full_name, to: :self
|
36
|
-
# def full_name
|
37
|
-
# "#{model.first_name} #{model.last_name}"
|
38
|
-
# end
|
39
|
-
# end
|
40
|
-
# @example 関連先のModelのPropsを結合する
|
41
|
-
# class Props::User < Props::Base
|
42
|
-
# # result: { posts: posts.as_props } => { posts: [{ id: 1, title: "foo" }, { id: 2, title: "bar" }] }
|
43
|
-
# relation :posts
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# これらの各種DSLは複数同時に設定することもできます
|
47
|
-
# @example 複数設定
|
48
|
-
# [app/models/props/user.rb]
|
49
|
-
# class Props::User < Props::Base
|
50
|
-
# # id, full_name, ageを出力させる
|
51
|
-
# attributes :id, :age
|
52
|
-
# attributes :full_name, to: :self
|
53
|
-
# relation :posts
|
54
|
-
# def full_name
|
55
|
-
# "#{model.first_name} #{model.last_name}"
|
56
|
-
# end
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# default値の設定やifオプションを渡して出力有無を動的に変更もできます
|
60
|
-
# @example default, ifの設定
|
61
|
-
# [app/models/props/user.rb]
|
62
|
-
# class Props::User < Props::Base
|
63
|
-
# # age が nil のときは 0 を出力する
|
64
|
-
# # age が 20 以上のときのみ出力する
|
65
|
-
# attributes :age, default: 0, if: :show_age?
|
66
|
-
# def show_age?
|
67
|
-
# model.age >= 20
|
68
|
-
# end
|
69
|
-
# end
|
70
|
-
#
|
71
|
-
#
|
72
|
-
# 本DSLを利用するときは基本的には attributes を使って設定するのが良いと思います
|
73
|
-
# 細かな使い方モジュールの該当DSL(self.xxxx)の説明を参照してください
|
74
|
-
module ChoronSupport
|
75
|
-
module Props
|
76
|
-
module Attributes
|
77
|
-
FORMATS = {
|
78
|
-
# HTMLのinput type="date"で使える形式
|
79
|
-
date: "%Y-%m-%d",
|
80
|
-
datetime: "%Y-%m-%dT%H:%M",
|
81
|
-
}.freeze
|
82
|
-
# 型のキャスト指定があってもキャストはしないメソッド
|
83
|
-
CAST_IGNORE_METHODS = [
|
84
|
-
# id は数値のほうが良いため
|
85
|
-
:id,
|
86
|
-
].freeze
|
87
|
-
# デフォルト値を設定しない場合に使う値
|
88
|
-
NO_DEFAULT = Object.new.freeze
|
1
|
+
require_relative "./private/setting"
|
2
|
+
module ChoronSupport::Props::Attributes
|
3
|
+
unless defined?(ActiveSupport)
|
4
|
+
raise "ActiveSupport is not defined. Please require 'active_support/all' in your Gemfile"
|
5
|
+
end
|
89
6
|
|
90
|
-
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
# DSLで設定できる設定値たち ==========================
|
11
|
+
# Props作成時に設定されるキーと値を設定します。
|
12
|
+
# この値はDSLを経由して内部的に設定されていきます
|
13
|
+
class_attribute :settings, instance_writer: false, default: nil
|
14
|
+
# Props作成時に自動で付与される元のクラスの文字列を設定しないときはtrueを設定してください
|
15
|
+
# @example
|
16
|
+
# class Props::Foos::Bar
|
17
|
+
# self.skip_meta_mark = true
|
18
|
+
# end
|
19
|
+
class_attribute :skip_meta_mark, default: false
|
20
|
+
# 他のPropsクラスの設定を継承するときに設定されます。設定できるのは1つだけです
|
21
|
+
class_attribute :inherit_props_class, default: nil
|
22
|
+
# ====================================================
|
23
|
+
|
24
|
+
# Propsとして出力する属性を設定するためのDSLです
|
25
|
+
# @param [Symbol] method モデル, もしくは to オプションで設定したオブジェクトに対して実行するメソッドを指定してください
|
26
|
+
# @param [Keyword] options その他のオプションを指定してください
|
27
|
+
# @option [Symbol] :to 指定したメソッドを実行するオブジェクトを指定できます
|
28
|
+
# @option [Symbol] :name Props化するときに出力する属性(Key)名を指定できます
|
29
|
+
# @option [Symbol | lambda] :if 属性を出力するための条件を指定できます
|
30
|
+
# @option [Symbol] :cast 属性を出力する前に指定したメソッドを実行できます。
|
31
|
+
# @option [Boolean] :default 属性値がnilのときに代わりに出力する値を指定できます
|
32
|
+
# @option [Proc] &block ブロックを渡すとそのブロックの戻り値を属性値として出力します
|
33
|
+
def self.attribute(method, **options, &block)
|
34
|
+
setting_params = options.merge(method:, block:)
|
35
|
+
setting = ChoronSupport::Props::Private::Setting.new(setting_params)
|
36
|
+
|
37
|
+
self.settings ||= []
|
38
|
+
self.settings << setting
|
39
|
+
end
|
91
40
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
41
|
+
# 他のPropsクラスの設定を継承するためのDSLです
|
42
|
+
# @param [ChoronSupport::Props::Base] inherit_props_class 継承するPropsクラスを指定してください
|
43
|
+
# @example
|
44
|
+
# class Props::Users::General < ChoronSupport::Props::Base
|
45
|
+
# inherit Props::Users::Base
|
46
|
+
# end
|
47
|
+
def self.inherit(props_class)
|
48
|
+
# 継承するクラスはProps::Baseを継承している必要があります
|
49
|
+
unless props_class.method_defined?(:as_props)
|
50
|
+
raise "inherit class must be respond to :as_props. #{props_class} is not respond to :as_props"
|
51
|
+
end
|
97
52
|
|
98
|
-
|
99
|
-
|
100
|
-
#
|
101
|
-
|
102
|
-
# Props作成時に自動で付与される元のクラスの文字列を設定しないときはtrueを設定してください
|
103
|
-
# @example
|
104
|
-
# class Props::Foo < Props::Base
|
105
|
-
# self.skip_meta_mark = true
|
106
|
-
# end
|
107
|
-
class_attribute :skip_meta_mark, default: false
|
108
|
-
# 他のPropsクラスの結果を結合するときに結合先のProps識別子を設定してください
|
109
|
-
# @example
|
110
|
-
# class Props::Foos::General < Props::Base
|
111
|
-
# # すべてのカラムを出す
|
112
|
-
# self.union = :model
|
113
|
-
# # as_props の結果を結合する
|
114
|
-
# self.union = :default
|
115
|
-
# # as_props(:secure) の結果を結合する
|
116
|
-
# self.union = :secure
|
117
|
-
# end
|
118
|
-
class_attribute :union, default: nil
|
119
|
-
# ====================================================
|
53
|
+
# 既に継承先が設定されている場合はエラーにします
|
54
|
+
if inherit_props_class.present?
|
55
|
+
raise "inherit props inherit class already set: #{inherit_props_class}.(Only one class can be inherited)"
|
56
|
+
end
|
120
57
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
# @param [Proc | Symbol] if その値を出すときの条件。Symbolだとselfに対してsendを実行します
|
128
|
-
def self.attribute(key, method: nil, to: :model, cast: nil, default: NO_DEFAULT, if: nil)
|
129
|
-
self.settings_attributes ||= []
|
130
|
-
self.settings_attributes << { key:, to:, method: (method || key), cast:, default:, if: }
|
131
|
-
end
|
58
|
+
self.inherit_props_class = props_class
|
59
|
+
self.settings ||= []
|
60
|
+
inherit_props_class.settings.to_a.each do |setting|
|
61
|
+
self.settings << setting
|
62
|
+
end
|
63
|
+
end
|
132
64
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
65
|
+
# Modelに対して関連付けされた別ModelのPropsを結合するためのDSLです
|
66
|
+
# @param [Symbol] method to オプションで指定されたオブジェクトに実行されるメソッドを指定してください
|
67
|
+
# @param [ChoronSupport::Props::Base | Symbol] props_class モデルをProps化するためのクラス もしくはそれを示す Symbol を指定してください
|
68
|
+
# @param [Array<Symbol>] only 指定した属性のみを出力します
|
69
|
+
# @param [Array<Symbol>] except 指定した属性を除外して出力します
|
70
|
+
# @param [Symbol] sti 継承元のクラスのPropsを利用したいときにtrueを指定してください
|
71
|
+
# @param [Keyword] options その他のオプションを指定してください。詳細は attribute と同じです
|
72
|
+
# @example
|
73
|
+
# class Props::Users::General < ChoronSupport::Props::Base
|
74
|
+
# relation :posts, :general, only: %i[id title]
|
75
|
+
# #=> { posts: user.posts.as_props(:general, only: %i[id title]) } と同じ結果になる
|
76
|
+
# end
|
77
|
+
def self.relation(method, props_class, only: nil, except: nil, sti: false, **options)
|
78
|
+
attribute(method, **options) do |model, params|
|
79
|
+
records = model.send(method)
|
80
|
+
# only等の設定はrelationで設定したものを適用する
|
81
|
+
params.merge!(only:, except:, sti:)
|
82
|
+
records&.as_props(props_class, **params)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
149
86
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
# class Props::User < ChoronSupport::Props::Base
|
156
|
-
# relation :posts
|
157
|
-
# #=> { posts: user.posts.as_props } と同じ結果になる
|
158
|
-
# relation :posts, props: :foo_bar
|
159
|
-
# #=> { posts: user.posts.as_props(:foo_bar) } と同じ結果になる
|
160
|
-
# relation :user_posts, relation: :posts
|
161
|
-
# #=> { user_posts: user.posts.as_props } と同じ結果になる
|
162
|
-
# end
|
163
|
-
def self.relation(key, relation: nil, to: :model, cast: nil, default: NO_DEFAULT, props: nil, if: nil)
|
164
|
-
relation ||= key
|
165
|
-
method = lambda { |model|
|
166
|
-
records = model.send(relation)
|
167
|
-
if props
|
168
|
-
records&.as_props(props) || {}
|
169
|
-
else
|
170
|
-
records&.as_props || {}
|
171
|
-
end
|
172
|
-
}
|
173
|
-
self.attribute(
|
174
|
-
key,
|
175
|
-
method:,
|
176
|
-
to:,
|
177
|
-
cast:,
|
178
|
-
default:,
|
179
|
-
if:,
|
180
|
-
)
|
181
|
-
end
|
87
|
+
# @return [Hash] props
|
88
|
+
def as_props
|
89
|
+
_props = {}
|
90
|
+
only_params = params[:only].to_a.map(&:to_sym)
|
91
|
+
except_params = params[:except].to_a.map(&:to_sym)
|
182
92
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
# end
|
190
|
-
def self.relations(*keys, to: :model, cast: nil, default: NO_DEFAULT, props: nil, if: nil)
|
191
|
-
keys.each do |key|
|
192
|
-
method = lambda { |model|
|
193
|
-
records = model.send(key)
|
194
|
-
if props
|
195
|
-
records&.as_props(props) || {}
|
196
|
-
else
|
197
|
-
records&.as_props || {}
|
198
|
-
end
|
199
|
-
}
|
200
|
-
self.attribute(
|
201
|
-
key,
|
202
|
-
method:,
|
203
|
-
to:,
|
204
|
-
cast:,
|
205
|
-
default:,
|
206
|
-
if:,
|
207
|
-
)
|
208
|
-
end
|
209
|
-
end
|
93
|
+
# DSLの設定を設定する
|
94
|
+
self.class.settings.to_a.each do |setting|
|
95
|
+
# 除外設定がある場合はスキップ
|
96
|
+
next if except_params.include?(setting.method.to_sym)
|
97
|
+
# only設定がある場合はそれ以外をスキップ
|
98
|
+
next if only_params.present? && only_params.exclude?(setting.method.to_sym)
|
210
99
|
|
211
|
-
|
212
|
-
|
213
|
-
# @return [Hash] 設定されるPropsのキーと値のペア
|
214
|
-
# @note memo
|
215
|
-
# if が予約語のため options として受け取っています。_ifも検討しましたが全体でキーワードの形を合わせたかったためoptionsの形にしています
|
216
|
-
def attribute(key, method: nil, to: :model, cast: nil, default: NO_DEFAULT, **options)
|
217
|
-
__build_props_attribute__(key, (method || key), to, cast, default, **options)
|
218
|
-
end
|
100
|
+
_props.merge!(__build_props_attribute__(setting))
|
101
|
+
end
|
219
102
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
methods.each do |method|
|
225
|
-
key = method.to_sym
|
226
|
-
unit_props = __build_props_attribute__(key, method, to, cast, default, **options)
|
103
|
+
# Classのマークをつける(テスト用)
|
104
|
+
_props.merge!(__build_props_class_mark__)
|
105
|
+
# Modelのマークをつける
|
106
|
+
_props.merge!(__build_props_meta_mark__)
|
227
107
|
|
228
|
-
|
229
|
-
|
108
|
+
_props
|
109
|
+
end
|
230
110
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
111
|
+
private
|
112
|
+
|
113
|
+
def model
|
114
|
+
raise NotImplementedError, "model method is not implemented. Please implement model method in your class"
|
115
|
+
end
|
235
116
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
_props.merge!(__build_props_meta_mark__)
|
117
|
+
def params
|
118
|
+
{}
|
119
|
+
end
|
240
120
|
|
241
|
-
|
242
|
-
|
121
|
+
FORMATS = {
|
122
|
+
# HTMLのinput type="date"で使える形式
|
123
|
+
date: "%Y-%m-%d",
|
124
|
+
datetime: "%Y-%m-%dT%H:%M"
|
125
|
+
}.freeze
|
126
|
+
# 型のキャスト指定があってもキャストはしないメソッド
|
127
|
+
CAST_IGNORE_METHODS = [
|
128
|
+
# id は数値のほうが良いため
|
129
|
+
:id
|
130
|
+
].freeze
|
131
|
+
# @param [Array<Symbol>] Setting
|
132
|
+
def __build_props_attribute__(setting)
|
133
|
+
attribute = {}
|
134
|
+
|
135
|
+
_if = setting.if
|
136
|
+
if _if.present?
|
137
|
+
result = send(_if)
|
138
|
+
return {} unless result
|
139
|
+
end
|
243
140
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
# もし両方を設定しているときはどちらの値も設定されます
|
251
|
-
# キーがかぶっているときはprops側が優先されます
|
252
|
-
# @return [Hash] props
|
253
|
-
def as_props
|
254
|
-
_props = {}
|
141
|
+
# javascriptは?をキーとして使えないので削除しつつ、isXxx形式に変換する
|
142
|
+
key = setting.name
|
143
|
+
if key.to_s.end_with?("?")
|
144
|
+
key = key.to_s.gsub("?", "").to_sym
|
145
|
+
key = "is_#{key}".to_sym unless key.start_with?("is_")
|
146
|
+
end
|
255
147
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
148
|
+
# javascriptは!をキーとして使えないので削除する
|
149
|
+
key = key.to_s.gsub("!", "").to_sym if key.to_s.end_with?("!")
|
150
|
+
|
151
|
+
method = setting.method
|
152
|
+
to = setting.to
|
153
|
+
# valはこの後の工程で書き換えの可能性があるため注意
|
154
|
+
val = if setting.block.present?
|
155
|
+
setting.block.call(model, params)
|
156
|
+
elsif to == :self
|
157
|
+
if method.is_a?(Proc)
|
158
|
+
method.call(self)
|
260
159
|
else
|
261
|
-
|
160
|
+
send(method)
|
262
161
|
end
|
263
|
-
|
264
|
-
|
265
|
-
# DSLの設定があればそれを設定する
|
266
|
-
self.class.settings_attributes.to_a.each do |settings|
|
267
|
-
_props.merge!(
|
268
|
-
attribute(settings[:key], method: settings[:method], to: settings[:to], cast: settings[:cast], default: settings[:default], if: settings[:if])
|
269
|
-
)
|
270
|
-
end
|
271
|
-
|
272
|
-
# Classのマークをつける(テスト用)
|
273
|
-
_props.merge!(__build_props_class_mark__)
|
274
|
-
# Modelのマークをつける
|
275
|
-
_props.merge!(__build_props_meta_mark__)
|
276
|
-
# Propsがオーバーライドされていればその値で上書きする
|
277
|
-
_props.merge!(self.props)
|
278
|
-
|
279
|
-
_props
|
280
|
-
end
|
281
|
-
|
282
|
-
# @return [Hash] props
|
283
|
-
# @note
|
284
|
-
# オーバーライドして使うことを想定しています
|
285
|
-
def props
|
286
|
-
{}
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
private
|
291
|
-
|
292
|
-
# @param [Array<Symbol>] methods
|
293
|
-
# @param [Symbol] key
|
294
|
-
# @param [Symbol] to メソッドのデリゲート先
|
295
|
-
# @param [Block] blockを渡すと実行結果をブロック引数でわたし、その中の戻り値を結果として返します
|
296
|
-
# @param [Symbol] cast デリゲート先のメソッドの戻り値に対して、さらにメソッドを実行する
|
297
|
-
# 複雑性を増す代わりに集約をさせています
|
298
|
-
def __build_props_attribute__(key, method, to, cast, default, **options)
|
299
|
-
props = {}
|
300
|
-
|
301
|
-
_if = options[:if]
|
302
|
-
if _if.present?
|
303
|
-
result = _if.is_a?(Proc) ? _if.call(model) : send(_if)
|
304
|
-
return {} unless result
|
305
|
-
end
|
306
|
-
|
307
|
-
# javascriptは?をキーとして使えないので削除しつつ、isXxx形式に変換する
|
308
|
-
if key.to_s.end_with?("?")
|
309
|
-
key = key.to_s.gsub("?", "").to_sym
|
310
|
-
key = "is_#{key}".to_sym unless key.start_with?("is_")
|
311
|
-
end
|
312
|
-
|
313
|
-
# valはこの後の工程で書き換えの可能性があるため注意
|
314
|
-
if to == :self
|
315
|
-
if method.is_a?(Proc)
|
316
|
-
val = method.call(self)
|
317
|
-
else
|
318
|
-
val = send(method)
|
319
|
-
end
|
320
|
-
else
|
321
|
-
if method.is_a?(Proc)
|
322
|
-
val = method.call(send(to))
|
162
|
+
elsif method.is_a?(Proc)
|
163
|
+
method.call(send(to))
|
323
164
|
else
|
324
|
-
|
165
|
+
send(to)&.send(method)
|
325
166
|
end
|
326
|
-
end
|
327
167
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
end
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
if val.nil? && default != NO_DEFAULT
|
343
|
-
val = default
|
168
|
+
case val
|
169
|
+
when Date
|
170
|
+
val = val.strftime(FORMATS[:date])
|
171
|
+
when ActiveSupport::TimeWithZone, Time
|
172
|
+
# 日付系であればjsで使えるようにhtmlに変換する
|
173
|
+
val = val.strftime(FORMATS[:datetime])
|
174
|
+
else
|
175
|
+
if setting.cast.present? && CAST_IGNORE_METHODS.exclude?(key)
|
176
|
+
val = setting.cast.to_s.split(".").inject(val) do |lval, cast_method|
|
177
|
+
lval.send(cast_method)
|
344
178
|
end
|
179
|
+
end
|
180
|
+
end
|
345
181
|
|
346
|
-
|
182
|
+
val = setting.default if val.nil? && setting.set_default?
|
347
183
|
|
348
|
-
|
349
|
-
end
|
184
|
+
attribute[key] = val
|
350
185
|
|
351
|
-
|
352
|
-
|
353
|
-
mark = {}
|
354
|
-
if ENV["RAILS_ENV"] == "test"
|
355
|
-
mark[:props_class_name] = self.class.name
|
356
|
-
if self.class.union.present?
|
357
|
-
mark[:union_type_name] = self.class.union
|
358
|
-
end
|
359
|
-
end
|
186
|
+
attribute
|
187
|
+
end
|
360
188
|
|
361
|
-
|
189
|
+
# テストモードのときはどのPropsを実行したかを判定できるように属性をつけたします
|
190
|
+
def __build_props_class_mark__
|
191
|
+
mark = {}
|
192
|
+
if ENV["RAILS_ENV"] == "test"
|
193
|
+
mark[:props_class_name] = self.class.name
|
194
|
+
if self.class.inherit_props_class.present?
|
195
|
+
mark[:inherit_props_class_name] =
|
196
|
+
self.class.inherit_props_class.try(:name) || self.class.inherit_props_class.to_s
|
362
197
|
end
|
198
|
+
end
|
363
199
|
|
364
|
-
|
365
|
-
|
366
|
-
return {} if self.class.skip_meta_mark
|
200
|
+
mark
|
201
|
+
end
|
367
202
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
self
|
372
|
-
end
|
203
|
+
# どのモデルのPropsかを判定できるように属性をつけたします
|
204
|
+
def __build_props_meta_mark__
|
205
|
+
return {} if self.class.skip_meta_mark
|
373
206
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
end
|
207
|
+
type_target = begin
|
208
|
+
model
|
209
|
+
rescue StandardError
|
210
|
+
self
|
379
211
|
end
|
212
|
+
|
213
|
+
{
|
214
|
+
type: type_target.class.try(:name).to_s,
|
215
|
+
model_name: type_target.class.try(:name).try(:demodulize).to_s
|
216
|
+
}
|
380
217
|
end
|
381
218
|
end
|
@@ -1,40 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# @example
|
4
|
-
# [app/models/props/base.rb]
|
5
|
-
# class Props::Base < ChoronSupport::Props::Base
|
6
|
-
# include ChoronSupport::Props::Attributes
|
7
|
-
# end
|
8
|
-
# そして各種モデルのPropsは上記のBaseクラスを継承して作成されています
|
9
|
-
# @example
|
10
|
-
# [app/models/props/user.rb]
|
11
|
-
# class Props::User < Props::Base
|
12
|
-
# attributes :id, :name, :age
|
13
|
-
# end
|
14
|
-
# [app/models/props/users/secure.rb]
|
15
|
-
# class Props::Users::Secure < Props::Base
|
16
|
-
# # secure側はageは非表示
|
17
|
-
# attributes :id, :name
|
18
|
-
# end
|
1
|
+
require_relative "./attributes"
|
2
|
+
|
19
3
|
module ChoronSupport
|
20
4
|
module Props
|
21
5
|
class Base
|
6
|
+
include ChoronSupport::Props::Attributes
|
7
|
+
|
22
8
|
# @param [ActiveRecord::Base] model Props対象のモデルのインスタンス
|
23
9
|
# @param [Hash] params その他のパラメータ
|
10
|
+
# @param [Boolean] params params[:only] 指定した属性のみを出力します
|
11
|
+
# @param [Boolean] params params[:except] 指定した属性を出力しません
|
24
12
|
def initialize(model, params = {})
|
25
13
|
@model = model
|
26
|
-
@params = params
|
27
|
-
end
|
28
|
-
|
29
|
-
# 継承先で実装されることを想定しています
|
30
|
-
# ChoronSupport::Props::Attributes を読み込んでいるときは、そちらでオーバーライドされています
|
31
|
-
def as_props
|
32
|
-
raise NotImplementedError
|
14
|
+
@params = params.to_h
|
33
15
|
end
|
34
16
|
|
35
17
|
private
|
36
18
|
|
37
|
-
|
19
|
+
# @override
|
20
|
+
attr_reader :model
|
21
|
+
|
22
|
+
# @override
|
23
|
+
attr_reader :params
|
38
24
|
end
|
39
25
|
end
|
40
26
|
end
|