json_representations 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a0f4c994f61bcb22f373780675d65c19c61da4763303faaf18f7c3195c91577b
4
+ data.tar.gz: aa1436306ae60776d0f0033c29f1e5708582be34f13b2a16c1b2d2ef28a00f66
5
+ SHA512:
6
+ metadata.gz: cbce25129dcfa28384c1339149f0284090cd93b35a60bb5f7fc63bdb3f19a0f5440b45f1822ec8d271278056a9097c5661208cc00e577b6b3ce4279f175cd1eb
7
+ data.tar.gz: d1d782de80c1e91bfeb256911aad10231980f397f7afcd64ffe85d09fa9921e4505c8756b26fbd4b3b29a7ed8de73721c398634e484de9afccef354ea6bffb61
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: RSpec
3
+
4
+ on:
5
+ push:
6
+ branches: [ '**' ]
7
+
8
+ jobs:
9
+ test:
10
+
11
+ runs-on: ubuntu-latest
12
+
13
+ strategy:
14
+ matrix:
15
+ ruby-version: [2.7.2, 2.6.6]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - name: Set up Ruby ${{ matrix.ruby-version }}
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby-version }}
23
+ - name: Install dependencies
24
+ run: bundle install
25
+ - name: Run tests
26
+ run: bundle exec rspec
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ .byebug_history
13
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 2.7.2
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.7.2
5
+ before_install: gem install bundler -v 2.2.14
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in json_representations.gemspec
6
+ gemspec
7
+
8
+ gem 'byebug'
data/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ json_representations (1.0.0)
5
+ activesupport (~> 6.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (6.1.3)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (>= 1.6, < 2)
13
+ minitest (>= 5.1)
14
+ tzinfo (~> 2.0)
15
+ zeitwerk (~> 2.3)
16
+ byebug (11.0.1)
17
+ concurrent-ruby (1.1.8)
18
+ diff-lcs (1.4.4)
19
+ i18n (1.8.9)
20
+ concurrent-ruby (~> 1.0)
21
+ minitest (5.14.4)
22
+ rake (13.0.1)
23
+ rspec (3.10.0)
24
+ rspec-core (~> 3.10.0)
25
+ rspec-expectations (~> 3.10.0)
26
+ rspec-mocks (~> 3.10.0)
27
+ rspec-core (3.10.1)
28
+ rspec-support (~> 3.10.0)
29
+ rspec-expectations (3.10.1)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.10.0)
32
+ rspec-mocks (3.10.2)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.10.0)
35
+ rspec-support (3.10.2)
36
+ tzinfo (2.0.4)
37
+ concurrent-ruby (~> 1.0)
38
+ zeitwerk (2.4.2)
39
+
40
+ PLATFORMS
41
+ ruby
42
+
43
+ DEPENDENCIES
44
+ bundler (~> 2.2.14)
45
+ byebug
46
+ json_representations!
47
+ rake (~> 13.0)
48
+ rspec (~> 3.10)
49
+
50
+ BUNDLED WITH
51
+ 2.2.14
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 rjurado01
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,182 @@
1
+ # JsonRepresentations
2
+ [![Gem Version](https://badge.fury.io/rb/json_representations.svg)](https://badge.fury.io/rb/json_representations)
3
+ ![Build Status](https://github.com/nosolosoftware/json_representations/actions/workflows/rspec.yml/badge.svg)
4
+
5
+ Creates representations of your model data in a simple and clean way.
6
+
7
+ ## Features
8
+
9
+ * Easy to use
10
+ * Easy to define representations
11
+ * Support representations hinheritance
12
+ * Support module definition
13
+ * Support options
14
+ * Support ActiveRecord collection options
15
+ * Faster
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem 'json_representations'
23
+ ```
24
+
25
+ And then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install json_representations
32
+
33
+ ## Usage
34
+
35
+ Includes the `JsonRepresentations` module into your class and define your representations.
36
+ Representations are evaluated into class instance object and must returns a `json` object.
37
+
38
+ ```ruby
39
+ class User
40
+ include JsonRepresentations
41
+
42
+ attr_accessor :first_name, :last_name, :age, :city
43
+
44
+ def initialize(first_name, last_name, age, city)
45
+ @first_name = first_name
46
+ @last_name = last_name
47
+ @age = age
48
+ @city = city
49
+ end
50
+
51
+ representation :public do |options| # you can pass options
52
+ {
53
+ full_name: "#{first_name} #{last_name}",
54
+ date: options[:date]
55
+ }
56
+ end
57
+
58
+ representation :private, extend: :public do # you can extends another representations
59
+ {
60
+ age: age,
61
+ city: city.representation(:basic)
62
+ }
63
+ end
64
+ end
65
+
66
+ # you can define representations in a module
67
+ module CityRepresentations
68
+ include JsonRepresentations
69
+
70
+ representation :basic do
71
+ {
72
+ name: name
73
+ }
74
+ end
75
+ end
76
+
77
+ class City
78
+ include CityRepresentations
79
+
80
+ attr_accessor :name
81
+
82
+ def initialize(name)
83
+ @name = name
84
+ end
85
+ end
86
+
87
+ city = City.new('Madrid')
88
+ user = User.new('John', 'Doe', 30, city)
89
+
90
+ user.representation(:private, date: '2017-12-21')
91
+ # {:full_name=>"John Doe", :date=>"2017-12-21", :age=>30, :city=>{:name=>"Madrid"}}
92
+
93
+ user.representation(:private, date: '2017-12-21') # short form
94
+ # {:full_name=>"John Doe", :date=>"2017-12-21", :age=>30, :city=>{:name=>"Madrid"}}
95
+ ```
96
+
97
+ ## Modules Inheritance
98
+
99
+ You can include a module representation into other module like this example:
100
+
101
+ ```ruby
102
+ module ParentRepresentations
103
+ include JsonRepresentations
104
+
105
+ representation :a do {name: name} end
106
+ representation :b do {name: name} end
107
+ representation :c do {name: name} end
108
+ end
109
+
110
+ module ChildRepresentations
111
+ include ParentRepresentations
112
+
113
+ representation :a do # overwrite
114
+ {color: color}
115
+ end
116
+
117
+ representation :b, extend: true do # extend parent representation with same name
118
+ {color: color}
119
+ end
120
+
121
+ representation :d, extend: :c do # extend parent representation
122
+ {color: color}
123
+ end
124
+ end
125
+
126
+ class Child
127
+ include ChildRepresentations
128
+
129
+ attr_accessor :color
130
+
131
+ def initialize(name, color)
132
+ @name = name
133
+ @color = color
134
+ end
135
+ end
136
+
137
+ child = Child.new('child', 'red')
138
+ child.representation(:a) # {color: 'red'}
139
+ child.representation(:b) # {name: 'child', color: 'red'}
140
+ child.representation(:c) # {name: 'child'}
141
+ child.representation(:d) # {name: 'child', color: 'red'}
142
+ ```
143
+
144
+ When you includes representation module (parent) into other module (child):
145
+
146
+ * Parent representations are included
147
+ * If a representation is redefined, it is overwritten
148
+ * You can extend parent representations
149
+ * You must use `extend: true` when use the same name
150
+
151
+ ## ActiveRecord collection options
152
+
153
+ You can use this ActiveRecord option when you define a representation:
154
+
155
+ * [includes](https://apidock.com/rails/ActiveRecord/QueryMethods/includes)
156
+ * [eager_load](https://apidock.com/rails/ActiveRecord/QueryMethods/eager_load)
157
+ * [preload](https://apidock.com/rails/ActiveRecord/QueryMethods/preload)
158
+
159
+ ```
160
+ representation :private, includes: [:city]
161
+ {
162
+ age: age,
163
+ city: city.representation(:basic)
164
+ }
165
+ end
166
+ ```
167
+
168
+ This options will be used on the collection before to serializing it automatically.
169
+
170
+ ## Development
171
+
172
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
173
+
174
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
175
+
176
+ ## Contributing
177
+
178
+ Bug reports and pull requests are welcome on GitHub at https://github.com/nosolosoftware/json_representations.
179
+
180
+ ## License
181
+
182
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'json_representations'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,27 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'json_representations/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'json_representations'
7
+ spec.version = JsonRepresentations::VERSION
8
+ spec.authors = ['rjurado01']
9
+ spec.email = ['rjurado01@gmail.com']
10
+
11
+ spec.summary = 'Creates representations of your model data'
12
+ spec.description = 'Creates representations of your model data in a simple and clean way'
13
+ spec.homepage = 'https://github.com/nosolosoftware/json_representations'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_dependency 'activesupport', '~> 6.0'
24
+ spec.add_development_dependency 'bundler', '~> 2.2.14'
25
+ spec.add_development_dependency 'rake', '~> 13.0'
26
+ spec.add_development_dependency 'rspec', '~> 3.10'
27
+ end
@@ -0,0 +1,88 @@
1
+ require 'active_support/core_ext/object'
2
+ require 'json_representations/collection.rb'
3
+
4
+ module JsonRepresentations
5
+ QUERY_METHODS = %i[includes eager_load preload].freeze
6
+
7
+ module ClassMethods
8
+ def representation(name, options={}, &block)
9
+ @representations ||= {}
10
+ @representations[name] = options.merge(name: name, class: self, block: block)
11
+
12
+ # copy parent representation options that should be inherited
13
+ return unless options[:extend]
14
+ extend_representation_name = options[:extend] == true ? name : options[:extend]
15
+ extend_representation = (parent_entity || self).representations[extend_representation_name]
16
+
17
+ QUERY_METHODS.each do |option|
18
+ next unless (extend_option_value = extend_representation[option])
19
+ @representations[name][option] = extend_option_value + (options[option] || [])
20
+ end
21
+ end
22
+
23
+ def representations
24
+ @representations
25
+ end
26
+
27
+ def parent_entity
28
+ @parent_entity
29
+ end
30
+
31
+ def find_representation(name)
32
+ representations[name] || @parent_entity&.find_representation(name) if name
33
+ end
34
+
35
+ def render_representation(object, representation_name, options)
36
+ return {} unless (representation = find_representation(representation_name))
37
+
38
+ data = {}
39
+ loop do
40
+ data = object.instance_exec(
41
+ options,
42
+ &representation[:block]
43
+ ).merge(data)
44
+
45
+ representation =
46
+ if representation[:extend] == true
47
+ representation[:class].parent_entity&.find_representation(representation[:name])
48
+ else
49
+ find_representation(representation[:extend])
50
+ end
51
+
52
+ return data.as_json unless representation
53
+ end
54
+ end
55
+ end
56
+
57
+ def self.included(base)
58
+ base.extend ClassMethods
59
+
60
+ base.class_eval do
61
+ eval %{
62
+ def representation(name, options={})
63
+ #{base}.render_representation(self, name.to_sym, options.dup)
64
+ end
65
+ }
66
+
67
+ def self.included(base)
68
+ if base.class == Module
69
+ JsonRepresentations.send(:included, base)
70
+ base.instance_variable_set :@parent_entity, self
71
+ else
72
+ context = self
73
+ base.define_singleton_method(:representations) { context.representations }
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ Array.include(JsonRepresentations::Collection)
81
+
82
+ if defined?(Mongoid::Criteria)
83
+ Mongoid::Criteria.include(JsonRepresentations::Collection)
84
+ end
85
+
86
+ if defined?(ActiveRecord::Relation)
87
+ ActiveRecord::Relation.include(JsonRepresentations::Collection)
88
+ end
@@ -0,0 +1,29 @@
1
+ module JsonRepresentations
2
+ module Collection
3
+ def self.included(base)
4
+ base.class_eval do
5
+ def representation(name=nil, options={})
6
+ subject = self
7
+
8
+ if respond_to?(:klass) && klass.respond_to?(:representations)
9
+ # call supported methods of ActiveRecord::QueryMethods
10
+ QUERY_METHODS.each do |method|
11
+ next unless respond_to? method
12
+
13
+ args = klass.representations.dig(name, method)
14
+
15
+ # we need to reassign because ActiveRecord returns new object
16
+ subject = subject.public_send(method, args) if args
17
+ end
18
+ end
19
+
20
+ return super if respond_to? :super
21
+
22
+ subject.map do |item|
23
+ item.respond_to?(:representation) ? item.representation(name, options) : item
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module JsonRepresentations
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json_representations
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - rjurado01
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-03-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.2.14
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.2.14
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.10'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.10'
69
+ description: Creates representations of your model data in a simple and clean way
70
+ email:
71
+ - rjurado01@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".github/workflows/rspec.yml"
77
+ - ".gitignore"
78
+ - ".rspec"
79
+ - ".tool-versions"
80
+ - ".travis.yml"
81
+ - Gemfile
82
+ - Gemfile.lock
83
+ - LICENSE.txt
84
+ - README.md
85
+ - Rakefile
86
+ - bin/console
87
+ - bin/setup
88
+ - json_representations.gemspec
89
+ - lib/json_representations.rb
90
+ - lib/json_representations/collection.rb
91
+ - lib/json_representations/version.rb
92
+ homepage: https://github.com/nosolosoftware/json_representations
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubygems_version: 3.1.4
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Creates representations of your model data
115
+ test_files: []