mutils 0.2.34 → 1.0.1

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 |
30
-
31
- ## Usage
32
- ### Serializer - JSON
33
- JSON Serializer for Active Models
46
+ ## Usage
34
47
 
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
@@ -64,48 +71,116 @@ Attributes are fields in the model itself. You can reference them by below examp
64
71
  # User Serializer
65
72
  class UserSerializer < Mutils::Serialization::BaseSerializer
66
73
  attributes :id, :first_name, :last_name, :email
74
+ ## OR
75
+ attribute :email, {always_include: true} ## this will allow to selectively include email
67
76
  end
68
77
  ```
69
- ##### Custom Methods
70
- Custom methods used in Serializer can be useful for cases as below.
71
- `scope` will be available to reference object in Serializer in below case its `user`
72
-
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
73
84
  ```ruby
74
85
  # frozen_string_literal: true
75
86
 
76
87
  # User Serializer
77
88
  class UserSerializer < Mutils::Serialization::BaseSerializer
78
89
  attributes :id, :first_name, :last_name, :email
79
- custom_methods :full_name
90
+
91
+ belongs_to :company, serializer: CompanySerializer, always_include: true
92
+ ## OR
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
80
97
 
81
98
  def full_name
82
99
  "#{scope.first_name} #{scope.last_name}"
83
100
  end
84
101
  end
85
102
  ```
86
- ##### Relations
87
- Relations such as `has_many`, `belongs_to`, `has_one` can be used as follows
88
- 1. Every relation must be provided with their own serializer
89
- 2. `always_include` option can be used to instruct `Serializer` to always include this relation
90
- 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
103
+ ### Conditional Attributes
104
+ Attributes are fields in the model itself. You can reference them by below example
105
+ ```ruby
106
+ # frozen_string_literal: true
91
107
 
108
+ # User Serializer
109
+ class UserSerializer < Mutils::Serialization::BaseSerializer
110
+ attributes :id, :first_name, :last_name
111
+ attribute :email, if: proc { |scope| scope.name == 'mutils' } ## Email will only serialize if user's name is 'mutils'
112
+ end
113
+ ```
114
+ in proc {|scope|}, scope is object which is being serialized
115
+ ### Conditional Relations
116
+ Attributes are fields in the model itself. You can reference them by below example
117
+ ```ruby
118
+ # frozen_string_literal: true
119
+
120
+ # User Serializer
121
+ class UserSerializer < Mutils::Serialization::BaseSerializer
122
+ attributes :id, :first_name, :last_name
123
+ has_many :comments, serializer: CommentSerializer, if: proc { |scope| scope.name == 'mutils' } ## comments will only serialize if user's name is 'mutils'
124
+ belongs_to :account, serializer: AccountSerializer, if: proc { |scope| scope.name != 'mutils' } ## account will only serialize if user's name is not 'mutils'
125
+ end
126
+ ```
127
+ in proc {|scope|}, scope is object which is being serialized
128
+ ### Attributes Blocks
129
+ While writting attribute a block can be provided for useful transformations like `full_name` as shown below
92
130
  ```ruby
93
131
  # frozen_string_literal: true
94
132
 
95
133
  # User Serializer
96
134
  class UserSerializer < Mutils::Serialization::BaseSerializer
97
135
  attributes :id, :first_name, :last_name, :email
98
- belongs_to :company, serializer: CompanySerializer, always_include: true
99
- has_many :comments, serializer: CommentSerializer
100
- has_one :account, serializer: AccountSerializer
136
+ attribute :full_name do |object|
137
+ "#{object.first_name} #{object.last_name}"
138
+ end
139
+ end
140
+ ```
141
+ ### Attributes Blocks with Params
142
+ While writting attribute a block can be provided for useful transformations like `full_name` as shown below
143
+ ```ruby
144
+ # frozen_string_literal: true
145
+
146
+ # User Serializer
147
+ class UserSerializer < Mutils::Serialization::BaseSerializer
148
+ attributes :id, :first_name, :last_name, :email
149
+ attribute :is_owner do |object,params|
150
+ params[:owner].id == object.id ? true:false
151
+ end
152
+ end
153
+ ```
154
+ ```ruby
155
+ # in controller
156
+
157
+ user = current_user
158
+ owner = owner_user
159
+ render json: UserSerializer.new(user,{params:{owner:owner}})
160
+ ```
161
+ ### Custom Methods
162
+ Custom methods used in Serializer can be useful for cases as below.
163
+ `scope` will be available to reference object in Serializer in below case its `user`
164
+
165
+ ```ruby
166
+ # frozen_string_literal: true
167
+
168
+ # User Serializer
169
+ class UserSerializer < Mutils::Serialization::BaseSerializer
170
+ attributes :id, :first_name, :last_name, :email
171
+ ###
172
+ custom_methods :full_name
173
+ ## OR
174
+ custom_method :full_name, {always_include: true} ## this will allow to selectively include full_name
175
+ ###
101
176
 
102
177
  def full_name
103
178
  "#{scope.first_name} #{scope.last_name}"
104
179
  end
105
180
  end
106
181
  ```
107
- ##### name_tag
108
- name_tag is used to provide custom name to serializer output keys for json or tags for xml
182
+ ### Name Tag
183
+ name_tag is used to provide custom name to serializer output keys for json
109
184
 
110
185
  **Options**
111
186
  - ``name_tag 'Person', true`` # Include Person or People in JSON serialization as root, true|false this only implies to root serializer
@@ -127,20 +202,20 @@ class UserSerializer < Mutils::Serialization::BaseSerializer
127
202
  end
128
203
  ```
129
204
 
130
- ## Usage: Use anywhere by
205
+ ### Sample Usage
131
206
 
132
207
  ```ruby
133
208
  user = User.first
134
209
  options = {includes: [:comments,:account]}
135
210
  UserSerializer.new(user,options).to_h
136
211
  ```
137
- ###or
212
+ ### or
138
213
  ```ruby
139
214
  users = User.all
140
215
  options = {includes: [:account]}
141
216
  UserSerializer.new(users,options).to_json
142
217
  ```
143
- ###or in controllers
218
+ ### or in controllers
144
219
  ```ruby
145
220
  users = User.all
146
221
  options = {includes: [:account]}
@@ -158,4 +233,8 @@ The gem is available as open source under the terms of the [MIT License](https:/
158
233
 
159
234
  ## Code of Conduct
160
235
 
161
- 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).
236
+ 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).
237
+
238
+ ## Security
239
+
240
+ 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.0.1
@@ -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