active_resourceable 0.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: b3871f317828c3c6384cef4b7989929fc00ec45da1b6542ee7871b552b523238
4
+ data.tar.gz: 8ab803621f88abfd564262797edd806453cfba42e3878a76c3ae3ae4694a0f5d
5
+ SHA512:
6
+ metadata.gz: 0adaacc5b2a3d81e6749925a7c08673c78644e3c90635ee86d0280b225e892ffa7b9c207fe156588b327b137ea3727ffcac9a2c8e079a466ec8048bc083ab1e2
7
+ data.tar.gz: c63d668b2959dd2fbdf03915545c3796c57e87c0a0ca35865b3883dfa18bb01795b2bbc12c1f8e6352a455ad7e60248bb0b59cee30238862cbd883368732bc01
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Adam Hess
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Active Resourceable
2
+
3
+ A tiny framework built on top of Rails in order to help developers focus on writing important business logic. It should be used with hotwired
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require "bundler/setup"
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
6
+ load "rails/tasks/engine.rake"
7
+ load "rails/tasks/statistics.rake"
8
+
9
+ Rake::TestTask.new do |test|
10
+ test.libs << "test"
11
+ test.test_files = FileList["test/**/*_test.rb"]
12
+ test.warning = false
13
+ end
14
+
15
+ task default: :test
@@ -0,0 +1,113 @@
1
+ module ActiveResourceable::Resourceable
2
+ extend ActiveSupport::Concern
3
+ included do
4
+ end
5
+
6
+ class_methods do
7
+
8
+ def resource_model name, **opt
9
+
10
+ model_class = name.to_s.classify.constantize if name.is_a? Symbol
11
+ model_class = name.classify.constantize if name.is_a? String
12
+ model_class = name if name.is_a? Class and name.ancestors.include? ActiveRecord::Base
13
+ raise "Unable to identify resource model" if model_class.nil?
14
+ model_name = model_class.name.singularize.downcase
15
+
16
+ filter_set = opt[:filter_set]
17
+
18
+ filter_set.each do |filter_attr, filter_opt|
19
+ filter_on filter_attr, **filter_opt
20
+ end unless filter_set.nil?
21
+
22
+ sort_set = opt[:sort_set]
23
+
24
+ sort_set.each do |sort_attr, sort_opt|
25
+ sort_on sort_attr, **sort_opt
26
+ end unless sort_set.nil?
27
+
28
+ define_method("list_#{model_name.pluralize}") do
29
+ @pagy, collection = pagy(filtrate(model_class.readable_for(access_object)))
30
+ instance_variable_set :"@#{model_name.pluralize}", collection
31
+ end
32
+
33
+ define_method("show_#{model_name}") do
34
+ instance = model_class.readable_for(access_object).find(params[:id])
35
+ instance.access_object = access_object
36
+ instance_variable_set :"@#{model_name}", instance
37
+ end
38
+
39
+ define_method("new_#{model_name}") do
40
+ instance = model_class.new
41
+ instance.access_object = access_object
42
+ instance_variable_set :"@#{model_name}", instance
43
+ end
44
+
45
+ define_method("create_#{model_name}") do
46
+ instance = model_class.new
47
+ instance_variable_set :"@#{model_name}", instance
48
+ instance.access_object = access_object
49
+ instance.assign_attributes send("#{model_name}_params")
50
+ instance.save
51
+ render :new, status: :unprocessable_entity unless instance_variable_get(:"@#{model_name}").valid?
52
+ end
53
+
54
+ define_method("edit_#{model_name}") do
55
+ instance = model_class.editable_for(access_object).find(params[:id])
56
+ instance.access_object = access_object
57
+ instance_variable_set :"@#{model_name}", instance
58
+ end
59
+
60
+ define_method("update_#{model_name}") do
61
+ instance = model_class.editable_for(access_object).find(params[:id])
62
+ instance.access_object = access_object
63
+ instance_variable_set :"@#{model_name}", instance
64
+ instance.assign_attributes send("#{model_name}_params")
65
+ instance.save
66
+ render :edit, status: :unprocessable_entity unless instance_variable_get(:"@#{model_name}").valid?
67
+ end
68
+
69
+ define_method("destroy_#{model_name}") do
70
+ instance = model_class.deletable_for(access_object).find(params[:id])
71
+ instance.access_object = access_object
72
+ instance.destroy
73
+ instance_variable_set :"@#{model_name}", instance
74
+ end
75
+
76
+ define_method("#{model_name}_params") do
77
+ instance = instance_variable_get(:"@#{model_name}")
78
+ fields = instance.accessable_fields
79
+ send("#{model_name}_attrs", params.fetch(model_name, {}).permit(fields), fields)
80
+ end
81
+
82
+ alias_method "#{model_name}_args", "#{model_name}_params"
83
+
84
+ define_method("#{model_name}_attrs") do |object_params, fields|
85
+ (fields.include?(:user_id) and access_object.present?) ? object_params.merge(user_id: access_object.id) : object_params
86
+ end
87
+
88
+ define_method(:access_object) do
89
+ @access.authenticated_user
90
+ end
91
+
92
+ define_method(:filter_params) do
93
+ params.fetch(:filters, {}).permit(*filter_set.keys)
94
+ end
95
+
96
+ define_method(:sort_params) do
97
+ params.permit(:sort)
98
+ end
99
+
100
+ alias_method :user_object, :access_object
101
+
102
+ before_action :"list_#{model_name.pluralize}", only: %i[index]
103
+ before_action :"show_#{model_name}", only: %i[show]
104
+ before_action :"new_#{model_name}", only: %i[new]
105
+ before_action :"create_#{model_name}", only: %i[create]
106
+ before_action :"edit_#{model_name}", only: %i[edit]
107
+ before_action :"update_#{model_name}", only: %i[update]
108
+ before_action :"destroy_#{model_name}", only: %i[destroy]
109
+
110
+ end
111
+
112
+ end
113
+ end
@@ -0,0 +1,19 @@
1
+ class ActiveResourceable::AppFormBuilder < ActionView::Helpers::FormBuilder
2
+
3
+ Dir.glob("#{Rails.root}/app/views/app_form_builder/*").each do |view_path|
4
+ field = view_path.split('/')[-1].split('.')[0][1..-1]
5
+ define_method(field) do |*args, **kwargs, &block|
6
+ @template.render partial: "/app_form_builder/#{field}", locals: { args: args, kwargs: kwargs, block: block, field: self }
7
+ end
8
+ end
9
+
10
+ def is_required method
11
+ @object.class.validators_on(method).any? do |validator|
12
+ validator.class == ActiveRecord::Validations::PresenceValidator
13
+ end unless @object.nil?
14
+ end
15
+
16
+ def should_display_input? method, access_object
17
+ @object.accessable_fields.any? { |attr| attr.is_a?(Hash) ? attr.keys.first.to_s == "#{method}_attributes" : attr == method }
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ class ActiveResourceable::ActiveRecordInstanceMethodJob < ApplicationJob
2
+ queue_as :default
3
+
4
+ def perform(instance, method, *args)
5
+ instance.send "#{method}_sync", *args
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ class ActiveResourceable::ActiveRecordInstanceMethodJobUniqueUntilExecutingJob < ApplicationJob
2
+ queue_as :default
3
+ unique :until_executing, on_conflict: ->(job) {}
4
+
5
+ def perform(instance, method, *args)
6
+ instance.send "#{method}_sync", *args
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveResourceable::Asyncable
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods do
5
+ def async_method method, options = {}
6
+ alias_method :"#{method}_sync", :"#{method}"
7
+
8
+ define_method(:"#{method}") do |*args|
9
+ ActiveResourceable::ActiveRecordInstanceMethodJob.set(**options).perform_later(self, method, *args)
10
+ end
11
+ end
12
+
13
+ def async_method_unique_until_executing method, options = {}
14
+ alias_method :"#{method}_sync", :"#{method}"
15
+
16
+ define_method(:"#{method}") do |*args|
17
+ ActiveResourceable::ActiveRecordInstanceMethodJobUniqueUntilExecutingJob.set(**options).perform_later(self, method, *args)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ module ActiveResourceable::Governable
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+
6
+ attr_accessor :access_object
7
+
8
+ # scope :editable_for, ->(user) {
9
+ # where(false)
10
+ # }
11
+ #
12
+ # scope :readable_for, ->(user) {
13
+ # editable_for user
14
+ # }
15
+ #
16
+ # scope :deletable_for, ->(user) {
17
+ # editable_for user
18
+ # }
19
+
20
+ end
21
+
22
+ def accessable_fields
23
+ raise NotImplementedError
24
+ end
25
+
26
+ end
@@ -0,0 +1,66 @@
1
+ class ActiveResourceable::Sessionable < Module
2
+ extend ActiveSupport::Concern
3
+
4
+ def initialize(attrs)
5
+ @session_attrs = attrs
6
+ end
7
+
8
+ def included(base)
9
+ session_attrs = @session_attrs
10
+
11
+ base.class_eval do
12
+
13
+ attr_accessor :session
14
+
15
+ define_method(:session_attrs) do
16
+ session_attrs
17
+ end
18
+
19
+ def delete_session *attrs
20
+ attrs = session_attrs if attrs.empty?
21
+ attrs.each do |name, opt|
22
+ send(:"delete_#{name}")
23
+ end
24
+ end
25
+
26
+ session_attrs.each do |name, opt|
27
+
28
+ define_method(:"session_name_for_#{name}") do
29
+ "#{self.class.name.tableize}_#{name}"
30
+ end
31
+
32
+ define_method(:"modified_at_session_name_for_#{name}") do
33
+ "#{self.class.name.tableize}_#{name}_modified_at"
34
+ end
35
+
36
+ define_method(name) do
37
+ raise "Session is not set" if self.session.nil?
38
+ is_expired = send(:"is_#{name}_expired?")
39
+ is_expired ? nil : self.session[send(:"session_name_for_#{name}")]
40
+ end
41
+
42
+ define_method(:"#{name}=") do |value|
43
+ raise "Session is not set" if self.session.nil?
44
+ self.session[send(:"session_name_for_#{name}")] = value
45
+ self.session[send(:"modified_at_session_name_for_#{name}")] = Time.now
46
+ end
47
+
48
+ define_method(:"delete_#{name}") do
49
+ raise "Session is not set" if self.session.nil?
50
+ self.session.delete send(:"modified_at_session_name_for_#{name}")
51
+ self.session.delete send(:"session_name_for_#{name}")
52
+ end
53
+
54
+ define_method(:"is_#{name}_expired?") do
55
+ raise "Session is not set" if self.session.nil?
56
+ modified_at = self.session[send(:"modified_at_session_name_for_#{name}")]
57
+ (not opt[:expire_after].nil? and not modified_at.nil?) ? modified_at.to_datetime + opt[:expire_after] < Time.now : false
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,40 @@
1
+ require "rails/engine"
2
+ require "pagy"
3
+ require "procore-sift"
4
+
5
+ module ActiveResourceable
6
+ class Engine < ::Rails::Engine
7
+ isolate_namespace ActiveResourceable
8
+ engine_name "active_resourceable"
9
+ config.eager_load_namespaces << ActiveResourceable
10
+ config.active_resourceable = ActiveSupport::OrderedOptions.new
11
+ config.autoload_once_paths = %W(
12
+ #{root}/app/channels
13
+ #{root}/app/controllers
14
+ #{root}/app/controllers/concerns
15
+ #{root}/app/helpers
16
+ #{root}/app/models
17
+ #{root}/app/models/concerns
18
+ #{root}/app/jobs
19
+ )
20
+
21
+ initializer "active_resourceable.resourceable", before: :load_config_initializers do
22
+ ActiveSupport.on_load(:action_controller_base) do
23
+ default_form_builder ActiveResourceable::AppFormBuilder
24
+ include Pagy::Backend
25
+ include Sift
26
+ include ActiveResourceable::Resourceable
27
+ end
28
+ end
29
+
30
+ initializer "active_resourceable.models_concerns" do
31
+ ActiveSupport.on_load(:active_record) do
32
+ include ActiveResourceable::Governable
33
+ include ActiveResourceable::Asyncable
34
+ scope :unpaginate, ->() {
35
+ offset(nil).limit(nil)
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveResourceable
2
+ VERSION = "0.0.0".freeze
3
+ end
@@ -0,0 +1,5 @@
1
+ require "active_resourceable/engine"
2
+
3
+ module ActiveResourceable
4
+ extend ActiveSupport::Autoload
5
+ end
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_resourceable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Abdullah Dahmash
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-02-15 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: 7.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 7.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: actionpack
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 7.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 7.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: activejob
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 7.0.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 7.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: railties
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 7.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 7.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: procore-sift
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 0.16.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.16.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: pagy
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 6.0.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 6.0.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: activejob-uniqueness
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 0.2.4
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 0.2.4
111
+ description: A tiny framework built on top of Rails in order to help developers focus
112
+ on writing important business logic. It should be used with hotwired
113
+ email:
114
+ - a@and.sa
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - MIT-LICENSE
120
+ - README.md
121
+ - Rakefile
122
+ - app/controllers/concerns/active_resourceable/resourceable.rb
123
+ - app/helpers/active_resourceable/app_form_builder.rb
124
+ - app/jobs/active_resourceable/active_record_instance_method_job.rb
125
+ - app/jobs/active_resourceable/active_record_instance_method_job_unique_until_executing_job.rb
126
+ - app/models/concerns/active_resourceable/asyncable.rb
127
+ - app/models/concerns/active_resourceable/governable.rb
128
+ - app/models/concerns/active_resourceable/sessionable.rb
129
+ - lib/active_resourceable.rb
130
+ - lib/active_resourceable/engine.rb
131
+ - lib/active_resourceable/version.rb
132
+ homepage: https://github.com/AbdullahDahmash/active_resourceable
133
+ licenses:
134
+ - MIT
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: 2.3.0
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubygems_version: 3.3.5
152
+ signing_key:
153
+ specification_version: 4
154
+ summary: Active Resourceable
155
+ test_files: []