fast_jsonapi 1.0.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ = fast_jsonapi
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to fast_jsonapi
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
+ * Fork the project.
10
+ * Start a feature/bugfix branch.
11
+ * Commit and push until you are happy with your contribution.
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2017 Shishir Kakaraddi. See LICENSE.txt for
18
+ further details.
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+ require 'juwelier'
14
+ Juwelier::Tasks.new do |gem|
15
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
16
+ gem.name = "fast_jsonapi"
17
+ gem.homepage = "http://github.com/Netflix/fast_jsonapi"
18
+ gem.license = "Apache-2.0"
19
+ gem.summary = %Q{fast JSON API(jsonapi.org) serializer}
20
+ gem.description = %Q{JSON API(jsonapi.org) serializer that works with rails and can be used to serialize any kind of ruby objects}
21
+ gem.email = ""
22
+ gem.authors = ["Shishir Kakaraddi", "Srinivas Raghunathan", "Adam Gross"]
23
+
24
+
25
+ if gem.respond_to?(:metadata)
26
+ gem.metadata['allowed_push_host'] = 'https://rubygems.org'
27
+ else
28
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
29
+ end
30
+ # dependencies defined in Gemfile
31
+ end
32
+ Juwelier::RubygemsDotOrgTasks.new
33
+ require 'rspec/core'
34
+ require 'rspec/core/rake_task'
35
+ RSpec::Core::RakeTask.new(:spec) do |spec|
36
+ spec.pattern = FileList['spec/**/*_spec.rb']
37
+ end
38
+
39
+ desc "Code coverage detail"
40
+ task :simplecov do
41
+ ENV['COVERAGE'] = "true"
42
+ Rake::Task['spec'].execute
43
+ end
44
+
45
+ task :default => :spec
46
+
47
+ require 'rdoc/task'
48
+ Rake::RDocTask.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "fast_jsonapi #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.16
@@ -0,0 +1,35 @@
1
+ {
2
+ "data": [
3
+ {
4
+ "id": "232",
5
+ "type": "movie",
6
+ "attributes": {
7
+ "name": "test movie",
8
+ "year": null
9
+ },
10
+ "relationships": {
11
+ "actors": {
12
+ "data": [
13
+ {
14
+ "id": "1",
15
+ "type": "actor"
16
+ },
17
+ {
18
+ "id": "2",
19
+ "type": "actor"
20
+ }
21
+ ]
22
+ },
23
+ "owner": {
24
+ "data": {
25
+ "id": "3",
26
+ "type": "user"
27
+ }
28
+ }
29
+ }
30
+ }
31
+ ],
32
+ "meta": {
33
+ "total": 2
34
+ }
35
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "data": {
3
+ "id": "232",
4
+ "type": "movie",
5
+ "attributes": {
6
+ "name": "test movie",
7
+ "year": null
8
+ },
9
+ "relationships": {
10
+ "actors": {
11
+ "data": [
12
+ {
13
+ "id": "1",
14
+ "type": "actor"
15
+ },
16
+ {
17
+ "id": "2",
18
+ "type": "actor"
19
+ }
20
+ ]
21
+ },
22
+ "owner": {
23
+ "data": {
24
+ "id": "3",
25
+ "type": "user"
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,108 @@
1
+ # Generated by juwelier
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: fast_jsonapi 1.0.16 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "fast_jsonapi"
9
+ s.version = "1.0.16"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.metadata = { "allowed_push_host" => "https://rubygems.org" } if s.respond_to? :metadata=
13
+ s.require_paths = ["lib"]
14
+ s.authors = ["Shishir Kakaraddi", "Srinivas Raghunathan", "Adam Gross"]
15
+ s.date = "2018-02-01"
16
+ s.description = "JSON API(jsonapi.org) serializer that works with rails and can be used to serialize any kind of ruby objects"
17
+ s.email = ""
18
+ s.extra_rdoc_files = [
19
+ "LICENSE.txt",
20
+ "README.md",
21
+ "README.rdoc"
22
+ ]
23
+ s.files = [
24
+ ".document",
25
+ ".rspec",
26
+ "Gemfile",
27
+ "Gemfile.lock",
28
+ "LICENSE.txt",
29
+ "README.md",
30
+ "README.rdoc",
31
+ "Rakefile",
32
+ "VERSION",
33
+ "docs/collection_serializer_output.json",
34
+ "docs/object_serializer.json",
35
+ "fast_jsonapi.gemspec",
36
+ "lib/extensions/has_one.rb",
37
+ "lib/fast_jsonapi.rb",
38
+ "lib/fast_jsonapi/object_serializer.rb",
39
+ "lib/fast_jsonapi/serialization_core.rb",
40
+ "spec/lib/extensions/active_record_spec.rb",
41
+ "spec/lib/object_serializer_caching_spec.rb",
42
+ "spec/lib/object_serializer_class_methods_spec.rb",
43
+ "spec/lib/object_serializer_hyphen_spec.rb",
44
+ "spec/lib/object_serializer_performance_spec.rb",
45
+ "spec/lib/object_serializer_spec.rb",
46
+ "spec/lib/object_serializer_struct_spec.rb",
47
+ "spec/lib/serialization_core_spec.rb",
48
+ "spec/shared/contexts/ams_context.rb",
49
+ "spec/shared/contexts/movie_context.rb",
50
+ "spec/spec_helper.rb"
51
+ ]
52
+ s.homepage = "http://github.com/Netflix/fast_jsonapi"
53
+ s.licenses = ["Apache-2.0"]
54
+ s.rubygems_version = "2.5.1"
55
+ s.summary = "fast JSON API(jsonapi.org) serializer"
56
+
57
+ if s.respond_to? :specification_version then
58
+ s.specification_version = 4
59
+
60
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
61
+ s.add_runtime_dependency(%q<activesupport>, ["~> 5.0"])
62
+ s.add_runtime_dependency(%q<multi_json>, ["~> 1.12"])
63
+ s.add_runtime_dependency(%q<oj>, ["~> 3.3"])
64
+ s.add_runtime_dependency(%q<skylight>, ["~> 1.3"])
65
+ s.add_runtime_dependency(%q<activerecord>, ["~> 5.0"])
66
+ s.add_development_dependency(%q<rspec>, ["~> 3.5.0"])
67
+ s.add_development_dependency(%q<rspec-benchmark>, ["~> 0.3.0"])
68
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
69
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
70
+ s.add_development_dependency(%q<juwelier>, ["~> 2.1.0"])
71
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
72
+ s.add_development_dependency(%q<byebug>, [">= 0"])
73
+ s.add_development_dependency(%q<active_model_serializers>, ["~> 0.10.4"])
74
+ s.add_development_dependency(%q<sqlite3>, ["~> 1.3"])
75
+ else
76
+ s.add_dependency(%q<activesupport>, ["~> 5.0"])
77
+ s.add_dependency(%q<multi_json>, ["~> 1.12"])
78
+ s.add_dependency(%q<oj>, ["~> 3.3"])
79
+ s.add_dependency(%q<skylight>, ["~> 1.3"])
80
+ s.add_dependency(%q<activerecord>, ["~> 5.0"])
81
+ s.add_dependency(%q<rspec>, ["~> 3.5.0"])
82
+ s.add_dependency(%q<rspec-benchmark>, ["~> 0.3.0"])
83
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
84
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
85
+ s.add_dependency(%q<juwelier>, ["~> 2.1.0"])
86
+ s.add_dependency(%q<simplecov>, [">= 0"])
87
+ s.add_dependency(%q<byebug>, [">= 0"])
88
+ s.add_dependency(%q<active_model_serializers>, ["~> 0.10.4"])
89
+ s.add_dependency(%q<sqlite3>, ["~> 1.3"])
90
+ end
91
+ else
92
+ s.add_dependency(%q<activesupport>, ["~> 5.0"])
93
+ s.add_dependency(%q<multi_json>, ["~> 1.12"])
94
+ s.add_dependency(%q<oj>, ["~> 3.3"])
95
+ s.add_dependency(%q<skylight>, ["~> 1.3"])
96
+ s.add_dependency(%q<activerecord>, ["~> 5.0"])
97
+ s.add_dependency(%q<rspec>, ["~> 3.5.0"])
98
+ s.add_dependency(%q<rspec-benchmark>, ["~> 0.3.0"])
99
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
100
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
101
+ s.add_dependency(%q<juwelier>, ["~> 2.1.0"])
102
+ s.add_dependency(%q<simplecov>, [">= 0"])
103
+ s.add_dependency(%q<byebug>, [">= 0"])
104
+ s.add_dependency(%q<active_model_serializers>, ["~> 0.10.4"])
105
+ s.add_dependency(%q<sqlite3>, ["~> 1.3"])
106
+ end
107
+ end
108
+
@@ -0,0 +1,16 @@
1
+ require 'active_record'
2
+
3
+ ::ActiveRecord::Associations::Builder::HasOne.class_eval do
4
+ # Based on
5
+ # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/builder/collection_association.rb#L50
6
+ # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/builder/singular_association.rb#L11
7
+ def self.define_accessors(mixin, reflection)
8
+ super
9
+ name = reflection.name
10
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
11
+ def #{name.to_s}_id
12
+ association(:#{name}).reader.id
13
+ end
14
+ CODE
15
+ end
16
+ end
@@ -0,0 +1,4 @@
1
+ module FastJsonapi
2
+ require 'fast_jsonapi/object_serializer'
3
+ require 'extensions/has_one'
4
+ end
@@ -0,0 +1,199 @@
1
+ require 'active_support/core_ext/object'
2
+ require 'active_support/concern'
3
+ require 'active_support/inflector'
4
+ require 'oj'
5
+ require 'multi_json'
6
+ require 'fast_jsonapi/serialization_core'
7
+ require 'skylight'
8
+
9
+ module FastJsonapi
10
+ module ObjectSerializer
11
+ extend ActiveSupport::Concern
12
+ include SerializationCore
13
+
14
+ # Skylight integration
15
+ # To remove Skylight
16
+ # Remove the included do block
17
+ # Remove the Gemfile entry
18
+ included do
19
+ include Skylight::Helpers
20
+
21
+ instrument_method :serializable_hash
22
+ instrument_method :to_json
23
+
24
+ # Set record_type based on the name of the serializer class
25
+ set_type default_record_type if default_record_type
26
+ end
27
+
28
+ def initialize(resource, options = {})
29
+ if options.present?
30
+ @meta_tags = options[:meta]
31
+ @includes = options[:include].delete_if(&:blank?) if options[:include].present?
32
+ self.class.has_permitted_includes(@includes) if @includes.present?
33
+ @known_included_objects = {} # keep track of inc objects that have already been serialized
34
+ end
35
+ # @records if enumerables like Array, ActiveRecord::Relation but if Struct just make it a @record
36
+ if resource.respond_to?(:each) && !resource.respond_to?(:each_pair)
37
+ @records = resource
38
+ else
39
+ @record = resource
40
+ end
41
+ end
42
+
43
+ def serializable_hash
44
+ serializable_hash = { data: nil }
45
+ serializable_hash[:meta] = @meta_tags if @meta_tags.present?
46
+ return hash_for_one_record(serializable_hash) if @record
47
+ return hash_for_multiple_records(serializable_hash) if @records
48
+ serializable_hash
49
+ end
50
+
51
+ def hash_for_one_record(serializable_hash)
52
+ serializable_hash[:data] = self.class.record_hash(@record)
53
+ serializable_hash[:included] = self.class.get_included_records(@record, @includes, @known_included_objects) if @includes.present?
54
+ serializable_hash
55
+ end
56
+
57
+ def hash_for_multiple_records(serializable_hash)
58
+ data = []
59
+ included = []
60
+ @records.each do |record|
61
+ data << self.class.record_hash(record)
62
+ included.concat self.class.get_included_records(record, @includes, @known_included_objects) if @includes.present?
63
+ end
64
+ serializable_hash[:data] = data
65
+ serializable_hash[:included] = included if @includes.present?
66
+ serializable_hash
67
+ end
68
+
69
+ def serialized_json
70
+ self.class.to_json(serializable_hash)
71
+ end
72
+
73
+ class_methods do
74
+ def use_hyphen
75
+ @hyphenated = true
76
+ end
77
+
78
+ def set_type(type_name)
79
+ self.record_type = type_name
80
+ if @hyphenated
81
+ self.record_type = type_name.to_s.dasherize.to_sym
82
+ end
83
+ end
84
+
85
+ def default_record_type
86
+ if self.name.end_with?('Serializer')
87
+ class_name = self.name.demodulize
88
+ range_end = class_name.rindex('Serializer')
89
+ class_name[0...range_end].underscore.to_sym
90
+ end
91
+ end
92
+
93
+ def cache_options(cache_options)
94
+ self.cached = cache_options[:enabled] || false
95
+ self.cache_length = cache_options[:cache_length] || 5.minutes
96
+ end
97
+
98
+ def attributes(*attributes_list)
99
+ attributes_list = attributes_list.first if attributes_list.first.class.is_a?(Array)
100
+ self.attributes_to_serialize = {} if self.attributes_to_serialize.nil?
101
+ attributes_list.each do |attr_name|
102
+ method_name = attr_name
103
+ key = method_name
104
+ if @hyphenated
105
+ key = attr_name.to_s.dasherize.to_sym
106
+ end
107
+ attributes_to_serialize[key] = method_name
108
+ end
109
+ end
110
+
111
+ def add_relationship(name, relationship)
112
+ self.relationships_to_serialize = {} if relationships_to_serialize.nil?
113
+ self.cachable_relationships_to_serialize = {} if cachable_relationships_to_serialize.nil?
114
+ self.uncachable_relationships_to_serialize = {} if uncachable_relationships_to_serialize.nil?
115
+
116
+ if !relationship[:cached]
117
+ self.uncachable_relationships_to_serialize[name] = relationship
118
+ else
119
+ self.cachable_relationships_to_serialize[name] = relationship
120
+ end
121
+ self.relationships_to_serialize[name] = relationship
122
+ end
123
+
124
+ def has_many(relationship_name, options = {})
125
+ singular_name = relationship_name.to_s.singularize
126
+ record_type = options[:record_type] || singular_name.to_sym
127
+ name = relationship_name.to_sym
128
+ key = options[:key] || name
129
+ if @hyphenated
130
+ key = options[:key] || relationship_name.to_s.dasherize.to_sym
131
+ record_type = options[:record_type] || singular_name.to_s.dasherize.to_sym
132
+ end
133
+ serializer_key = options[:serializer] || record_type
134
+ relationship = {
135
+ key: key,
136
+ name: name,
137
+ id_method_name: options[:id_method_name] || (singular_name + '_ids').to_sym,
138
+ record_type: record_type,
139
+ object_method_name: options[:object_method_name] || name,
140
+ serializer: compute_serializer_name(serializer_key),
141
+ relationship_type: :has_many,
142
+ cached: options[:cached] || false
143
+ }
144
+ add_relationship(name, relationship)
145
+ end
146
+
147
+ def belongs_to(relationship_name, options = {})
148
+ name = relationship_name.to_sym
149
+ key = options[:key] || name
150
+ record_type = options[:record_type] || name
151
+ serializer_key = options[:serializer] || record_type
152
+ if @hyphenated
153
+ key = options[:key] || relationship_name.to_s.dasherize.to_sym
154
+ record_type = options[:record_type] || relationship_name.to_s.dasherize.to_sym
155
+ end
156
+ relationship = {
157
+ key: key,
158
+ name: name,
159
+ id_method_name: options[:id_method_name] || (relationship_name.to_s + '_id').to_sym,
160
+ record_type: record_type,
161
+ object_method_name: options[:object_method_name] || name,
162
+ serializer: compute_serializer_name(serializer_key),
163
+ relationship_type: :belongs_to,
164
+ cached: options[:cached] || true
165
+ }
166
+ add_relationship(name, relationship)
167
+ end
168
+
169
+ def has_one(relationship_name, options = {})
170
+ name = relationship_name.to_sym
171
+ key = options[:key] || name
172
+ record_type = options[:record_type] || name
173
+ serializer_key = options[:serializer] || record_type
174
+ if @hyphenated
175
+ key = options[:key] || relationship_name.to_s.dasherize.to_sym
176
+ record_type = options[:record_type] || relationship_name.to_s.dasherize.to_sym
177
+ end
178
+ relationship = {
179
+ key: key,
180
+ name: name,
181
+ id_method_name: options[:id_method_name] || (relationship_name.to_s + '_id').to_sym,
182
+ record_type: record_type,
183
+ object_method_name: options[:object_method_name] || name,
184
+ serializer: compute_serializer_name(serializer_key),
185
+ relationship_type: :has_one,
186
+ cached: options[:cached] || false
187
+ }
188
+ add_relationship(name, relationship)
189
+ end
190
+
191
+ def compute_serializer_name(serializer_key)
192
+ namespace = self.name.gsub(/()?\w+Serializer$/, '')
193
+ serializer_name = serializer_key.to_s.classify + 'Serializer'
194
+ return (namespace + serializer_name).to_sym if namespace.present?
195
+ (serializer_key.to_s.classify + 'Serializer').to_sym
196
+ end
197
+ end
198
+ end
199
+ end