mutils 0.2.34 → 1.0.1

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 |
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