api_maker 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/app/api_maker/api_helpers/api_maker_helpers.rb +5 -0
  3. data/app/api_maker/services/can_can/load_abilities.rb +30 -0
  4. data/app/api_maker/services/devise/sign_in.rb +64 -0
  5. data/app/api_maker/services/devise/sign_out.rb +9 -0
  6. data/app/api_maker/services/models/find_or_create_by.rb +18 -0
  7. data/app/channels/api_maker/subscriptions_channel.rb +33 -2
  8. data/app/controllers/api_maker/base_controller.rb +7 -3
  9. data/app/controllers/api_maker/commands_controller.rb +26 -4
  10. data/app/controllers/api_maker/session_statuses_controller.rb +1 -1
  11. data/app/services/api_maker/abilities_loader.rb +104 -0
  12. data/app/services/api_maker/application_service.rb +2 -1
  13. data/app/services/api_maker/base_command.rb +248 -0
  14. data/app/services/api_maker/collection_command_service.rb +29 -15
  15. data/app/services/api_maker/collection_loader.rb +124 -0
  16. data/app/services/api_maker/command_failed_error.rb +3 -0
  17. data/app/services/api_maker/command_response.rb +17 -6
  18. data/app/services/api_maker/command_service.rb +3 -3
  19. data/app/services/api_maker/create_command.rb +11 -26
  20. data/app/services/api_maker/create_command_service.rb +3 -3
  21. data/app/services/api_maker/database_type.rb +9 -0
  22. data/app/services/api_maker/deep_merge_params.rb +26 -0
  23. data/app/services/api_maker/deserializer.rb +35 -0
  24. data/app/services/api_maker/destroy_command.rb +15 -21
  25. data/app/services/api_maker/destroy_command_service.rb +3 -3
  26. data/app/services/api_maker/generate_react_native_api_service.rb +3 -19
  27. data/app/services/api_maker/include_helpers.rb +17 -0
  28. data/app/services/api_maker/index_command.rb +8 -88
  29. data/app/services/api_maker/index_command_service.rb +5 -5
  30. data/app/services/api_maker/js_method_namer_service.rb +1 -1
  31. data/app/services/api_maker/locals_from_controller.rb +14 -0
  32. data/app/services/api_maker/member_command_service.rb +15 -13
  33. data/app/services/api_maker/model_classes_java_script_generator_service.rb +37 -0
  34. data/app/services/api_maker/model_content_generator_service.rb +17 -21
  35. data/app/services/api_maker/models/save.rb +29 -0
  36. data/app/services/api_maker/models_finder_service.rb +6 -2
  37. data/app/services/api_maker/models_generator_service.rb +6 -43
  38. data/app/services/api_maker/move_components_to_routes.rb +50 -0
  39. data/app/services/api_maker/primary_id_for_model.rb +6 -0
  40. data/app/services/api_maker/reset_indexed_db_service.rb +36 -0
  41. data/app/services/api_maker/routes_file_reloader.rb +20 -0
  42. data/app/services/api_maker/select_columns_on_collection.rb +78 -0
  43. data/app/services/api_maker/select_parser.rb +32 -0
  44. data/app/services/api_maker/service_command.rb +27 -0
  45. data/app/services/api_maker/service_command_service.rb +14 -0
  46. data/app/services/api_maker/simple_model_errors.rb +52 -0
  47. data/app/services/api_maker/update_command.rb +8 -24
  48. data/app/services/api_maker/update_command_service.rb +3 -3
  49. data/app/services/api_maker/valid_command.rb +4 -13
  50. data/app/services/api_maker/valid_command_service.rb +3 -3
  51. data/app/services/api_maker/validation_errors_generator_service.rb +146 -0
  52. data/app/views/api_maker/_data.html.erb +17 -11
  53. data/config/routes.rb +0 -2
  54. data/lib/api_maker/ability.rb +22 -7
  55. data/lib/api_maker/ability_loader.rb +9 -6
  56. data/lib/api_maker/base_collection_instance.rb +15 -0
  57. data/lib/api_maker/base_resource.rb +135 -9
  58. data/lib/api_maker/base_service.rb +14 -0
  59. data/lib/api_maker/collection_serializer.rb +95 -34
  60. data/lib/api_maker/command_spec_helper.rb +41 -11
  61. data/lib/api_maker/configuration.rb +31 -4
  62. data/lib/api_maker/expect_to_able_to_helper.rb +31 -0
  63. data/lib/api_maker/individual_command.rb +24 -9
  64. data/lib/api_maker/javascript/model-template.js.erb +39 -25
  65. data/lib/api_maker/javascript/models.js.erb +6 -0
  66. data/lib/api_maker/loader.rb +1 -1
  67. data/lib/api_maker/memory_storage.rb +1 -1
  68. data/lib/api_maker/model_extensions.rb +34 -18
  69. data/lib/api_maker/permitted_params_argument.rb +5 -1
  70. data/lib/api_maker/preloader.rb +71 -32
  71. data/lib/api_maker/preloader_base.rb +108 -0
  72. data/lib/api_maker/preloader_belongs_to.rb +34 -33
  73. data/lib/api_maker/preloader_has_many.rb +45 -39
  74. data/lib/api_maker/preloader_has_one.rb +30 -47
  75. data/lib/api_maker/railtie.rb +3 -11
  76. data/lib/api_maker/relationship_preloader.rb +42 -0
  77. data/lib/api_maker/resource_routing.rb +18 -4
  78. data/lib/api_maker/result_parser.rb +34 -20
  79. data/lib/api_maker/serializer.rb +53 -22
  80. data/lib/api_maker/spec_helper/browser_logs.rb +14 -0
  81. data/lib/api_maker/spec_helper/execute_collection_command.rb +46 -0
  82. data/lib/api_maker/spec_helper/execute_member_command.rb +52 -0
  83. data/lib/api_maker/spec_helper/expect_no_browser_errors.rb +18 -0
  84. data/lib/api_maker/spec_helper/wait_for_expect.rb +20 -0
  85. data/lib/api_maker/spec_helper/wait_for_flash_message.rb +21 -0
  86. data/lib/api_maker/spec_helper.rb +112 -48
  87. data/lib/api_maker/version.rb +1 -1
  88. data/lib/api_maker.rb +7 -3
  89. metadata +108 -89
  90. data/README.md +0 -476
  91. data/app/controllers/api_maker/devise_controller.rb +0 -60
  92. data/lib/api_maker/base_command.rb +0 -81
  93. data/lib/api_maker/javascript/api.js +0 -92
  94. data/lib/api_maker/javascript/base-model.js +0 -543
  95. data/lib/api_maker/javascript/bootstrap/attribute-row.jsx +0 -16
  96. data/lib/api_maker/javascript/bootstrap/attribute-rows.jsx +0 -47
  97. data/lib/api_maker/javascript/bootstrap/card.jsx +0 -79
  98. data/lib/api_maker/javascript/bootstrap/checkbox.jsx +0 -127
  99. data/lib/api_maker/javascript/bootstrap/checkboxes.jsx +0 -105
  100. data/lib/api_maker/javascript/bootstrap/live-table.jsx +0 -168
  101. data/lib/api_maker/javascript/bootstrap/money-input.jsx +0 -136
  102. data/lib/api_maker/javascript/bootstrap/radio-buttons.jsx +0 -80
  103. data/lib/api_maker/javascript/bootstrap/select.jsx +0 -168
  104. data/lib/api_maker/javascript/bootstrap/string-input.jsx +0 -203
  105. data/lib/api_maker/javascript/cable-connection-pool.js +0 -169
  106. data/lib/api_maker/javascript/cable-subscription-pool.js +0 -111
  107. data/lib/api_maker/javascript/cable-subscription.js +0 -33
  108. data/lib/api_maker/javascript/collection.js +0 -186
  109. data/lib/api_maker/javascript/commands-pool.js +0 -123
  110. data/lib/api_maker/javascript/custom-error.js +0 -14
  111. data/lib/api_maker/javascript/deserializer.js +0 -35
  112. data/lib/api_maker/javascript/devise.js.erb +0 -113
  113. data/lib/api_maker/javascript/error-logger.js +0 -119
  114. data/lib/api_maker/javascript/event-connection.jsx +0 -24
  115. data/lib/api_maker/javascript/event-created.jsx +0 -26
  116. data/lib/api_maker/javascript/event-destroyed.jsx +0 -26
  117. data/lib/api_maker/javascript/event-emitter-listener.jsx +0 -32
  118. data/lib/api_maker/javascript/event-listener.jsx +0 -41
  119. data/lib/api_maker/javascript/event-updated.jsx +0 -26
  120. data/lib/api_maker/javascript/form-data-to-object.js +0 -70
  121. data/lib/api_maker/javascript/included.js +0 -39
  122. data/lib/api_maker/javascript/key-value-store.js +0 -47
  123. data/lib/api_maker/javascript/logger.js +0 -23
  124. data/lib/api_maker/javascript/model-name.js +0 -21
  125. data/lib/api_maker/javascript/models-response-reader.js +0 -43
  126. data/lib/api_maker/javascript/paginate.jsx +0 -128
  127. data/lib/api_maker/javascript/params.js +0 -68
  128. data/lib/api_maker/javascript/resource-route.jsx +0 -75
  129. data/lib/api_maker/javascript/resource-routes.jsx +0 -36
  130. data/lib/api_maker/javascript/result.js +0 -25
  131. data/lib/api_maker/javascript/session-status-updater.js +0 -113
  132. data/lib/api_maker/javascript/sort-link.jsx +0 -88
  133. data/lib/api_maker/javascript/updated-attribute.jsx +0 -60
  134. data/lib/api_maker/preloader_through.rb +0 -101
  135. data/lib/api_maker/relationship_includer.rb +0 -42
