mutils 0.2.35 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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