mutils 0.2.35 → 1.1.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.
data/README.md CHANGED
@@ -1,13 +1,34 @@
1
- [![Maintainability](https://api.codeclimate.com/v1/badges/2c937dd6d25937ec41bd/maintainability)](https://codeclimate.com/github/niteshpurohit/mutils/maintainability)
1
+ [![Maintainability](https://api.codeclimate.com/v1/badges/42e8a34f839ca0c5ec45/maintainability)](https://codeclimate.com/github/code-vedas/mutils/maintainability)
2
2
  ![](https://ruby-gem-downloads-badge.herokuapp.com/mutils?type=total&color=brightgreen)
3
3
  [![Gem Version](https://badge.fury.io/rb/mutils.svg)](https://badge.fury.io/rb/mutils)
4
- [![Coverage Status](https://coveralls.io/repos/github/niteshpurohit/mutils/badge.svg?branch=feature/coverall)](https://coveralls.io/github/niteshpurohit/mutils?branch=feature/coverall)
5
- [![Build Status](https://travis-ci.com/niteshpurohit/mutils.svg?branch=master)](https://travis-ci.com/niteshpurohit/mutils)
4
+ [![Coverage Status](https://coveralls.io/repos/github/Code-Vedas/mutils/badge.svg?branch=master)](https://coveralls.io/github/Code-Vedas/mutils?branch=master)
5
+ [![Build Status](https://travis-ci.com/code-vedas/mutils.svg?branch=master)](https://travis-ci.com/code-vedas/mutils)
6
6
  # Mutils
7
7
  ## Introduction
8
8
  `mutils` is collection of useful modules for `ruby on rails` which is tested and benchmarked against high load.
9
9
 
10
10
  These collection of modules are built by developer for developers :-)
11
+ # Table of Contents
12
+
13
+ * [Features](#features)
14
+ * [Installation](#installation)
15
+ * [Usage](#usage)
16
+ * [Rails Generator](#rails-generator)
17
+ * [Attributes](#attributes)
18
+ * [Relations](#relations)
19
+ * [Conditional Attributes](#conditional-attributes)
20
+ * [Conditional Relations](#conditional-relations)
21
+ * [Attributes Block](#attributes-blocks)
22
+ * [Attributes Block with Params](#attributes-blocks-with-params)
23
+ * [Custom Methods](#custom-methods)
24
+ * [Name Tag](#name-tag)
25
+ * [Sample Usage](#sample-usage)
26
+
27
+ ## Features
28
+ * Simple declaration syntax similar to Active Model Serializer
29
+ * Realtionships support `belongs_to`, `has_many`, `has_one`
30
+ * Block style attributes with params
31
+
11
32
  ## Installation
12
33
 
13
34
  Add this line to your application's Gemfile:
@@ -22,17 +43,9 @@ Or install it yourself as:
22
43
 
23
44
  $ gem install mutils
24
45
 
25
- ## Modules
26
- | Sno | Name | Status |
27
- |:---: |:-----------------: |:------: |
28
- | 1 | Serializer - JSON | Done |
29
- | 2 | Serializer - XML | Done |
46
+ ## Usage
30
47
 
31
- ## Usage
32
- ### Serializer - JSON
33
- JSON Serializer for Active Models
34
-
35
- #### Generate Serializer by command
48
+ ### Rails Generator
36
49
  ```shell script
37
50
  rails g mutils:serializer User id first_name last_name email
38
51
 
@@ -50,13 +63,7 @@ class UserSerializer < Mutils::Serialization::BaseSerializer
50
63
  end
51
64
  ```
52
65
 
53
- #### Decorations Available
54
- 1. Attributes
55
- 2. Custom Methods
56
- 3. Relations
57
- 3. name_tag
58
-
59
- ##### Attributes
66
+ ### Attributes
60
67
  Attributes are fields in the model itself. You can reference them by below example
61
68
  ```ruby
62
69
  # frozen_string_literal: true
@@ -68,54 +75,131 @@ class UserSerializer < Mutils::Serialization::BaseSerializer
68
75
  attribute :email, {always_include: true} ## this will allow to selectively include email
69
76
  end
70
77
  ```
71
- ##### Custom Methods
72
- Custom methods used in Serializer can be useful for cases as below.
73
- `scope` will be available to reference object in Serializer in below case its `user`
74
-
78
+ ### Relations
79
+ Relations such as `has_many`, `belongs_to`, `has_one` can be used as follows
80
+ 1. Every relation must be provided with their own serializer
81
+ 2. `always_include` option can be used to instruct `Serializer` to always include this relation
82
+ 3. `always_include` by default is disabled, relations which are not `always_include` can be included while using the serializer. Refer to next section for this usage
83
+ 4. `label` option can be used to override model class name while serializing
75
84
  ```ruby
76
85
  # frozen_string_literal: true
77
86
 
78
87
  # User Serializer
79
88
  class UserSerializer < Mutils::Serialization::BaseSerializer
80
89
  attributes :id, :first_name, :last_name, :email
81
- ###
82
- custom_methods :full_name
90
+
91
+ belongs_to :company, serializer: CompanySerializer, always_include: true
83
92
  ## OR
84
- custom_method :full_name, {always_include: true} ## this will allow to selectively include full_name
85
- ###
93
+ belongs_to :company, serializer: CompanySerializer, always_include: true, label: 'organization' ##<== important to give singular name
94
+
95
+ has_many :comments, serializer: CommentSerializer
96
+ has_one :account, serializer: AccountSerializer
86
97
 
87
98
  def full_name
88
99
  "#{scope.first_name} #{scope.last_name}"
89
100
  end
90
101
  end
91
102
  ```
92
- ##### Relations
93
- Relations such as `has_many`, `belongs_to`, `has_one` can be used as follows
94
- 1. Every relation must be provided with their own serializer
95
- 2. `always_include` option can be used to instruct `Serializer` to always include this relation
96
- 3. `always_include` by default is disabled, relations which are not `always_include` can be included while using the serializer. Refer to next section for this usage
97
- 4. `label` option can be used to override model class name while serializing
103
+ ### Conditional Attributes
104
+ Serializer can have conditional attributes with `if: Proc`
105
+ `if: Proc` block can receive `scope` and `params` as arguments
106
+
107
+ - __in proc {|scope|}__, scope is object which is being serialized
108
+ - __in proc {|scope,params|}__, scope is object which is being serialized and params is hash given to Serializer as second arguments in {params:anything}
109
+ ```ruby
110
+ # frozen_string_literal: true
111
+
112
+ # User Serializer
113
+ class UserSerializer < Mutils::Serialization::BaseSerializer
114
+ attributes :id, :first_name, :last_name
115
+ attribute :email, if: proc { |scope| scope.name == 'mutils' } ## Email will only serialize if user's name is 'mutils'
116
+ # OR with Params
117
+ attribute :email, if: proc { |scope,params| params && params[:show_email] == true } ## Email will only serialize if params[:show_email] is true
118
+ end
119
+
120
+ UserSerializer.new(user) # Without params
121
+ UserSerializer.new(user,{params:{show_email:true}}) # With params
122
+ ```
123
+
124
+ ### Conditional Relations
125
+ Serializer can have conditional relations with `if: Proc`
126
+ `if: Proc` block can receive `scope` and `params` as arguments
127
+
128
+ - __in proc {|scope|}__, scope is object which is being serialized
129
+ - __in proc {|scope,params|}__, scope is object which is being serialized and params is hash given to Serializer as second arguments in {params:anything}
130
+ ```ruby
131
+ # frozen_string_literal: true
132
+
133
+ # User Serializer
134
+ class UserSerializer < Mutils::Serialization::BaseSerializer
135
+ attributes :id, :first_name, :last_name
136
+ has_many :comments, serializer: CommentSerializer, if: proc { |scope| scope.name == 'mutils' } ## comments will only serialize if user's name is 'mutils'
137
+ belongs_to :account, serializer: AccountSerializer, if: proc { |scope| scope.name != 'mutils' } ## account will only serialize if user's name is not 'mutils'
138
+ # OR with Params
139
+ belongs_to :account, serializer: AccountSerializer, if: proc { |scope,params| params && params[:show_account] == true } ## account will only serialize if params[:show_account] is true
140
+ end
141
+
142
+ UserSerializer.new(user) # Without params
143
+ UserSerializer.new(user,{params:{show_account:true}}) # With params
144
+
145
+ ```
146
+
147
+ ### Attributes Blocks
148
+ While writting attribute a block can be provided for useful transformations like `full_name` as shown below
98
149
  ```ruby
99
150
  # frozen_string_literal: true
100
151
 
101
152
  # User Serializer
102
153
  class UserSerializer < Mutils::Serialization::BaseSerializer
103
154
  attributes :id, :first_name, :last_name, :email
104
-
105
- belongs_to :company, serializer: CompanySerializer, always_include: true
106
- ##OR
107
- belongs_to :company, serializer: CompanySerializer, always_include: true, label: 'organization' ##<== important to give singular name
108
-
109
- has_many :comments, serializer: CommentSerializer
110
- has_one :account, serializer: AccountSerializer
155
+ attribute :full_name do |object|
156
+ "#{object.first_name} #{object.last_name}"
157
+ end
158
+ end
159
+ ```
160
+ ### Attributes Blocks with Params
161
+ While writting attribute a block can be provided for useful transformations like `full_name` as shown below
162
+ ```ruby
163
+ # frozen_string_literal: true
164
+
165
+ # User Serializer
166
+ class UserSerializer < Mutils::Serialization::BaseSerializer
167
+ attributes :id, :first_name, :last_name, :email
168
+ attribute :is_owner do |object,params|
169
+ params[:owner].id == object.id ? true:false
170
+ end
171
+ end
172
+ ```
173
+ ```ruby
174
+ # in controller
175
+
176
+ user = current_user
177
+ owner = owner_user
178
+ render json: UserSerializer.new(user,{params:{owner:owner}})
179
+ ```
180
+ ### Custom Methods
181
+ Custom methods used in Serializer can be useful for cases as below.
182
+ `scope` will be available to reference object in Serializer in below case its `user`
183
+
184
+ ```ruby
185
+ # frozen_string_literal: true
186
+
187
+ # User Serializer
188
+ class UserSerializer < Mutils::Serialization::BaseSerializer
189
+ attributes :id, :first_name, :last_name, :email
190
+ ###
191
+ custom_methods :full_name
192
+ ## OR
193
+ custom_method :full_name, {always_include: true} ## this will allow to selectively include full_name
194
+ ###
111
195
 
112
196
  def full_name
113
197
  "#{scope.first_name} #{scope.last_name}"
114
198
  end
115
199
  end
116
200
  ```
117
- ##### name_tag
118
- name_tag is used to provide custom name to serializer output keys for json or tags for xml
201
+ ### Name Tag
202
+ name_tag is used to provide custom name to serializer output keys for json
119
203
 
120
204
  **Options**
121
205
  - ``name_tag 'Person', true`` # Include Person or People in JSON serialization as root, true|false this only implies to root serializer
@@ -137,20 +221,20 @@ class UserSerializer < Mutils::Serialization::BaseSerializer
137
221
  end
138
222
  ```
139
223
 
140
- ## Usage: Use anywhere by
224
+ ### Sample Usage
141
225
 
142
226
  ```ruby
143
227
  user = User.first
144
228
  options = {includes: [:comments,:account]}
145
229
  UserSerializer.new(user,options).to_h
146
230
  ```
147
- ###or
231
+ ### or
148
232
  ```ruby
149
233
  users = User.all
150
234
  options = {includes: [:account]}
151
235
  UserSerializer.new(users,options).to_json
152
236
  ```
153
- ###or in controllers
237
+ ### or in controllers
154
238
  ```ruby
155
239
  users = User.all
156
240
  options = {includes: [:account]}
@@ -168,4 +252,8 @@ The gem is available as open source under the terms of the [MIT License](https:/
168
252
 
169
253
  ## Code of Conduct
170
254
 
171
- Everyone interacting in the Mutils project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/niteshpurohit/mutils/blob/master/CODE_OF_CONDUCT.md).
255
+ Everyone interacting in the Mutils project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/code-vedas/mutils/blob/master/CODE_OF_CONDUCT.md).
256
+
257
+ ## Security
258
+
259
+ For security refer to [security](https://github.com/Code-Vedas/mutils/blob/master/SECURITY.md) document.
@@ -0,0 +1,13 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ Versions currently being supported with security updates.
6
+
7
+ | Version | Supported |
8
+ | ------- | ------------------ |
9
+ | 1.x.x | :white_check_mark: |
10
+
11
+ ## Reporting a Vulnerability
12
+
13
+ Create an issue or email at security@codevedas.com
data/Version ADDED
@@ -0,0 +1 @@
1
+ v1.1.0
@@ -0,0 +1 @@
1
+ module.exports = {extends: ['@commitlint/config-angular']};
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ set -euo pipefail
4
+
5
+ mkdir -p $HOME/.gem
6
+ touch $HOME/.gem/credentials
7
+ chmod 0600 $HOME/.gem/credentials
8
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
9
+ gem build *.gemspec
10
+ gem push *.gem
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'dry/inflector'
3
4
  require_relative 'mutils/version'
4
- require 'active_support/concern'
5
- require 'active_support/inflector'
6
- require 'active_support/core_ext/hash'
5
+ require_relative 'mutils/lib/helper'
6
+ require_relative 'mutils/lib/result_hash'
7
7
  require_relative 'mutils/serialization/serialization_results'
8
8
  require_relative 'mutils/serialization/serialization_includes'
9
9
  require_relative 'mutils/serialization/serialization_methods'
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+ # module Mutils
5
+ module Mutils
6
+ module Lib
7
+ # Helper: caching expensive repetitive operations
8
+ class Helper
9
+ include Singleton
10
+
11
+ def initialize
12
+ self.inflector_object = Dry::Inflector.new
13
+ self.pluralize_cache = {}
14
+ self.underscore_cache = {}
15
+ self.constantize_cache = {}
16
+ end
17
+
18
+ def underscore(string)
19
+ underscore_cache[string] = inflector_object.underscore string unless underscore_cache[string]
20
+ underscore_cache[string]
21
+ end
22
+
23
+ def pluralize(string)
24
+ pluralize_cache[string] = inflector_object.pluralize string unless pluralize_cache[string]
25
+ pluralize_cache[string]
26
+ end
27
+
28
+ def constantize(string)
29
+ constantize_cache[string] = Object.const_get string unless constantize_cache[string]
30
+ constantize_cache[string]
31
+ end
32
+
33
+ def collection?(object)
34
+ object.respond_to?(:size) && !object.respond_to?(:each_pair)
35
+ end
36
+
37
+ private
38
+
39
+ attr_accessor :inflector_object, :pluralize_cache, :underscore_cache, :constantize_cache
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # module Mutils
4
+ module Mutils
5
+ module Lib
6
+ # ResultHash: Store result using this class.
7
+ class ResultHash
8
+ def initialize
9
+ self._hash = {}
10
+ end
11
+
12
+ def []=(key, value)
13
+ _hash[key] = value
14
+ end
15
+
16
+ def hash
17
+ _hash
18
+ end
19
+
20
+ private
21
+
22
+ attr_accessor :_hash
23
+ end
24
+ end
25
+ end
@@ -33,14 +33,6 @@ module Mutils
33
33
  JSON.generate(as_json, options)
34
34
  end
35
35
 
36
- def to_xml(_options = {})
37
- to_h.to_xml(root: class_name, skip_instruct: true, indent: 2)
38
- end
39
-
40
- def as_xml(_options = {})
41
- to_xml
42
- end
43
-
44
36
  private
45
37
 
46
38
  attr_writer :scope
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Module Mutils
4
+ module Mutils
5
+ # Module SerializationCore
6
+ module Serialization
7
+ # Module Methods
8
+ module Methods
9
+ # Module Attributes
10
+ module Attributes
11
+ def attributes(*attributes_list)
12
+ parse_attributes_methods(attributes_list, false)
13
+ end
14
+
15
+ def custom_methods(*attributes_list)
16
+ parse_attributes_methods(attributes_list, true)
17
+ end
18
+
19
+ def parse_attributes_methods(list, is_method)
20
+ self.attributes_to_serialize = {} if attributes_to_serialize.nil?
21
+ list&.each do |attr|
22
+ value = { method: is_method, always_include: true }
23
+ attributes_to_serialize[attr] = value
24
+ end
25
+ end
26
+
27
+ def attribute(method_name, options = {}, &proc)
28
+ raise "if: should be a Proc object for attribute #{method_name}" if options[:if] && !options[:if].instance_of?(Proc)
29
+
30
+ if proc.instance_of? Proc
31
+ self.attributes_to_serialize_blocks = {} if attributes_to_serialize_blocks.nil?
32
+ options[:block] = proc
33
+ attributes_to_serialize_blocks[method_name] = options
34
+ else
35
+ add_single_attribute(method_name, options, false)
36
+ end
37
+ end
38
+
39
+ def custom_method(method_name, options = {})
40
+ add_single_attribute(method_name, options, true)
41
+ end
42
+
43
+ def add_single_attribute(method_name, options, is_method)
44
+ self.attributes_to_serialize = {} if attributes_to_serialize.nil?
45
+ always_include = options[:always_include].nil? ? false : options[:always_include]
46
+ value = { method: is_method, always_include: always_include, if: options[:if] }
47
+ attributes_to_serialize[method_name] = value
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Module Mutils
4
+ module Mutils
5
+ # Module SerializationCore
6
+ module Serialization
7
+ # Module Methods
8
+ module Methods
9
+ # Module Main
10
+ module Main
11
+ def name_tag(name_tag, root = nil)
12
+ self.serializer_name = name_tag
13
+ self.include_root = root
14
+ end
15
+
16
+ def class_exists?(class_name)
17
+ klass = begin
18
+ Mutils::Lib::Helper.instance.constantize(class_name.to_s)
19
+ rescue StandardError
20
+ nil
21
+ end
22
+ klass && defined?(klass) && klass.is_a?(Class)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end