@@ -1,113 +0,0 @@
1
- import Devise from "./devise"
2
-
3
- var inflection = require("inflection")
4
- var wakeEvent = require("wake-event")
5
-
6
- export default class ApiMakerSessionStatusUpdater {
7
- static current() {
8
- if (!window.apiMakerSessionStatusUpdater)
9
- window.apiMakerSessionStatusUpdater = new ApiMakerSessionStatusUpdater()
10
-
11
- return window.apiMakerSessionStatusUpdater
12
- }
13
-
14
- constructor(args = {}) {
15
- this.debugging = args.debug || false
16
- this.events = {}
17
- this.timeout = args.timeout || 600000
18
-
19
- this.connectOnlineEvent()
20
- this.connectWakeEvent()
21
- }
22
-
23
- connectOnlineEvent() {
24
- window.addEventListener("online", () => { this.updateSessionStatus() }, false)
25
- }
26
-
27
- connectWakeEvent() {
28
- wakeEvent(() => { this.updateSessionStatus() })
29
- }
30
-
31
- debug(message) {
32
- if (this.debugging)
33
- console.log(`ApiMakerSessionStatusUpdater: ${message}`)
34
- }
35
-
36
- sessionStatus() {
37
- return new Promise(resolve => {
38
- var xhr = new XMLHttpRequest()
39
- xhr.open("POST", "/api_maker/session_statuses", true)
40
- xhr.onload = () => {
41
- var response = JSON.parse(xhr.responseText)
42
- resolve(response)
43
- }
44
- xhr.send()
45
- })
46
- }
47
-
48
- onSignedOut(callback) {
49
- this.addEvent("onSignedOut", callback)
50
- }
51
-
52
- startTimeout() {
53
- this.debug("startTimeout")
54
-
55
- if (this.updateTimeout)
56
- clearTimeout(this.updateTimeout)
57
-
58
- this.updateTimeout = setTimeout(
59
- () => {
60
- this.startTimeout()
61
- this.updateSessionStatus()
62
- },
63
- this.timeout
64
- )
65
- }
66
-
67
- stopTimeout() {
68
- if (this.updateTimeout)
69
- clearTimeout(this.updateTimeout)
70
- }
71
-
72
- updateSessionStatus() {
73
- this.debug("updateSessionStatus")
74
-
75
- this.sessionStatus().then(result => {
76
- this.debug(`Result: ${JSON.stringify(result, null, 2)}`)
77
- this.updateMetaElementsFromResult(result)
78
- this.updateUserSessionsFromResult(result)
79
- })
80
- }
81
-
82
- updateMetaElementsFromResult(result) {
83
- this.debug("updateMetaElementsFromResult")
84
- var csrfTokenElement = document.querySelector("meta[name='csrf-token']")
85
-
86
- if (csrfTokenElement) {
87
- this.debug(`Changing token from "${csrfTokenElement.getAttribute("content")}" to "${result.csrf_token}"`)
88
- csrfTokenElement.setAttribute("content", result.csrf_token)
89
- } else {
90
- this.debug("csrf token element couldn't be found")
91
- }
92
- }
93
-
94
- updateUserSessionsFromResult(result) {
95
- for(var scopeName in result.scopes) {
96
- this.updateUserSessionScopeFromResult(scopeName, result.scopes[scopeName])
97
- }
98
- }
99
-
100
- updateUserSessionScopeFromResult(scopeName, scope) {
101
- var deviseMethodName = `current${inflection.camelize(scopeName)}`
102
- var deviseIsSignedInMethodName = `is${inflection.camelize(scopeName)}SignedIn`
103
- var currentlySignedIn = Devise[deviseIsSignedInMethodName]()
104
- var signedInOnBackend = scope.signed_in
105
-
106
- if (currentlySignedIn && !signedInOnBackend) {
107
- this.debug(`${inflection.camelize(scopeName)} signed in on frontend but not in backend!`)
108
-
109
- Devise.setSignedOut({scope: scopeName})
110
- Devise.callSignOutEvent({scope: scopeName})
111
- }
112
- }
113
- }
@@ -1,88 +0,0 @@
1
- import { Link } from "react-router-dom"
2
- import qs from "qs"
3
- import React from "react"
4
-
5
- const inflection = require("inflection")
6
-
7
- export default class extends React.Component {
8
- constructor(props) {
9
- super(props)
10
-
11
- var searchKey = this.props.query.queryArgs.searchKey
12
- if (!searchKey)
13
- searchKey = "q"
14
-
15
- this.state = {searchKey: searchKey}
16
- }
17
-
18
- attribute() {
19
- return inflection.underscore(this.props.attribute)
20
- }
21
-
22
- href() {
23
- var currentParams = qs.parse(window.location.search.substr(1))
24
-
25
- if (!currentParams[this.state.searchKey])
26
- currentParams[this.state.searchKey] = {}
27
-
28
- currentParams[this.state.searchKey]["s"] = `${this.attribute()} ${this.sortMode()}`
29
-
30
- var newParams = qs.stringify(currentParams)
31
- var newPath = `${location.pathname}?${newParams}`
32
-
33
- return newPath
34
- }
35
-
36
- isSortedByAttribute() {
37
- if (this.props.query.queryArgs.ransack && this.props.query.queryArgs.ransack.s == this.attribute())
38
- return true
39
-
40
- if (this.props.query.queryArgs.ransack && this.props.query.queryArgs.ransack.s == `${this.attribute()} asc`)
41
- return true
42
-
43
- return false
44
- }
45
-
46
- render() {
47
- var LinkComponent = this.linkComponent()
48
- var { attribute, className, linkComponent, query, title, ...other } = this.props
49
-
50
- return (
51
- <LinkComponent {...other} className={this.className()} data-attribute={attribute} data-sort-mode={this.sortMode()} to={this.href()}>
52
- {this.title()}
53
- </LinkComponent>
54
- )
55
- }
56
-
57
- className() {
58
- var classNames = ["component-api-maker-bootstrap-sort-link"]
59
-
60
- if (this.props.className)
61
- classNames.push(this.props.className)
62
-
63
- return classNames.join(" ")
64
- }
65
-
66
- linkComponent() {
67
- if (this.props.linkComponent) {
68
- return this.props.linkComponent
69
- } else {
70
- return Link
71
- }
72
- }
73
-
74
- sortMode() {
75
- if (this.isSortedByAttribute()) {
76
- return "desc"
77
- } else {
78
- return "asc"
79
- }
80
- }
81
-
82
- title() {
83
- if (this.props.title)
84
- return this.props.title
85
-
86
- return this.props.query.modelClass().humanAttributeName(this.props.attribute)
87
- }
88
- }
@@ -1,60 +0,0 @@
1
- import PropTypes from "prop-types"
2
- import PropTypesExact from "prop-types-exact"
3
- import React from "react"
4
-
5
- export default class ApiMakerUpdatedAttribute extends React.Component {
6
- static propTypes = PropTypesExact({
7
- attribute: PropTypes.string,
8
- model: PropTypes.object.isRequired,
9
- onValue: PropTypes.func
10
- })
11
-
12
- constructor(props) {
13
- super(props)
14
- this.state = {
15
- model: this.props.model
16
- }
17
- }
18
-
19
- componentDidMount() {
20
- this.setAttribute()
21
- this.connect()
22
- }
23
-
24
- componentWillUnmount() {
25
- this.connectUpdated.unsubscribe()
26
- }
27
-
28
- connect() {
29
- this.connectUpdated = this.props.model.connectUpdated(args =>
30
- this.setState(
31
- {model: args.model},
32
- () => this.setAttribute()
33
- )
34
- )
35
- }
36
-
37
- setAttribute() {
38
- var newValue
39
-
40
- if (this.props.onValue) {
41
- newValue = this.props.onValue.apply(null, [{model: this.state.model}])
42
- } else {
43
- if (!this.state.model[this.props.attribute])
44
- throw new Error(`No such method: ${this.state.model.modelClassData().name}#${this.props.attribute}()`)
45
-
46
- newValue = this.state.model[this.props.attribute].apply(this.state.model)
47
- }
48
-
49
- this.setState({
50
- value: newValue
51
- })
52
- }
53
-
54
- render() {
55
- if (this.state.value === undefined)
56
- return ""
57
-
58
- return this.state.value
59
- }
60
- }
@@ -1,101 +0,0 @@
1
- class ApiMaker::PreloaderThrough
2
- def initialize(collection:, reflection:)
3
- @collection = collection
4
- @reflection = reflection
5
- end
6
-
7
- def models_query_through_reflection
8
- last_reflection = @reflection.through_reflection.inverse_of
9
-
10
- if last_reflection
11
- table_name = last_reflection.table_name
12
- primary_key = last_reflection.klass.primary_key
13
- else
14
- table_name = @reflection.through_reflection.active_record.model_name.plural
15
- primary_key = @reflection.through_reflection.active_record.primary_key
16
- end
17
-
18
- joins_hash = joins_array_to_hash(joins_for_reflection(@reflection))
19
-
20
- @reflection.klass.joins(joins_hash)
21
- .where(table_name => {primary_key => @collection.map(&:id)})
22
- end
23
-
24
- def joins_for_reflection(current_reflection)
25
- joins = []
26
-
27
- loop do
28
- # Resolve if the through relationship is through multiple other through relationships
29
- current_reflection = resolve_through(current_reflection)
30
-
31
- macro = current_reflection.through_reflection.macro
32
- inverse_name = current_reflection.through_reflection.__send__(:inverse_name)
33
-
34
- if inverse_name
35
- joins << inverse_name
36
- elsif macro == :has_many
37
- joins << current_reflection.through_reflection.name
38
- elsif macro == :belongs_to || macro == :has_one
39
- joins << current_reflection.through_reflection.active_record.model_name.plural.to_sym
40
- else
41
- raise "Unknown class: #{current_reflection.through_reflection.class.name}"
42
- end
43
-
44
- current_reflection = next_reflection_for(current_reflection)
45
-
46
- unless current_reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
47
- joins.append(append_name_for_current_reflection(current_reflection))
48
- break
49
- end
50
- end
51
-
52
- joins
53
- end
54
-
55
- def append_name_for_current_reflection(current_reflection)
56
- singular_name = current_reflection.__send__(:inverse_name)&.to_s || current_reflection.active_record.model_name.param_key
57
- return singular_name.to_sym if @reflection.klass.reflections.key?(singular_name)
58
-
59
- plural_name = singular_name.pluralize
60
- return plural_name.to_sym if @reflection.klass.reflections.key?(plural_name)
61
-
62
- raise "Couldn't find a reflection name #{singular_name} or #{plural_name} on #{@reflection.klass.name}"
63
- end
64
-
65
- def joins_array_to_hash(array)
66
- array = array.clone
67
-
68
- result = {}
69
- work_result = result
70
-
71
- while array.any?
72
- element = array.pop
73
-
74
- if array.length == 1
75
- work_result[element] = array.pop
76
- else
77
- work_result[element] = {}
78
- end
79
-
80
- work_result = work_result[element]
81
- end
82
-
83
- result
84
- end
85
-
86
- def next_reflection_for(current_reflection)
87
- reflection_name = (current_reflection.source_reflection_name || @reflection.name).to_s
88
-
89
- new_reflection = current_reflection.through_reflection.klass.reflections[reflection_name.pluralize]
90
- new_reflection ||= current_reflection.through_reflection.klass.reflections[reflection_name.singularize]
91
-
92
- raise "No such reflection: #{current_reflection.through_reflection.klass.name}##{reflection_name}" unless new_reflection
93
-
94
- new_reflection
95
- end
96
-
97
- def resolve_through(current_reflection)
98
- current_reflection = current_reflection.through_reflection while current_reflection.through_reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
99
- current_reflection
100
- end
101
- end
@@ -1,42 +0,0 @@
1
- class ApiMaker::RelationshipIncluder
2
- def self.parse(include_param)
3
- if include_param.nil?
4
- nil
5
- elsif include_param.is_a?(String)
6
- ApiMaker::RelationshipIncluder.parse_string(include_param)
7
- elsif include_param.is_a?(Array)
8
- ApiMaker::RelationshipIncluder.parse_array(include_param)
9
- else
10
- raise "Unexpected parameter given (#{include_param.class.name}): #{include_param}"
11
- end
12
- end
13
-
14
- def self.parse_string(include_param)
15
- splitted = include_param.split(".")
16
- initial = splitted.shift
17
- rest = splitted.join(".")
18
- {initial => rest}
19
- end
20
-
21
- def self.parse_array(include_param)
22
- result = {}
23
- include_param.each do |include_param_i|
24
- parsed = ApiMaker::RelationshipIncluder.parse(include_param_i)
25
- parsed.each do |key, value|
26
- if result.key?(key)
27
- if result[key].is_a?(String)
28
- result[key] = [result[key], value]
29
- elsif result[key].is_a?(Array)
30
- result[key] << value
31
- else
32
- raise "Unknown object: #{result[key].class.name}"
33
- end
34
- else
35
- result[key] = value
36
- end
37
- end
38
- end
39
-
40
- result
41
- end
42
- end