api_maker 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +476 -0
- data/Rakefile +27 -0
- data/app/channels/api_maker/subscriptions_channel.rb +80 -0
- data/app/controllers/api_maker/base_controller.rb +32 -0
- data/app/controllers/api_maker/commands_controller.rb +26 -0
- data/app/controllers/api_maker/devise_controller.rb +60 -0
- data/app/controllers/api_maker/session_statuses_controller.rb +33 -0
- data/app/services/api_maker/application_service.rb +7 -0
- data/app/services/api_maker/collection_command_service.rb +24 -0
- data/app/services/api_maker/command_response.rb +67 -0
- data/app/services/api_maker/command_service.rb +31 -0
- data/app/services/api_maker/create_command.rb +62 -0
- data/app/services/api_maker/create_command_service.rb +18 -0
- data/app/services/api_maker/destroy_command.rb +39 -0
- data/app/services/api_maker/destroy_command_service.rb +22 -0
- data/app/services/api_maker/generate_react_native_api_service.rb +61 -0
- data/app/services/api_maker/index_command.rb +96 -0
- data/app/services/api_maker/index_command_service.rb +22 -0
- data/app/services/api_maker/js_method_namer_service.rb +11 -0
- data/app/services/api_maker/member_command_service.rb +25 -0
- data/app/services/api_maker/model_content_generator_service.rb +108 -0
- data/app/services/api_maker/models_finder_service.rb +22 -0
- data/app/services/api_maker/models_generator_service.rb +104 -0
- data/app/services/api_maker/update_command.rb +43 -0
- data/app/services/api_maker/update_command_service.rb +21 -0
- data/app/services/api_maker/valid_command.rb +35 -0
- data/app/services/api_maker/valid_command_service.rb +21 -0
- data/app/views/api_maker/_data.html.erb +15 -0
- data/config/rails_best_practices.yml +55 -0
- data/config/routes.rb +7 -0
- data/lib/api_maker.rb +36 -0
- data/lib/api_maker/ability.rb +39 -0
- data/lib/api_maker/ability_loader.rb +21 -0
- data/lib/api_maker/action_controller_base_extensions.rb +5 -0
- data/lib/api_maker/base_command.rb +81 -0
- data/lib/api_maker/base_resource.rb +78 -0
- data/lib/api_maker/collection_serializer.rb +69 -0
- data/lib/api_maker/command_spec_helper.rb +57 -0
- data/lib/api_maker/configuration.rb +34 -0
- data/lib/api_maker/engine.rb +5 -0
- data/lib/api_maker/individual_command.rb +37 -0
- data/lib/api_maker/javascript/api.js +92 -0
- data/lib/api_maker/javascript/base-model.js +543 -0
- data/lib/api_maker/javascript/bootstrap/attribute-row.jsx +16 -0
- data/lib/api_maker/javascript/bootstrap/attribute-rows.jsx +47 -0
- data/lib/api_maker/javascript/bootstrap/card.jsx +79 -0
- data/lib/api_maker/javascript/bootstrap/checkbox.jsx +127 -0
- data/lib/api_maker/javascript/bootstrap/checkboxes.jsx +105 -0
- data/lib/api_maker/javascript/bootstrap/live-table.jsx +168 -0
- data/lib/api_maker/javascript/bootstrap/money-input.jsx +136 -0
- data/lib/api_maker/javascript/bootstrap/radio-buttons.jsx +80 -0
- data/lib/api_maker/javascript/bootstrap/select.jsx +168 -0
- data/lib/api_maker/javascript/bootstrap/string-input.jsx +203 -0
- data/lib/api_maker/javascript/cable-connection-pool.js +169 -0
- data/lib/api_maker/javascript/cable-subscription-pool.js +111 -0
- data/lib/api_maker/javascript/cable-subscription.js +33 -0
- data/lib/api_maker/javascript/collection.js +186 -0
- data/lib/api_maker/javascript/commands-pool.js +123 -0
- data/lib/api_maker/javascript/custom-error.js +14 -0
- data/lib/api_maker/javascript/deserializer.js +35 -0
- data/lib/api_maker/javascript/devise.js.erb +113 -0
- data/lib/api_maker/javascript/error-logger.js +119 -0
- data/lib/api_maker/javascript/event-connection.jsx +24 -0
- data/lib/api_maker/javascript/event-created.jsx +26 -0
- data/lib/api_maker/javascript/event-destroyed.jsx +26 -0
- data/lib/api_maker/javascript/event-emitter-listener.jsx +32 -0
- data/lib/api_maker/javascript/event-listener.jsx +41 -0
- data/lib/api_maker/javascript/event-updated.jsx +26 -0
- data/lib/api_maker/javascript/form-data-to-object.js +70 -0
- data/lib/api_maker/javascript/included.js +39 -0
- data/lib/api_maker/javascript/key-value-store.js +47 -0
- data/lib/api_maker/javascript/logger.js +23 -0
- data/lib/api_maker/javascript/model-name.js +21 -0
- data/lib/api_maker/javascript/model-template.js.erb +110 -0
- data/lib/api_maker/javascript/models-response-reader.js +43 -0
- data/lib/api_maker/javascript/paginate.jsx +128 -0
- data/lib/api_maker/javascript/params.js +68 -0
- data/lib/api_maker/javascript/resource-route.jsx +75 -0
- data/lib/api_maker/javascript/resource-routes.jsx +36 -0
- data/lib/api_maker/javascript/result.js +25 -0
- data/lib/api_maker/javascript/session-status-updater.js +113 -0
- data/lib/api_maker/javascript/sort-link.jsx +88 -0
- data/lib/api_maker/javascript/updated-attribute.jsx +60 -0
- data/lib/api_maker/loader.rb +14 -0
- data/lib/api_maker/memory_storage.rb +65 -0
- data/lib/api_maker/model_extensions.rb +96 -0
- data/lib/api_maker/permitted_params_argument.rb +12 -0
- data/lib/api_maker/preloader.rb +91 -0
- data/lib/api_maker/preloader_belongs_to.rb +58 -0
- data/lib/api_maker/preloader_has_many.rb +69 -0
- data/lib/api_maker/preloader_has_one.rb +70 -0
- data/lib/api_maker/preloader_through.rb +101 -0
- data/lib/api_maker/railtie.rb +14 -0
- data/lib/api_maker/relationship_includer.rb +42 -0
- data/lib/api_maker/resource_routing.rb +8 -0
- data/lib/api_maker/result_parser.rb +50 -0
- data/lib/api_maker/serializer.rb +86 -0
- data/lib/api_maker/spec_helper.rb +100 -0
- data/lib/api_maker/version.rb +3 -0
- data/lib/tasks/api_maker_tasks.rake +5 -0
- metadata +581 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
class ApiMaker::UpdateCommand < ApiMaker::BaseCommand
|
2
|
+
attr_reader :command, :model, :params, :serializer
|
3
|
+
|
4
|
+
def execute!
|
5
|
+
each_command do |command|
|
6
|
+
@command = command
|
7
|
+
@model = command.model
|
8
|
+
@params = command.args || {}
|
9
|
+
@serializer = serialized_resource(model)
|
10
|
+
|
11
|
+
if command.model.update(sanitize_parameters)
|
12
|
+
success_response
|
13
|
+
else
|
14
|
+
failure_response
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
ServicePattern::Response.new(success: true)
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_response
|
22
|
+
command.fail(
|
23
|
+
model: serializer.result,
|
24
|
+
success: false,
|
25
|
+
errors: model.errors.full_messages
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def sanitize_parameters
|
30
|
+
serializer.resource_instance.permitted_params(ApiMaker::PermittedParamsArgument.new(command: command, model: model))
|
31
|
+
end
|
32
|
+
|
33
|
+
def serialized_resource(model)
|
34
|
+
ApiMaker::Serializer.new(ability: current_ability, args: api_maker_args, model: model)
|
35
|
+
end
|
36
|
+
|
37
|
+
def success_response
|
38
|
+
command.result(
|
39
|
+
model: serializer.result,
|
40
|
+
success: true
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class ApiMaker::UpdateCommandService < ApiMaker::CommandService
|
2
|
+
def execute
|
3
|
+
ApiMaker::UpdateCommand.execute_in_thread!(
|
4
|
+
ability: ability,
|
5
|
+
args: args,
|
6
|
+
collection: collection,
|
7
|
+
commands: commands,
|
8
|
+
command_response: command_response,
|
9
|
+
controller: controller
|
10
|
+
)
|
11
|
+
ServicePattern::Response.new(success: true)
|
12
|
+
end
|
13
|
+
|
14
|
+
def collection
|
15
|
+
@collection ||= model_class.accessible_by(@ability, :update).where(model_class.primary_key => ids)
|
16
|
+
end
|
17
|
+
|
18
|
+
def ids
|
19
|
+
@commands.values.map { |command| command.fetch("primary_key") }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class ApiMaker::ValidCommand < ApiMaker::BaseCommand
|
2
|
+
attr_reader :command, :model, :params, :serializer
|
3
|
+
|
4
|
+
def execute!
|
5
|
+
each_command do |command|
|
6
|
+
@command = command
|
7
|
+
@params = command.args || {}
|
8
|
+
|
9
|
+
if command.model_id.present?
|
10
|
+
model = resource_instance_class.find(command.model_id)
|
11
|
+
else
|
12
|
+
model = resource_instance_class.new
|
13
|
+
end
|
14
|
+
|
15
|
+
serializer = serialized_resource(model)
|
16
|
+
model.assign_attributes(sanitize_parameters(serializer))
|
17
|
+
|
18
|
+
command.result(valid: model.valid?, errors: model.errors.full_messages)
|
19
|
+
end
|
20
|
+
|
21
|
+
ServicePattern::Response.new(success: true)
|
22
|
+
end
|
23
|
+
|
24
|
+
def resource_instance_class
|
25
|
+
collection.klass
|
26
|
+
end
|
27
|
+
|
28
|
+
def sanitize_parameters(serializer)
|
29
|
+
serializer.resource_instance.permitted_params(ApiMaker::PermittedParamsArgument.new(command: command, model: serializer.model))
|
30
|
+
end
|
31
|
+
|
32
|
+
def serialized_resource(model)
|
33
|
+
ApiMaker::Serializer.new(ability: current_ability, args: api_maker_args, model: model)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class ApiMaker::ValidCommandService < ApiMaker::CommandService
|
2
|
+
def execute
|
3
|
+
ApiMaker::ValidCommand.execute_in_thread!(
|
4
|
+
ability: ability,
|
5
|
+
args: args,
|
6
|
+
collection: collection,
|
7
|
+
commands: commands,
|
8
|
+
command_response: command_response,
|
9
|
+
controller: controller
|
10
|
+
)
|
11
|
+
ServicePattern::Response.new(success: true)
|
12
|
+
end
|
13
|
+
|
14
|
+
def collection
|
15
|
+
@collection ||= model_class.accessible_by(@ability, :valid).where(model_class.primary_key => ids)
|
16
|
+
end
|
17
|
+
|
18
|
+
def ids
|
19
|
+
@commands.values.map { |command| command.fetch("primary_key") }
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<div class="api-maker-data"<%
|
2
|
+
|
3
|
+
Devise.mappings.each do |scope|
|
4
|
+
model = __send__("current_#{scope[0]}")
|
5
|
+
next unless model
|
6
|
+
|
7
|
+
resource_class = ApiMaker::Serializer.resource_for(model.class)
|
8
|
+
next unless resource_class
|
9
|
+
|
10
|
+
serializer = ApiMaker::Serializer.new(ability: current_ability, args: api_maker_args, model: model) if model
|
11
|
+
|
12
|
+
%> data-current-<%= scope[0].to_s.dasherize %>="<%= model ? serializer.to_json : null %>"<%
|
13
|
+
end
|
14
|
+
|
15
|
+
%>></div>
|
@@ -0,0 +1,55 @@
|
|
1
|
+
AddModelVirtualAttributeCheck: { }
|
2
|
+
AlwaysAddDbIndexCheck: { }
|
3
|
+
#CheckSaveReturnValueCheck: { }
|
4
|
+
#CheckDestroyReturnValueCheck: { }
|
5
|
+
DefaultScopeIsEvilCheck: { }
|
6
|
+
DryBundlerInCapistranoCheck: { }
|
7
|
+
#HashSyntaxCheck: { }
|
8
|
+
IsolateSeedDataCheck: { }
|
9
|
+
KeepFindersOnTheirOwnModelCheck: { }
|
10
|
+
LawOfDemeterCheck: { }
|
11
|
+
#LongLineCheck: { max_line_length: 80 }
|
12
|
+
MoveCodeIntoControllerCheck: { }
|
13
|
+
MoveCodeIntoHelperCheck: { array_count: 3 }
|
14
|
+
MoveCodeIntoModelCheck: { use_count: 2 }
|
15
|
+
MoveFinderToNamedScopeCheck: { }
|
16
|
+
#MoveModelLogicIntoModelCheck: { use_count: 4 }
|
17
|
+
NeedlessDeepNestingCheck: { nested_count: 2 }
|
18
|
+
NotRescueExceptionCheck: { }
|
19
|
+
NotUseDefaultRouteCheck: { }
|
20
|
+
NotUseTimeAgoInWordsCheck: { }
|
21
|
+
OveruseRouteCustomizationsCheck: { customize_count: 3 }
|
22
|
+
ProtectMassAssignmentCheck: { }
|
23
|
+
RemoveEmptyHelpersCheck: { }
|
24
|
+
#RemoveTabCheck: { }
|
25
|
+
RemoveTrailingWhitespaceCheck: { }
|
26
|
+
RemoveUnusedMethodsInControllersCheck: {
|
27
|
+
except_methods: [
|
28
|
+
"ApiMaker::BaseController#current_ability",
|
29
|
+
"ApiMaker::CommandsController#create",
|
30
|
+
"ApiMaker::DeviseController#do_sign_in",
|
31
|
+
"ApiMaker::DeviseController#do_sign_out",
|
32
|
+
"ApiMaker::MemberActionsController#create",
|
33
|
+
"ApiMaker::ModelController#index",
|
34
|
+
"ApiMaker::ModelController#show",
|
35
|
+
"ApiMaker::ModelController#create",
|
36
|
+
"ApiMaker::ModelController#edit",
|
37
|
+
"ApiMaker::ModelController#validate"
|
38
|
+
]
|
39
|
+
}
|
40
|
+
RemoveUnusedMethodsInHelpersCheck: { except_methods: [] }
|
41
|
+
RemoveUnusedMethodsInModelsCheck: { except_methods: [] }
|
42
|
+
ReplaceComplexCreationWithFactoryMethodCheck: { attribute_assignment_count: 2 }
|
43
|
+
ReplaceInstanceVariableWithLocalVariableCheck: { }
|
44
|
+
RestrictAutoGeneratedRoutesCheck: { }
|
45
|
+
SimplifyRenderInControllersCheck: { }
|
46
|
+
SimplifyRenderInViewsCheck: { }
|
47
|
+
#UseBeforeFilterCheck: { customize_count: 2 }
|
48
|
+
UseModelAssociationCheck: { }
|
49
|
+
UseMultipartAlternativeAsContentTypeOfEmailCheck: { }
|
50
|
+
#UseParenthesesInMethodDefCheck: { }
|
51
|
+
UseObserverCheck: { }
|
52
|
+
UseQueryAttributeCheck: { }
|
53
|
+
UseSayWithTimeInMigrationsCheck: { }
|
54
|
+
UseScopeAccessCheck: { }
|
55
|
+
UseTurboSprocketsRails3Check: { }
|
data/config/routes.rb
ADDED
data/lib/api_maker.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "api_maker/engine"
|
2
|
+
|
3
|
+
require "active_record_query_fixer"
|
4
|
+
require "ransack"
|
5
|
+
require "service_pattern"
|
6
|
+
|
7
|
+
require_relative "api_maker/action_controller_base_extensions"
|
8
|
+
|
9
|
+
module ApiMaker
|
10
|
+
dir = "#{__dir__}/api_maker"
|
11
|
+
|
12
|
+
autoload :Ability, "#{dir}/ability"
|
13
|
+
autoload :AbilityLoader, "#{dir}/ability_loader"
|
14
|
+
autoload :BaseCommand, "#{dir}/base_command"
|
15
|
+
autoload :BaseResource, "#{dir}/base_resource"
|
16
|
+
autoload :CollectionSerializer, "#{dir}/collection_serializer"
|
17
|
+
autoload :CommandSpecHelper, "#{dir}/command_spec_helper"
|
18
|
+
autoload :Configuration, "#{dir}/configuration"
|
19
|
+
autoload :IndividualCommand, "#{dir}/individual_command"
|
20
|
+
autoload :Loader, "#{dir}/loader"
|
21
|
+
autoload :MemoryStorage, "#{dir}/memory_storage"
|
22
|
+
autoload :ModelExtensions, "#{dir}/model_extensions"
|
23
|
+
autoload :PermittedParamsArgument, "#{dir}/permitted_params_argument"
|
24
|
+
autoload :Preloader, "#{dir}/preloader"
|
25
|
+
autoload :PreloaderBelongsTo, "#{dir}/preloader_belongs_to"
|
26
|
+
autoload :PreloaderHasMany, "#{dir}/preloader_has_many"
|
27
|
+
autoload :PreloaderHasOne, "#{dir}/preloader_has_one"
|
28
|
+
autoload :PreloaderThrough, "#{dir}/preloader_through"
|
29
|
+
autoload :RelationshipIncluder, "#{dir}/relationship_includer"
|
30
|
+
autoload :ResourceRouting, "#{dir}/resource_routing"
|
31
|
+
autoload :ResultParser, "#{dir}/result_parser"
|
32
|
+
autoload :Serializer, "#{dir}/serializer"
|
33
|
+
autoload :SpecHelper, "#{dir}/spec_helper"
|
34
|
+
end
|
35
|
+
|
36
|
+
require_relative "api_maker/railtie"
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class ApiMaker::Ability
|
2
|
+
include CanCan::Ability
|
3
|
+
|
4
|
+
attr_reader :loader
|
5
|
+
|
6
|
+
def initialize(args: nil)
|
7
|
+
@args = args
|
8
|
+
@loader = ApiMaker::AbilityLoader.new(ability: self, args: args)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Override methods from CanCan::Ability to first load abilities from the given resource
|
12
|
+
def can?(*args)
|
13
|
+
subject = args.second
|
14
|
+
load_abilities(subject)
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def model_adapter(*args)
|
19
|
+
subject = args.first
|
20
|
+
load_abilities(subject)
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def load_abilities(subject)
|
25
|
+
return unless active_record?(subject)
|
26
|
+
|
27
|
+
if subject.class == Class
|
28
|
+
loader.load_model_class(subject)
|
29
|
+
elsif subject.class != Class
|
30
|
+
loader.load_model_class(subject.class)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def active_record?(subject)
|
35
|
+
return subject < ActiveRecord::Base if subject.class == Class
|
36
|
+
|
37
|
+
subject.is_a?(ActiveRecord::Base)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class ApiMaker::AbilityLoader
|
2
|
+
def initialize(ability:, args:)
|
3
|
+
@ability = ability
|
4
|
+
@args = args
|
5
|
+
@loaded_model_names = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def load_model_class(model_class)
|
9
|
+
return if @loaded_model_names.key?(model_class.name)
|
10
|
+
|
11
|
+
resource = ApiMaker::MemoryStorage.current.resource_for_model(model_class)
|
12
|
+
load_resource(resource)
|
13
|
+
end
|
14
|
+
|
15
|
+
def load_resource(resource)
|
16
|
+
return if @loaded_model_names.key?(resource.model_class_name)
|
17
|
+
|
18
|
+
resource.new(ability: @ability, args: @args, model: nil).abilities
|
19
|
+
@loaded_model_names[resource.model_class_name] = true
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
class ApiMaker::BaseCommand
|
2
|
+
attr_reader :api_maker_args, :commands, :command_response, :collection, :controller, :current_ability
|
3
|
+
|
4
|
+
# Returns true if the gem "goldiloader" is present in the app
|
5
|
+
def self.goldiloader?
|
6
|
+
@goldiloader = Gem::Specification.find_all_by_name("goldiloader").any? if @goldiloader.nil?
|
7
|
+
@goldiloader
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(ability:, args:, collection:, commands:, command_response:, controller:)
|
11
|
+
@api_maker_args = args
|
12
|
+
@current_ability = ability
|
13
|
+
@collection = collection
|
14
|
+
@commands = commands
|
15
|
+
@command_response = command_response
|
16
|
+
@controller = controller
|
17
|
+
|
18
|
+
# Make it possible to do custom preloads (useful in threadded mode that doesnt support Goldiloader)
|
19
|
+
@collection = custom_collection(@collection) if respond_to?(:custom_collection)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.execute_in_thread!(**args)
|
23
|
+
args.fetch(:command_response).with_thread do
|
24
|
+
new(**args).execute!
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def each_command(args = {}, &blk)
|
29
|
+
if args[:threadded]
|
30
|
+
# Goldiloader doesn't work with threads (loads all relationships for each thread)
|
31
|
+
@collection = @collection.auto_include(false) if ApiMaker::BaseCommand.goldiloader?
|
32
|
+
|
33
|
+
# Load relationship before commands so each command doesn't query on its own
|
34
|
+
@collection.load
|
35
|
+
end
|
36
|
+
|
37
|
+
@commands.each do |command_id, command_data|
|
38
|
+
if args[:threadded]
|
39
|
+
command_response.with_thread do
|
40
|
+
run_command(command_id, command_data, &blk)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
run_command(command_id, command_data, &blk)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
delegate :result_for_command, to: :command_response
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def run_command(command_id, command_data)
|
53
|
+
command = ApiMaker::IndividualCommand.new(
|
54
|
+
args: command_data[:args],
|
55
|
+
collection: @collection,
|
56
|
+
command: self,
|
57
|
+
id: command_id,
|
58
|
+
primary_key: command_data[:primary_key],
|
59
|
+
response: command_response
|
60
|
+
)
|
61
|
+
|
62
|
+
begin
|
63
|
+
yield command
|
64
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
65
|
+
command.error(success: false, errors: [command_error_message(e)])
|
66
|
+
|
67
|
+
Rails.logger.error e.message
|
68
|
+
Rails.logger.error e.backtrace.join("\n")
|
69
|
+
|
70
|
+
ApiMaker::Configuration.current.report_error(controller: controller, error: e)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def command_error_message(error)
|
75
|
+
if Rails.application.config.consider_all_requests_local
|
76
|
+
"#{error.class.name}: #{error.message}"
|
77
|
+
else
|
78
|
+
"Internal server error"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class ApiMaker::BaseResource
|
2
|
+
attr_reader :ability, :args, :model
|
3
|
+
|
4
|
+
delegate :can, to: :ability
|
5
|
+
|
6
|
+
CRUD = [:create, :read, :update, :destroy].freeze
|
7
|
+
|
8
|
+
def self.attributes(*attributes, **args)
|
9
|
+
attributes.each do |attribute|
|
10
|
+
ApiMaker::MemoryStorage.current.add(self, :attributes, attribute, args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self._attributes
|
15
|
+
ApiMaker::MemoryStorage.current.storage_for(self, :attributes)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.collection_commands(*list)
|
19
|
+
list.each do |collection_command|
|
20
|
+
ApiMaker::MemoryStorage.current.add(self, :collection_commands, collection_command)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.member_commands(*list)
|
25
|
+
list.each do |member_command|
|
26
|
+
ApiMaker::MemoryStorage.current.add(self, :member_commands, member_command)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.model_class=(klass)
|
31
|
+
# Set the name to avoid reloading issues with Rails
|
32
|
+
@model_class_name ||= klass.name
|
33
|
+
ApiMaker::MemoryStorage.current.model_class_for(resource: self, klass: klass)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.model_class
|
37
|
+
# Use the name to constantize to avoid reloading issues with Rails
|
38
|
+
model_class_name.constantize
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.model_class_name
|
42
|
+
@model_class_name ||= name.gsub(/Resource$/, "").gsub(/^Resources::/, "")
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.relationships(*relationships)
|
46
|
+
relationships.each do |relationship|
|
47
|
+
ApiMaker::MemoryStorage.current.add(self, :relationships, relationship)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self._relationships
|
52
|
+
ApiMaker::MemoryStorage.current.storage_for(self, :relationships)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.collection_name
|
56
|
+
@collection_name ||= plural_name.underscore.dasherize
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.default_select
|
60
|
+
_attributes.select do |_attribute_name, args|
|
61
|
+
!args.fetch(:args).key?(:selected_by_default) || args.fetch(:args).fetch(:selected_by_default)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.plural_name
|
66
|
+
@plural_name ||= short_name.pluralize
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.short_name
|
70
|
+
@short_name ||= name.match(/\AResources::(.+)Resource\Z/)[1]
|
71
|
+
end
|
72
|
+
|
73
|
+
def initialize(ability: nil, args: {}, model:)
|
74
|
+
@ability = ability
|
75
|
+
@args = args
|
76
|
+
@model = model
|
77
|
+
end
|
78
|
+
end
|