active_model_serializers 0.8.3 → 0.10.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.
Files changed (232) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +29 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  4. data/.gitignore +17 -0
  5. data/.rubocop.yml +104 -0
  6. data/.rubocop_todo.yml +167 -0
  7. data/.simplecov +110 -0
  8. data/.travis.yml +39 -24
  9. data/CHANGELOG.md +465 -6
  10. data/CONTRIBUTING.md +105 -0
  11. data/Gemfile +50 -1
  12. data/{MIT-LICENSE.txt → MIT-LICENSE} +3 -2
  13. data/README.md +102 -590
  14. data/Rakefile +93 -8
  15. data/active_model_serializers.gemspec +65 -23
  16. data/appveyor.yml +24 -0
  17. data/bin/bench +171 -0
  18. data/bin/bench_regression +316 -0
  19. data/bin/serve_benchmark +39 -0
  20. data/docs/ARCHITECTURE.md +126 -0
  21. data/docs/README.md +40 -0
  22. data/docs/STYLE.md +58 -0
  23. data/docs/general/adapters.md +245 -0
  24. data/docs/general/caching.md +52 -0
  25. data/docs/general/configuration_options.md +100 -0
  26. data/docs/general/deserialization.md +100 -0
  27. data/docs/general/getting_started.md +133 -0
  28. data/docs/general/instrumentation.md +40 -0
  29. data/docs/general/key_transforms.md +40 -0
  30. data/docs/general/logging.md +14 -0
  31. data/docs/general/rendering.md +255 -0
  32. data/docs/general/serializers.md +372 -0
  33. data/docs/how-open-source-maintained.jpg +0 -0
  34. data/docs/howto/add_pagination_links.md +139 -0
  35. data/docs/howto/add_root_key.md +51 -0
  36. data/docs/howto/outside_controller_use.md +58 -0
  37. data/docs/howto/passing_arbitrary_options.md +27 -0
  38. data/docs/howto/serialize_poro.md +32 -0
  39. data/docs/howto/test.md +152 -0
  40. data/docs/integrations/ember-and-json-api.md +112 -0
  41. data/docs/integrations/grape.md +19 -0
  42. data/docs/jsonapi/errors.md +56 -0
  43. data/docs/jsonapi/schema/schema.json +366 -0
  44. data/docs/jsonapi/schema.md +151 -0
  45. data/docs/rfcs/0000-namespace.md +106 -0
  46. data/docs/rfcs/template.md +15 -0
  47. data/lib/action_controller/serialization.rb +31 -36
  48. data/lib/active_model/serializable_resource.rb +11 -0
  49. data/lib/active_model/serializer/adapter/attributes.rb +15 -0
  50. data/lib/active_model/serializer/adapter/base.rb +16 -0
  51. data/lib/active_model/serializer/adapter/json.rb +15 -0
  52. data/lib/active_model/serializer/adapter/json_api.rb +15 -0
  53. data/lib/active_model/serializer/adapter/null.rb +15 -0
  54. data/lib/active_model/serializer/adapter.rb +24 -0
  55. data/lib/active_model/serializer/array_serializer.rb +9 -0
  56. data/lib/active_model/serializer/association.rb +19 -0
  57. data/lib/active_model/serializer/associations.rb +87 -220
  58. data/lib/active_model/serializer/attribute.rb +25 -0
  59. data/lib/active_model/serializer/attributes.rb +82 -0
  60. data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
  61. data/lib/active_model/serializer/caching.rb +333 -0
  62. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  63. data/lib/active_model/serializer/collection_serializer.rb +64 -0
  64. data/lib/active_model/serializer/configuration.rb +35 -0
  65. data/lib/active_model/serializer/error_serializer.rb +10 -0
  66. data/lib/active_model/serializer/errors_serializer.rb +27 -0
  67. data/lib/active_model/serializer/field.rb +90 -0
  68. data/lib/active_model/serializer/fieldset.rb +31 -0
  69. data/lib/active_model/serializer/has_many_reflection.rb +10 -0
  70. data/lib/active_model/serializer/has_one_reflection.rb +10 -0
  71. data/lib/active_model/serializer/include_tree.rb +111 -0
  72. data/lib/active_model/serializer/links.rb +35 -0
  73. data/lib/active_model/serializer/lint.rb +146 -0
  74. data/lib/active_model/serializer/meta.rb +29 -0
  75. data/lib/active_model/serializer/null.rb +17 -0
  76. data/lib/active_model/serializer/reflection.rb +147 -0
  77. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  78. data/lib/active_model/serializer/type.rb +25 -0
  79. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  80. data/lib/active_model/serializer.rb +158 -481
  81. data/lib/active_model_serializers/adapter/attributes.rb +76 -0
  82. data/lib/active_model_serializers/adapter/base.rb +83 -0
  83. data/lib/active_model_serializers/adapter/json.rb +21 -0
  84. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +213 -0
  85. data/lib/active_model_serializers/adapter/json_api/error.rb +96 -0
  86. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +49 -0
  87. data/lib/active_model_serializers/adapter/json_api/link.rb +83 -0
  88. data/lib/active_model_serializers/adapter/json_api/meta.rb +37 -0
  89. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +62 -0
  90. data/lib/active_model_serializers/adapter/json_api/relationship.rb +52 -0
  91. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +37 -0
  92. data/lib/active_model_serializers/adapter/json_api.rb +516 -0
  93. data/lib/active_model_serializers/adapter/null.rb +9 -0
  94. data/lib/active_model_serializers/adapter.rb +92 -0
  95. data/lib/active_model_serializers/callbacks.rb +55 -0
  96. data/lib/active_model_serializers/deprecate.rb +55 -0
  97. data/lib/active_model_serializers/deserialization.rb +13 -0
  98. data/lib/active_model_serializers/json_pointer.rb +14 -0
  99. data/lib/active_model_serializers/key_transform.rb +70 -0
  100. data/lib/active_model_serializers/logging.rb +122 -0
  101. data/lib/active_model_serializers/model.rb +49 -0
  102. data/lib/active_model_serializers/railtie.rb +46 -0
  103. data/lib/active_model_serializers/register_jsonapi_renderer.rb +65 -0
  104. data/lib/active_model_serializers/serializable_resource.rb +81 -0
  105. data/lib/active_model_serializers/serialization_context.rb +32 -0
  106. data/lib/active_model_serializers/test/schema.rb +138 -0
  107. data/lib/active_model_serializers/test/serializer.rb +125 -0
  108. data/lib/active_model_serializers/test.rb +7 -0
  109. data/lib/active_model_serializers.rb +32 -89
  110. data/lib/generators/rails/USAGE +6 -0
  111. data/lib/generators/rails/resource_override.rb +10 -0
  112. data/lib/generators/rails/serializer_generator.rb +36 -0
  113. data/lib/generators/rails/templates/serializer.rb.erb +8 -0
  114. data/lib/grape/active_model_serializers.rb +14 -0
  115. data/lib/grape/formatters/active_model_serializers.rb +15 -0
  116. data/lib/grape/helpers/active_model_serializers.rb +16 -0
  117. data/test/action_controller/adapter_selector_test.rb +53 -0
  118. data/test/action_controller/explicit_serializer_test.rb +134 -0
  119. data/test/action_controller/json/include_test.rb +167 -0
  120. data/test/action_controller/json_api/deserialization_test.rb +112 -0
  121. data/test/action_controller/json_api/errors_test.rb +41 -0
  122. data/test/action_controller/json_api/linked_test.rb +197 -0
  123. data/test/action_controller/json_api/pagination_test.rb +116 -0
  124. data/test/action_controller/json_api/transform_test.rb +181 -0
  125. data/test/action_controller/serialization_scope_name_test.rb +229 -0
  126. data/test/action_controller/serialization_test.rb +469 -0
  127. data/test/active_model_serializers/adapter_for_test.rb +208 -0
  128. data/test/active_model_serializers/json_pointer_test.rb +20 -0
  129. data/test/active_model_serializers/key_transform_test.rb +263 -0
  130. data/test/active_model_serializers/logging_test.rb +77 -0
  131. data/test/active_model_serializers/model_test.rb +9 -0
  132. data/test/active_model_serializers/railtie_test_isolated.rb +63 -0
  133. data/test/active_model_serializers/serialization_context_test_isolated.rb +58 -0
  134. data/test/active_model_serializers/test/schema_test.rb +130 -0
  135. data/test/active_model_serializers/test/serializer_test.rb +62 -0
  136. data/test/active_record_test.rb +9 -0
  137. data/test/adapter/deprecation_test.rb +100 -0
  138. data/test/adapter/json/belongs_to_test.rb +45 -0
  139. data/test/adapter/json/collection_test.rb +90 -0
  140. data/test/adapter/json/has_many_test.rb +45 -0
  141. data/test/adapter/json/transform_test.rb +93 -0
  142. data/test/adapter/json_api/belongs_to_test.rb +155 -0
  143. data/test/adapter/json_api/collection_test.rb +95 -0
  144. data/test/adapter/json_api/errors_test.rb +78 -0
  145. data/test/adapter/json_api/fields_test.rb +87 -0
  146. data/test/adapter/json_api/has_many_embed_ids_test.rb +43 -0
  147. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +96 -0
  148. data/test/adapter/json_api/has_many_test.rb +144 -0
  149. data/test/adapter/json_api/has_one_test.rb +80 -0
  150. data/test/adapter/json_api/json_api_test.rb +35 -0
  151. data/test/adapter/json_api/linked_test.rb +392 -0
  152. data/test/adapter/json_api/links_test.rb +93 -0
  153. data/test/adapter/json_api/pagination_links_test.rb +166 -0
  154. data/test/adapter/json_api/parse_test.rb +137 -0
  155. data/test/adapter/json_api/relationship_test.rb +161 -0
  156. data/test/adapter/json_api/relationships_test.rb +199 -0
  157. data/test/adapter/json_api/resource_identifier_test.rb +85 -0
  158. data/test/adapter/json_api/resource_meta_test.rb +100 -0
  159. data/test/adapter/json_api/toplevel_jsonapi_test.rb +82 -0
  160. data/test/adapter/json_api/transform_test.rb +502 -0
  161. data/test/adapter/json_api/type_test.rb +61 -0
  162. data/test/adapter/json_test.rb +45 -0
  163. data/test/adapter/null_test.rb +23 -0
  164. data/test/adapter/polymorphic_test.rb +171 -0
  165. data/test/adapter_test.rb +67 -0
  166. data/test/array_serializer_test.rb +20 -73
  167. data/test/benchmark/app.rb +65 -0
  168. data/test/benchmark/benchmarking_support.rb +67 -0
  169. data/test/benchmark/bm_caching.rb +119 -0
  170. data/test/benchmark/bm_transform.rb +34 -0
  171. data/test/benchmark/config.ru +3 -0
  172. data/test/benchmark/controllers.rb +84 -0
  173. data/test/benchmark/fixtures.rb +219 -0
  174. data/test/cache_test.rb +485 -0
  175. data/test/collection_serializer_test.rb +110 -0
  176. data/test/fixtures/active_record.rb +78 -0
  177. data/test/fixtures/poro.rb +282 -0
  178. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  179. data/test/generators/serializer_generator_test.rb +57 -0
  180. data/test/grape_test.rb +82 -0
  181. data/test/include_tree/from_include_args_test.rb +26 -0
  182. data/test/include_tree/from_string_test.rb +94 -0
  183. data/test/include_tree/include_args_to_hash_test.rb +64 -0
  184. data/test/lint_test.rb +49 -0
  185. data/test/logger_test.rb +18 -0
  186. data/test/poro_test.rb +9 -0
  187. data/test/serializable_resource_test.rb +83 -0
  188. data/test/serializers/association_macros_test.rb +36 -0
  189. data/test/serializers/associations_test.rb +295 -0
  190. data/test/serializers/attribute_test.rb +151 -0
  191. data/test/serializers/attributes_test.rb +52 -0
  192. data/test/serializers/caching_configuration_test_isolated.rb +170 -0
  193. data/test/serializers/configuration_test.rb +32 -0
  194. data/test/serializers/fieldset_test.rb +14 -0
  195. data/test/serializers/meta_test.rb +196 -0
  196. data/test/serializers/options_test.rb +21 -0
  197. data/test/serializers/read_attribute_for_serialization_test.rb +79 -0
  198. data/test/serializers/root_test.rb +21 -0
  199. data/test/serializers/serialization_test.rb +55 -0
  200. data/test/serializers/serializer_for_test.rb +134 -0
  201. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  202. data/test/support/isolated_unit.rb +79 -0
  203. data/test/support/rails5_shims.rb +47 -0
  204. data/test/support/rails_app.rb +45 -0
  205. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  206. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  207. data/test/support/schemas/custom/show.json +7 -0
  208. data/test/support/schemas/hyper_schema.json +93 -0
  209. data/test/support/schemas/render_using_json_api.json +43 -0
  210. data/test/support/schemas/simple_json_pointers.json +10 -0
  211. data/test/support/serialization_testing.rb +53 -0
  212. data/test/test_helper.rb +48 -23
  213. metadata +449 -43
  214. data/DESIGN.textile +0 -586
  215. data/Gemfile.edge +0 -9
  216. data/bench/perf.rb +0 -43
  217. data/cruft.md +0 -19
  218. data/lib/active_model/array_serializer.rb +0 -104
  219. data/lib/active_record/serializer_override.rb +0 -16
  220. data/lib/generators/resource_override.rb +0 -13
  221. data/lib/generators/serializer/USAGE +0 -9
  222. data/lib/generators/serializer/serializer_generator.rb +0 -42
  223. data/lib/generators/serializer/templates/serializer.rb +0 -19
  224. data/test/association_test.rb +0 -592
  225. data/test/caching_test.rb +0 -96
  226. data/test/generators_test.rb +0 -85
  227. data/test/no_serialization_scope_test.rb +0 -34
  228. data/test/serialization_scope_name_test.rb +0 -67
  229. data/test/serialization_test.rb +0 -392
  230. data/test/serializer_support_test.rb +0 -51
  231. data/test/serializer_test.rb +0 -1465
  232. data/test/test_fakes.rb +0 -217
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env ruby
2
+ require 'fileutils'
3
+ require 'pathname'
4
+ require 'shellwords'
5
+ require 'English'
6
+
7
+ ############################
8
+ # USAGE
9
+ #
10
+ # bundle exec bin/bench_regression <ref1> <ref2>
11
+ # <ref1> defaults to the current branch
12
+ # <ref2> defaults to the master branch
13
+ # bundle exec bin/bench_regression current # will run on the current branch
14
+ # bundle exec bin/bench_regression revisions 792fb8a90 master # every revision inclusive
15
+ # bundle exec bin/bench_regression 792fb8a90 master --repeat-count 2 --env CACHE_ON=off
16
+ # bundle exec bin/bench_regression vendor
17
+ ###########################
18
+
19
+ class BenchRegression
20
+ ROOT = Pathname File.expand_path(File.join(*['..', '..']), __FILE__)
21
+ TMP_DIR_NAME = File.join('tmp', 'bench')
22
+ TMP_DIR = File.join(ROOT, TMP_DIR_NAME)
23
+ E_TMP_DIR = Shellwords.shellescape(TMP_DIR)
24
+ load ROOT.join('bin', 'bench')
25
+
26
+ attr_reader :source_stasher
27
+
28
+ def initialize
29
+ @source_stasher = SourceStasher.new
30
+ end
31
+
32
+ class SourceStasher
33
+ attr_reader :gem_require_paths, :gem_paths
34
+ attr_writer :vendor
35
+
36
+ def initialize
37
+ @gem_require_paths = []
38
+ @gem_paths = []
39
+ refresh_temp_dir
40
+ @vendor = false
41
+ end
42
+
43
+ def temp_dir_empty?
44
+ File.directory?(TMP_DIR) &&
45
+ Dir[File.join(TMP_DIR, '*')].none?
46
+ end
47
+
48
+ def empty_temp_dir
49
+ return if @vendor
50
+ return if temp_dir_empty?
51
+ FileUtils.mkdir_p(TMP_DIR)
52
+ Dir[File.join(TMP_DIR, '*')].each do |file|
53
+ if File.directory?(file)
54
+ FileUtils.rm_rf(file)
55
+ else
56
+ FileUtils.rm(file)
57
+ end
58
+ end
59
+ end
60
+
61
+ def fill_temp_dir
62
+ vendor_files(Dir[File.join(ROOT, 'test', 'benchmark', '*.{rb,ru}')])
63
+ # vendor_file(File.join('bin', 'bench'))
64
+ housekeeping { empty_temp_dir }
65
+ vendor_gem('benchmark-ips')
66
+ end
67
+
68
+ def vendor_files(files)
69
+ files.each do |file|
70
+ vendor_file(file)
71
+ end
72
+ end
73
+
74
+ def vendor_file(file)
75
+ FileUtils.cp(file, File.join(TMP_DIR, File.basename(file)))
76
+ end
77
+
78
+ def vendor_gem(gem_name)
79
+ directory_name = `bundle exec gem unpack benchmark-ips --target=#{E_TMP_DIR}`[/benchmark-ips.+\d/]
80
+ gem_paths << File.join(TMP_DIR, directory_name)
81
+ gem_require_paths << File.join(TMP_DIR_NAME, directory_name, 'lib')
82
+ housekeeping { remove_vendored_gems }
83
+ end
84
+
85
+ def remove_vendored_gems
86
+ return if @vendor
87
+ FileUtils.rm_rf(*gem_paths)
88
+ end
89
+
90
+ def refresh_temp_dir
91
+ empty_temp_dir
92
+ fill_temp_dir
93
+ end
94
+
95
+ def housekeeping
96
+ at_exit { yield }
97
+ end
98
+ end
99
+
100
+ module RevisionMethods
101
+ module_function
102
+ def current_branch
103
+ @current_branch ||= `cat .git/HEAD | cut -d/ -f3,4,5`.chomp
104
+ end
105
+
106
+ def current_revision
107
+ `git rev-parse --short HEAD`.chomp
108
+ end
109
+
110
+ def revision_description(rev)
111
+ `git log --oneline -1 #{rev}`.chomp
112
+ end
113
+
114
+ def revisions(start_ref, end_ref)
115
+ cmd = "git rev-list --reverse #{start_ref}..#{end_ref}"
116
+ `#{cmd}`.chomp.split("\n")
117
+ end
118
+
119
+ def checkout_ref(ref)
120
+ `git checkout #{ref}`.chomp
121
+ if $CHILD_STATUS
122
+ STDERR.puts "Checkout failed: #{ref}, #{$CHILD_STATUS.exitstatus}" unless $CHILD_STATUS.success?
123
+ $CHILD_STATUS.success?
124
+ else
125
+ true
126
+ end
127
+ end
128
+
129
+ def clean_head
130
+ system('git reset --hard --quiet')
131
+ end
132
+ end
133
+ module ShellMethods
134
+
135
+ def sh(cmd)
136
+ puts cmd
137
+ # system(cmd)
138
+ run(cmd)
139
+ # env = {}
140
+ # # out = STDOUT
141
+ # pid = spawn(env, cmd)
142
+ # Process.wait(pid)
143
+ # pid = fork do
144
+ # exec cmd
145
+ # end
146
+ # Process.waitpid2(pid)
147
+ # puts $CHILD_STATUS.exitstatus
148
+ end
149
+
150
+ require 'pty'
151
+ # should consider trapping SIGINT in here
152
+ def run(cmd)
153
+ puts cmd
154
+ child_process = ''
155
+ result = ''
156
+ # http://stackoverflow.com/a/1162850
157
+ # stream output of subprocess
158
+ begin
159
+ PTY.spawn(cmd) do |stdin, _stdout, pid|
160
+ begin
161
+ # Do stuff with the output here. Just printing to show it works
162
+ stdin.each do |line|
163
+ print line
164
+ result << line
165
+ end
166
+ child_process = PTY.check(pid)
167
+ rescue Errno::EIO
168
+ puts 'Errno:EIO error, but this probably just means ' \
169
+ 'that the process has finished giving output'
170
+ end
171
+ end
172
+ rescue PTY::ChildExited
173
+ puts 'The child process exited!'
174
+ end
175
+ unless (child_process && child_process.success?)
176
+ exitstatus = child_process.exitstatus
177
+ puts "FAILED: #{child_process.pid} exited with status #{exitstatus.inspect} due to failed command #{cmd}"
178
+ exit exitstatus || 1
179
+ end
180
+ result
181
+ end
182
+
183
+ def bundle(ref)
184
+ system("rm -f Gemfile.lock")
185
+ # This is absolutely critical for bundling to work
186
+ Bundler.with_clean_env do
187
+ system("bundle check ||
188
+ bundle install --local ||
189
+ bundle install ||
190
+ bundle update")
191
+ end
192
+
193
+ # if $CHILD_STATUS
194
+ # STDERR.puts "Bundle failed at: #{ref}, #{$CHILD_STATUS.exitstatus}" unless $CHILD_STATUS.success?
195
+ # $CHILD_STATUS.success?
196
+ # else
197
+ # false
198
+ # end
199
+ end
200
+ end
201
+ include ShellMethods
202
+ include RevisionMethods
203
+
204
+ def benchmark_refs(ref1: nil, ref2: nil, cmd:)
205
+ checking_out = false
206
+ ref0 = current_branch
207
+ ref1 ||= current_branch
208
+ ref2 ||= 'master'
209
+ p [ref0, ref1, ref2, current_revision]
210
+
211
+ run_benchmark_at_ref(cmd, ref1)
212
+ p [ref0, ref1, ref2, current_revision]
213
+ run_benchmark_at_ref(cmd, ref2)
214
+ p [ref0, ref1, ref2, current_revision]
215
+
216
+ checking_out = true
217
+ checkout_ref(ref0)
218
+ rescue Exception # rubocop:disable Lint/RescueException
219
+ STDERR.puts "[ERROR] #{$!.message}"
220
+ checkout_ref(ref0) unless checking_out
221
+ raise
222
+ end
223
+
224
+ def benchmark_revisions(ref1: nil, ref2: nil, cmd:)
225
+ checking_out = false
226
+ ref0 = current_branch
227
+ ref1 ||= current_branch
228
+ ref2 ||= 'master'
229
+
230
+ revisions(ref1, ref2).each do |rev|
231
+ STDERR.puts "Checking out: #{revision_description(rev)}"
232
+
233
+ run_benchmark_at_ref(cmd, rev)
234
+ clean_head
235
+ end
236
+ checking_out = true
237
+ checkout_ref(ref0)
238
+ rescue Exception # rubocop:disable Lint/RescueException
239
+ STDERR.puts "[ERROR]: #{$!.message}"
240
+ checkout_ref(ref0) unless checking_out
241
+ raise
242
+ end
243
+
244
+ def run_benchmark_at_ref(cmd, ref)
245
+ checkout_ref(ref)
246
+ run_benchmark(cmd, ref)
247
+ end
248
+
249
+ def run_benchmark(cmd, ref = nil)
250
+ ref ||= current_revision
251
+ bundle(ref) &&
252
+ benchmark_tests(cmd, ref)
253
+ end
254
+
255
+ def benchmark_tests(cmd, ref)
256
+ base = E_TMP_DIR
257
+ # cmd.sub('bin/bench', 'tmp/revision_runner/bench')
258
+ # bundle = Gem.bin('bunle'
259
+ # Bundler.with_clean_env(&block)
260
+
261
+ # cmd = Shellwords.shelljoin(cmd)
262
+ # cmd = "COMMIT_HASH=#{ref} BASE=#{base} bundle exec ruby -rbenchmark/ips #{cmd}"
263
+ # Add vendoring benchmark/ips to load path
264
+
265
+ # CURRENT THINKING: IMPORTANT
266
+ # Pass into require statement as RUBYOPTS i.e. via env rather than command line argument
267
+ # otherwise, have a 'fast ams benchmarking' module that extends benchmarkings to add the 'ams'
268
+ # method but doesn't depend on benchmark-ips
269
+ options = {
270
+ commit_hash: ref,
271
+ base: base,
272
+ rubyopt: Shellwords.shellescape("-Ilib:#{source_stasher.gem_require_paths.join(':')}")
273
+ }
274
+ BenchmarkDriver.parse_argv_and_run(ARGV.dup, options)
275
+ end
276
+ end
277
+
278
+ if $PROGRAM_NAME == __FILE__
279
+ benchmarking = BenchRegression.new
280
+
281
+ case ARGV[0]
282
+ when 'current'
283
+ # Run current branch only
284
+
285
+ # super simple command line parsing
286
+ args = ARGV.dup
287
+ _ = args.shift # remove 'current' from args
288
+ cmd = args
289
+ benchmarking.run_benchmark(cmd)
290
+ when 'revisions'
291
+ # Runs on every revision
292
+
293
+ # super simple command line parsing
294
+ args = ARGV.dup
295
+ _ = args.shift
296
+ ref1 = args.shift # remove 'revisions' from args
297
+ ref2 = args.shift
298
+ cmd = args
299
+ benchmarking.benchmark_revisions(ref1: ref1, ref2: ref2, cmd: cmd)
300
+ when 'vendor'
301
+ # Just prevents vendored files from being cleaned up
302
+ # at exit. (They are vendored at initialize.)
303
+ benchmarking.source_stasher.vendor = true
304
+ else
305
+ # Default: Compare current_branch to master
306
+ # Optionally: pass in two refs as args to `bin/bench_regression`
307
+ # TODO: Consider checking across more revisions, to automatically find problems.
308
+
309
+ # super simple command line parsing
310
+ args = ARGV.dup
311
+ ref1 = args.shift
312
+ ref2 = args.shift
313
+ cmd = args
314
+ benchmarking.benchmark_refs(ref1: ref1, ref2: ref2, cmd: cmd)
315
+ end
316
+ end
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ case "$1" in
5
+
6
+ start)
7
+ config="${CONFIG_RU:-test/benchmark/config.ru}"
8
+ bundle exec ruby -Ilib -S rackup "$config" --daemonize --pid tmp/benchmark_app.pid --warn --server webrick
9
+ until [ -f 'tmp/benchmark_app.pid' ]; do
10
+ sleep 0.1 # give it time to start.. I don't know a better way
11
+ done
12
+ cat tmp/benchmark_app.pid
13
+ true
14
+ ;;
15
+
16
+ stop)
17
+ if [ -f 'tmp/benchmark_app.pid' ]; then
18
+ kill -TERM $(cat tmp/benchmark_app.pid)
19
+ else
20
+ echo 'No pidfile'
21
+ false
22
+ fi
23
+ ;;
24
+
25
+ status)
26
+ if [ -f 'tmp/benchmark_app.pid' ]; then
27
+ kill -0 $(cat tmp/benchmark_app.pid)
28
+ [ "$?" -eq 0 ]
29
+ else
30
+ echo 'No pidfile'
31
+ false
32
+ fi
33
+ ;;
34
+
35
+ *)
36
+ echo "Usage: $0 [start|stop|status]"
37
+ ;;
38
+
39
+ esac
@@ -0,0 +1,126 @@
1
+ [Back to Guides](README.md)
2
+
3
+ This document focuses on architecture the 0.10.x version of ActiveModelSerializers. If you are interested in the architecture of the 0.8 or 0.9 versions,
4
+ please refer to the [0.8 README](https://github.com/rails-api/active_model_serializers/blob/0-8-stable/README.md) or
5
+ [0.9 README](https://github.com/rails-api/active_model_serializers/blob/0-9-stable/README.md).
6
+
7
+ The original design is also available [here](https://github.com/rails-api/active_model_serializers/blob/d72b66d4c5355b0ff0a75a04895fcc4ea5b0c65e/README.textile).
8
+
9
+ # ARCHITECTURE
10
+
11
+ An **`ActiveModel::Serializer`** wraps a [serializable resource](https://github.com/rails/rails/blob/4-2-stable/activemodel/lib/active_model/serialization.rb)
12
+ and exposes an `attributes` method, among a few others.
13
+ It allows you to specify which attributes and associations should be represented in the serializatation of the resource.
14
+ It requires an adapter to transform its attributes into a JSON document; it cannot be serialized itself.
15
+ It may be useful to think of it as a
16
+ [presenter](http://blog.steveklabnik.com/posts/2011-09-09-better-ruby-presenters).
17
+
18
+ The **`ActiveModel::ArraySerializer`** represent a collection of resources as serializers
19
+ and, if there is no serializer, primitives.
20
+
21
+ The **`ActiveModel::Adapter`** describes the structure of the JSON document generated from a
22
+ serializer. For example, the `Attributes` example represents each serializer as its
23
+ unmodified attributes. The `JsonApi` adapter represents the serializer as a [JSON
24
+ API](http://jsonapi.org/) document.
25
+
26
+ The **`ActiveModelSerializers::SerializableResource`** acts to coordinate the serializer(s) and adapter
27
+ to an object that responds to `to_json`, and `as_json`. It is used in the controller to
28
+ encapsulate the serialization resource when rendered. However, it can also be used on its own
29
+ to serialize a resource outside of a controller, as well.
30
+
31
+ ## Primitive handling
32
+
33
+ Definitions: A primitive is usually a String or Array. There is no serializer
34
+ defined for them; they will be serialized when the resource is converted to JSON (`as_json` or
35
+ `to_json`). (The below also applies for any object with no serializer.)
36
+
37
+ ActiveModelSerializers doesn't handle primitives passed to `render json:` at all.
38
+
39
+ However, when a primitive value is an attribute or in a collection,
40
+ it is not modified.
41
+
42
+ Internally, if no serializer can be found in the controller, the resource is not decorated by
43
+ ActiveModelSerializers.
44
+
45
+ If the collection serializer (ArraySerializer) cannot
46
+ identify a serializer for a resource in its collection, it raises [`NoSerializerError`](https://github.com/rails-api/active_model_serializers/issues/1191#issuecomment-142327128)
47
+ which is rescued in `ActiveModel::Serializer::Reflection#build_association` which sets
48
+ the association value directly:
49
+
50
+ ```ruby
51
+ reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
52
+ ```
53
+
54
+ (which is called by the adapter as `serializer.associations(*)`.)
55
+
56
+ ## How options are parsed
57
+
58
+ High-level overview:
59
+
60
+ - For a collection
61
+ - `:serializer` specifies the collection serializer and
62
+ - `:each_serializer` specifies the serializer for each resource in the collection.
63
+ - For a single resource, the `:serializer` option is the resource serializer.
64
+ - Options are partitioned in serializer options and adapter options. Keys for adapter options are specified by
65
+ [`ADAPTER_OPTION_KEYS`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/serializable_resource.rb#L5).
66
+ The remaining options are serializer options.
67
+
68
+ Details:
69
+
70
+ 1. **ActionController::Serialization**
71
+ 1. `serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)`
72
+ 1. `options` are partitioned into `adapter_opts` and everything else (`serializer_opts`).
73
+ The `adapter_opts` keys are defined in `ActiveModelSerializers::SerializableResource::ADAPTER_OPTION_KEYS`.
74
+ 1. **ActiveModelSerializers::SerializableResource**
75
+ 1. `if serializable_resource.serializer?` (there is a serializer for the resource, and an adapter is used.)
76
+ - Where `serializer?` is `use_adapter? && !!(serializer)`
77
+ - Where `use_adapter?`: 'True when no explicit adapter given, or explicit value is truthy (non-nil);
78
+ False when explicit adapter is falsy (nil or false)'
79
+ - Where `serializer`:
80
+ 1. from explicit `:serializer` option, else
81
+ 2. implicitly from resource `ActiveModel::Serializer.serializer_for(resource)`
82
+ 1. A side-effect of checking `serializer` is:
83
+ - The `:serializer` option is removed from the serializer_opts hash
84
+ - If the `:each_serializer` option is present, it is removed from the serializer_opts hash and set as the `:serializer` option
85
+ 1. The serializer and adapter are created as
86
+ 1. `serializer_instance = serializer.new(resource, serializer_opts)`
87
+ 2. `adapter_instance = ActiveModel::Serializer::Adapter.create(serializer_instance, adapter_opts)`
88
+ 1. **ActiveModel::Serializer::ArraySerializer#new**
89
+ 1. If the `serializer_instance` was a `ArraySerializer` and the `:serializer` serializer_opts
90
+ is present, then [that serializer is passed into each resource](https://github.com/rails-api/active_model_serializers/blob/a54d237e2828fe6bab1ea5dfe6360d4ecc8214cd/lib/active_model/serializer/array_serializer.rb#L14-L16).
91
+ 1. **ActiveModel::Serializer#attributes** is used by the adapter to get the attributes for
92
+ resource as defined by the serializer.
93
+
94
+ ## What does a 'serializable resource' look like?
95
+
96
+ - An `ActiveRecord::Base` object.
97
+ - Any Ruby object that passes the
98
+ [Lint](http://www.rubydoc.info/github/rails-api/active_model_serializers/ActiveModel/Serializer/Lint/Tests)
99
+ [code](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer/lint.rb).
100
+
101
+ ActiveModelSerializers provides a
102
+ [`ActiveModelSerializers::Model`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/model.rb),
103
+ which is a simple serializable PORO (Plain-Old Ruby Object).
104
+
105
+ ActiveModelSerializers::Model may be used either as a template, or in production code.
106
+
107
+ ```ruby
108
+ class MyModel < ActiveModelSerializers::Model
109
+ attr_accessor :id, :name, :level
110
+ end
111
+ ```
112
+
113
+ The default serializer for `MyModel` would be `MyModelSerializer` whether MyModel is an
114
+ ActiveRecord::Base object or not.
115
+
116
+ Outside of the controller the rules are **exactly** the same as for records. For example:
117
+
118
+ ```ruby
119
+ render json: MyModel.new(level: 'awesome'), adapter: :json
120
+ ```
121
+
122
+ would be serialized the same as
123
+
124
+ ```ruby
125
+ ActiveModelSerializers::SerializableResource.new(MyModel.new(level: 'awesome'), adapter: :json).as_json
126
+ ```
data/docs/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # Docs - ActiveModel::Serializer 0.10.x
2
+
3
+ This is the documentation of ActiveModelSerializers, it's focused on the **0.10.x version.**
4
+
5
+ -----
6
+
7
+ ## General
8
+
9
+ - [Getting Started](general/getting_started.md)
10
+ - [Configuration Options](general/configuration_options.md)
11
+ - [Serializers](general/serializers.md)
12
+ - [Adapters](general/adapters.md)
13
+ - [Rendering](general/rendering.md)
14
+ - [Caching](general/caching.md)
15
+ - [Logging](general/logging.md)
16
+ - [Deserialization](general/deserialization.md)
17
+ - [Instrumentation](general/instrumentation.md)
18
+ - JSON API
19
+ - [Schema](jsonapi/schema.md)
20
+ - [Errors](jsonapi/errors.md)
21
+ - [ARCHITECTURE](ARCHITECTURE.md)
22
+
23
+ ## How to
24
+
25
+ - [How to add root key](howto/add_root_key.md)
26
+ - [How to add pagination links](howto/add_pagination_links.md)
27
+ - [Using ActiveModelSerializers Outside Of Controllers](howto/outside_controller_use.md)
28
+ - [Testing ActiveModelSerializers](howto/test.md)
29
+ - [Passing Arbitrary Options](howto/passing_arbitrary_options.md)
30
+ - [How to serialize a Plain-Old Ruby Object (PORO)](howto/serialize_poro.md)
31
+
32
+ ## Integrations
33
+
34
+ | Integration | Supported ActiveModelSerializers versions | Gem name and/or link
35
+ |----|-----|----
36
+ | Ember.js | 0.9.x | [active-model-adapter](https://github.com/ember-data/active-model-adapter)
37
+ | Ember.js | 0.10.x + | [docs/integrations/ember-and-json-api.md](integrations/ember-and-json-api.md)
38
+ | Grape | 0.10.x + | [docs/integrations/grape.md](integrations/grape.md) |
39
+ | Grape | 0.9.x | https://github.com/jrhe/grape-active_model_serializers/ |
40
+ | Sinatra | 0.9.x | https://github.com/SauloSilva/sinatra-active-model-serializers/
data/docs/STYLE.md ADDED
@@ -0,0 +1,58 @@
1
+ # STYLE
2
+
3
+ ## Code and comments
4
+
5
+ - We are actively working to identify tasks under the label [**Good for New
6
+ Contributors**](https://github.com/rails-api/active_model_serializers/labels/Good%20for%20New%20Contributors).
7
+ - [Changelog
8
+ Missing](https://github.com/rails-api/active_model_serializers/issues?q=label%3A%22Changelog+Missing%22+is%3Aclosed) is
9
+ an easy way to help out.
10
+
11
+ - [Fix a bug](https://github.com/rails-api/active_model_serializers/labels/Ready%20for%20PR).
12
+ - Ready for PR - A well defined bug, needs someone to PR a fix.
13
+ - Bug - Anything that is broken.
14
+ - Regression - A bug that did not exist in previous versions and isn't a new feature (applied in tandem with Bug).
15
+ - Performance - A performance related issue. We could track this as a bug, but usually these would have slightly lower priority than standard bugs.
16
+
17
+ - [Develop new features](https://github.com/rails-api/active_model_serializers/labels/Feature).
18
+
19
+ - [Improve code quality](https://codeclimate.com/github/rails-api/active_model_serializers/code?sort=smell_count&sort_direction=desc).
20
+
21
+ - [Improve amount of code exercised by tests](https://codeclimate.com/github/rails-api/active_model_serializers/coverage?sort=covered_percent&sort_direction=asc).
22
+
23
+ - [Fix RuboCop (Style) TODOS](https://github.com/rails-api/active_model_serializers/blob/master/.rubocop_todo.yml).
24
+ - Delete and offsense, run `rake rubocop` (or possibly `rake rubocop:auto_correct`),
25
+ and [submit a PR](CONTRIBUTING.md#submitting-a-pull-request-pr).
26
+
27
+ - We are also encouraging comments to substantial changes (larger than bugfixes and simple features) under an
28
+ "RFC" (Request for Comments) process before we start active development.
29
+ Look for the [**RFC**](https://github.com/rails-api/active_model_serializers/labels/RFC) label.
30
+
31
+
32
+ ## Pull requests
33
+
34
+ - If the tests pass and the pull request looks good, a maintainer will merge it.
35
+ - If the pull request needs to be changed,
36
+ - you can change it by updating the branch you generated the pull request from
37
+ - either by adding more commits, or
38
+ - by force pushing to it
39
+ - A maintainer can make any changes themselves and manually merge the code in.
40
+
41
+ ## Commit messages
42
+
43
+ - [A Note About Git Commit Messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
44
+ - [http://stopwritingramblingcommitmessages.com/](http://stopwritingramblingcommitmessages.com/)
45
+ - [ThoughtBot style guide](https://github.com/thoughtbot/guides/tree/master/style#git)
46
+
47
+ #### About Pull Requests (PR's)
48
+
49
+ - [Using Pull Requests](https://help.github.com/articles/using-pull-requests)
50
+ - [Github pull requests made easy](http://www.element84.com/github-pull-requests-made-easy.html)
51
+ - [Exercism Git Workflow](http://help.exercism.io/git-workflow.html).
52
+ - [Level up your Git](http://rakeroutes.com/blog/deliberate-git/)
53
+ - [All Your Open Source Code Are Belong To Us](http://www.benjaminfleischer.com/2013/07/30/all-your-open-source-code-are-belong-to-us/)
54
+
55
+ ## Issue Labeling
56
+
57
+ ActiveModelSerializers uses a subset of [StandardIssueLabels](https://github.com/wagenet/StandardIssueLabels) for Github Issues. You can [see our labels here](https://github.com/rails-api/active_model_serializers/labels).
58
+