mno-enterprise-core 2.0.0

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.
Files changed (138) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +1 -0
  3. data/Rakefile +12 -0
  4. data/app/assets/images/mno_enterprise/main-logo.png +0 -0
  5. data/app/controllers/mno_enterprise/application_controller.rb +116 -0
  6. data/app/helpers/mno_enterprise/application_helper.rb +67 -0
  7. data/app/helpers/mno_enterprise/impersonate_helper.rb +27 -0
  8. data/app/models/mno_enterprise/ability.rb +6 -0
  9. data/app/models/mno_enterprise/app.rb +72 -0
  10. data/app/models/mno_enterprise/app_instance.rb +36 -0
  11. data/app/models/mno_enterprise/app_instances_sync.rb +6 -0
  12. data/app/models/mno_enterprise/arrears_situation.rb +6 -0
  13. data/app/models/mno_enterprise/audit_event.rb +21 -0
  14. data/app/models/mno_enterprise/base_resource.rb +228 -0
  15. data/app/models/mno_enterprise/credit_card.rb +40 -0
  16. data/app/models/mno_enterprise/deletion_request.rb +35 -0
  17. data/app/models/mno_enterprise/impac/dashboard.rb +36 -0
  18. data/app/models/mno_enterprise/impac/dashboard_provisioner.rb +5 -0
  19. data/app/models/mno_enterprise/impac/kpi.rb +9 -0
  20. data/app/models/mno_enterprise/impac/widget.rb +13 -0
  21. data/app/models/mno_enterprise/invoice.rb +53 -0
  22. data/app/models/mno_enterprise/org_invite.rb +50 -0
  23. data/app/models/mno_enterprise/organization.rb +33 -0
  24. data/app/models/mno_enterprise/team.rb +50 -0
  25. data/app/models/mno_enterprise/tenant.rb +5 -0
  26. data/app/models/mno_enterprise/tenant_invoice.rb +5 -0
  27. data/app/models/mno_enterprise/user.rb +183 -0
  28. data/app/pdf/mno_enterprise/invoice_pdf.rb +516 -0
  29. data/config/initializers/audit_log.rb +5 -0
  30. data/config/locales/devise.en.yml +60 -0
  31. data/config/routes.rb +2 -0
  32. data/config/styleguide.yml +106 -0
  33. data/lib/accountingjs_serializer.rb +51 -0
  34. data/lib/devise/controllers/extension_helpers.rb +52 -0
  35. data/lib/devise/extension_routes.rb +11 -0
  36. data/lib/devise/hooks/password_expirable.rb +5 -0
  37. data/lib/devise/models/password_expirable.rb +28 -0
  38. data/lib/devise/models/remote_authenticatable.rb +48 -0
  39. data/lib/devise/strategies/remote_authenticatable.rb +44 -0
  40. data/lib/devise_extension.rb +36 -0
  41. data/lib/faraday/adapter/net_http_no_proxy.rb +19 -0
  42. data/lib/generators/mno_enterprise/database_extension/USAGE +11 -0
  43. data/lib/generators/mno_enterprise/database_extension/database_extension_generator.rb +36 -0
  44. data/lib/generators/mno_enterprise/database_extension/templates/model.rb +9 -0
  45. data/lib/generators/mno_enterprise/dummy/dummy_generator.rb +98 -0
  46. data/lib/generators/mno_enterprise/dummy/templates/rails/application.rb.erb +9 -0
  47. data/lib/generators/mno_enterprise/dummy/templates/rails/boot.rb.erb +6 -0
  48. data/lib/generators/mno_enterprise/dummy/templates/rails/database.yml +22 -0
  49. data/lib/generators/mno_enterprise/dummy/templates/rails/routes.rb +8 -0
  50. data/lib/generators/mno_enterprise/dummy/templates/rails/test-env.rb +45 -0
  51. data/lib/generators/mno_enterprise/install/install_generator.rb +140 -0
  52. data/lib/generators/mno_enterprise/install/templates/Procfile +1 -0
  53. data/lib/generators/mno_enterprise/install/templates/config/initializers/mno_enterprise.rb +135 -0
  54. data/lib/generators/mno_enterprise/install/templates/config/mno_enterprise_styleguide.yml +104 -0
  55. data/lib/generators/mno_enterprise/install/templates/javascripts/mno_enterprise_extensions.js +7 -0
  56. data/lib/generators/mno_enterprise/install/templates/stylesheets/main.less_erb +25 -0
  57. data/lib/generators/mno_enterprise/install/templates/stylesheets/theme.less_erb +59 -0
  58. data/lib/generators/mno_enterprise/install/templates/stylesheets/variables.less +337 -0
  59. data/lib/generators/mno_enterprise/install/templates/tasks/sprites.rake +14 -0
  60. data/lib/generators/mno_enterprise/puma_stack/puma_stack_generator.rb +58 -0
  61. data/lib/generators/mno_enterprise/templates/scripts/monit/app-server.conf +8 -0
  62. data/lib/generators/mno_enterprise/templates/scripts/nginx/app +51 -0
  63. data/lib/generators/mno_enterprise/templates/scripts/puma.rb +25 -0
  64. data/lib/generators/mno_enterprise/templates/scripts/setup.sh +27 -0
  65. data/lib/generators/mno_enterprise/templates/scripts/upstart/app-web-hotrestart.conf +26 -0
  66. data/lib/generators/mno_enterprise/templates/scripts/upstart/app-web-server.conf +34 -0
  67. data/lib/generators/mno_enterprise/templates/scripts/upstart/app-web.conf +2 -0
  68. data/lib/generators/mno_enterprise/templates/scripts/upstart/app.conf +11 -0
  69. data/lib/her_extension/her_orm_adapter.rb +54 -0
  70. data/lib/her_extension/middleware/mnoe_api_v1_parse_json.rb +54 -0
  71. data/lib/her_extension/model/associations/association.rb +61 -0
  72. data/lib/her_extension/model/associations/association_proxy.rb +34 -0
  73. data/lib/her_extension/model/associations/has_many_association.rb +115 -0
  74. data/lib/her_extension/model/attributes.rb +43 -0
  75. data/lib/her_extension/model/orm.rb +59 -0
  76. data/lib/her_extension/model/parse.rb +40 -0
  77. data/lib/her_extension/model/relation.rb +92 -0
  78. data/lib/her_extension/validations/remote_uniqueness_validation.rb +33 -0
  79. data/lib/html_processor.rb +106 -0
  80. data/lib/mandrill_client.rb +58 -0
  81. data/lib/mno-enterprise-core.rb +1 -0
  82. data/lib/mno_enterprise/concerns.rb +4 -0
  83. data/lib/mno_enterprise/concerns/controllers.rb +6 -0
  84. data/lib/mno_enterprise/concerns/controllers/angular_csrf.rb +59 -0
  85. data/lib/mno_enterprise/concerns/controllers/auth.rb +9 -0
  86. data/lib/mno_enterprise/concerns/controllers/auth/confirmations_controller.rb +187 -0
  87. data/lib/mno_enterprise/concerns/controllers/auth/passwords_controller.rb +54 -0
  88. data/lib/mno_enterprise/concerns/controllers/auth/registrations_controller.rb +136 -0
  89. data/lib/mno_enterprise/concerns/controllers/auth/sessions_controller.rb +54 -0
  90. data/lib/mno_enterprise/concerns/controllers/auth/unlocks_controller.rb +50 -0
  91. data/lib/mno_enterprise/concerns/models.rb +6 -0
  92. data/lib/mno_enterprise/concerns/models/ability.rb +108 -0
  93. data/lib/mno_enterprise/concerns/models/app_instance.rb +100 -0
  94. data/lib/mno_enterprise/concerns/models/organization.rb +102 -0
  95. data/lib/mno_enterprise/core.rb +279 -0
  96. data/lib/mno_enterprise/database_extendable.rb +57 -0
  97. data/lib/mno_enterprise/engine.rb +33 -0
  98. data/lib/mno_enterprise/testing_support/ability_test_helper.rb +10 -0
  99. data/lib/mno_enterprise/testing_support/common_rake.rb +19 -0
  100. data/lib/mno_enterprise/testing_support/factories.rb +13 -0
  101. data/lib/mno_enterprise/testing_support/factories/app_instances.rb +30 -0
  102. data/lib/mno_enterprise/testing_support/factories/apps.rb +45 -0
  103. data/lib/mno_enterprise/testing_support/factories/arrears_situation.rb +14 -0
  104. data/lib/mno_enterprise/testing_support/factories/audit_event.rb +15 -0
  105. data/lib/mno_enterprise/testing_support/factories/credit_card.rb +33 -0
  106. data/lib/mno_enterprise/testing_support/factories/deletion_request.rb +17 -0
  107. data/lib/mno_enterprise/testing_support/factories/impac/dashboards.rb +15 -0
  108. data/lib/mno_enterprise/testing_support/factories/impac/kpis.rb +20 -0
  109. data/lib/mno_enterprise/testing_support/factories/impac/widgets.rb +15 -0
  110. data/lib/mno_enterprise/testing_support/factories/invoices.rb +51 -0
  111. data/lib/mno_enterprise/testing_support/factories/org_invite.rb +24 -0
  112. data/lib/mno_enterprise/testing_support/factories/organizations.rb +25 -0
  113. data/lib/mno_enterprise/testing_support/factories/team.rb +17 -0
  114. data/lib/mno_enterprise/testing_support/factories/tenant.rb +12 -0
  115. data/lib/mno_enterprise/testing_support/factories/tenant_invoice.rb +29 -0
  116. data/lib/mno_enterprise/testing_support/factories/users.rb +48 -0
  117. data/lib/mno_enterprise/testing_support/jpi_v1_test_helper.rb +49 -0
  118. data/lib/mno_enterprise/testing_support/mno_enterprise_api_test_helper.rb +167 -0
  119. data/lib/mno_enterprise/testing_support/mnoe_faraday_test_adapter.rb +173 -0
  120. data/lib/mno_enterprise/testing_support/organizations_shared_helpers.rb +175 -0
  121. data/lib/mno_enterprise/testing_support/user_action_shared.rb +47 -0
  122. data/lib/mno_enterprise/version.rb +3 -0
  123. data/lib/tasks/mno_enterprise_tasks.rake +22 -0
  124. data/spec/controllers/mno_enterprise/angular_csrf_spec.rb +42 -0
  125. data/spec/lib/her_extension/her_orm_adapter.rb +7 -0
  126. data/spec/lib/her_extension/model/relation_spec.rb +7 -0
  127. data/spec/lib/mandrill_client_spec.rb +64 -0
  128. data/spec/mno_enterprise_spec.rb +79 -0
  129. data/spec/models/mno_enterprise/app_instance_spec.rb +7 -0
  130. data/spec/models/mno_enterprise/app_spec.rb +62 -0
  131. data/spec/models/mno_enterprise/base_resource_spec.rb +28 -0
  132. data/spec/models/mno_enterprise/deletion_request_spec.rb +26 -0
  133. data/spec/models/mno_enterprise/invoice_spec.rb +7 -0
  134. data/spec/models/mno_enterprise/organization_spec.rb +7 -0
  135. data/spec/models/mno_enterprise/user_spec.rb +44 -0
  136. data/spec/rails_helper.rb +73 -0
  137. data/spec/spec_helper.rb +78 -0
  138. metadata +421 -0
@@ -0,0 +1,14 @@
1
+ # require 'sprite_factory'
2
+
3
+ namespace :assets do
4
+ desc 'recreate sprite images and css'
5
+ task :resprite => :environment do
6
+ SpriteFactory.report = true # output report during generation
7
+ SpriteFactory.library = :chunkypng # use simple chunkypng gem to handle .png sprite generation
8
+ SpriteFactory.layout = :packed # pack sprite sheets into optimized rectangles
9
+ SpriteFactory.style = :scss # Generates a css.scss file
10
+ SpriteFactory.cssurl = "image-url('sprites/$IMAGE')"
11
+
12
+ SpriteFactory.run!('vendor/sprites/icons', output_image: 'app/assets/images/sprites/icons.sprite.png', output_style: 'app/assets/stylesheets/sprites/icons.less', selector: '.i-ic-')
13
+ end
14
+ end
@@ -0,0 +1,58 @@
1
+ require 'rails/generators/base'
2
+
3
+ module MnoEnterprise
4
+ module Generators
5
+ class PumaStackGenerator < ::Rails::Generators::Base
6
+ source_root File.expand_path("../../templates", __FILE__)
7
+ argument :environment, type: :string
8
+ desc "Description:\n Configure a stack composed of Nginx, Puma, Upstart and Monit\n\n"
9
+
10
+ def validate_environment
11
+ unless available_environments.include?(environment)
12
+ raise Exception.new("Environment '#{environment}' is not defined. Please define this environment in config/environments/#{environment}.rb")
13
+ end
14
+ end
15
+
16
+ def install_puma_gem
17
+ gem "puma"
18
+ @num_cpus = ask("How many CPUs (or vCPU for EC2) does your #{environment} machine have? [1]")
19
+ @num_cpus = "1" if @num_cpus.blank?
20
+ template "scripts/puma.rb", "scripts/#{environment}/puma.rb"
21
+ end
22
+
23
+ def copy_setup_script
24
+ template "scripts/setup.sh", "scripts/#{environment}/setup.sh"
25
+ end
26
+
27
+ def copy_nginx
28
+ @app_domain = ask("What is the domain pointing to your #{environment} application? [#{default_domain}]")
29
+ @app_domain = default_domain if @app_domain.blank?
30
+ template "scripts/nginx/app", "scripts/#{environment}/nginx/app"
31
+ end
32
+
33
+ def copy_upstart
34
+ template "scripts/upstart/app.conf", "scripts/#{environment}/upstart/app.conf"
35
+ template "scripts/upstart/app-web.conf", "scripts/#{environment}/upstart/app-web.conf"
36
+ template "scripts/upstart/app-web-server.conf", "scripts/#{environment}/upstart/app-web-server.conf"
37
+ template "scripts/upstart/app-web-hotrestart.conf", "scripts/#{environment}/upstart/app-web-hotrestart.conf"
38
+ end
39
+
40
+ def copy_monit
41
+ template "scripts/monit/app-server.conf", "scripts/#{environment}/monit/app-server.conf"
42
+ end
43
+
44
+ protected
45
+ def available_environments
46
+ Dir.glob("./config/environments/*.rb").map { |filename| File.basename(filename, ".rb") }
47
+ end
48
+
49
+ def app_name
50
+ @app_name ||= Rails.application.class.parent_name.underscore.gsub('_','-')
51
+ end
52
+
53
+ def default_domain
54
+ @default_domain ||= "#{app_name}-mnoe.maestrano.io"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,8 @@
1
+ check process <%= app_name %>-server
2
+ with pidfile "/apps/<%= app_name %>/current/tmp/pids/puma.pid"
3
+ start program = "/sbin/start <%= app_name %>-web-server"
4
+ stop program = "/sbin/stop <%= app_name %>-web-server"
5
+ if mem is greater than 1500.0 MB for 1 cycles then exec "/sbin/hotrestart <%= app_name %>"
6
+ if cpu is greater than 60% for 2 cycles then exec "/sbin/hotrestart <%= app_name %>"
7
+
8
+ group <%= app_name %>
@@ -0,0 +1,51 @@
1
+ upstream <%= app_name %>-backend {
2
+ server unix:/apps/<%= app_name %>/current/tmp/sockets/puma.sock fail_timeout=0;
3
+ }
4
+
5
+ # Rewrite http traffic to https
6
+ server {
7
+ server_name <%= app_name %>-mnoe.maestrano.io;
8
+ listen 80;
9
+
10
+ location / {
11
+ rewrite ^ https://$host$request_uri? permanent;
12
+ }
13
+ }
14
+
15
+ server {
16
+ server_name <%= @app_domain %>;
17
+ listen 443;
18
+
19
+ ssl on;
20
+ ssl_certificate /etc/nginx/certificates/maestrano.io.wildcard-current/maestrano.io.wildcard.chained.crt;
21
+ ssl_certificate_key /etc/nginx/certificates/maestrano.io.wildcard-current/maestrano.io.wildcard.key;
22
+
23
+ root /apps/<%= app_name %>/current/public;
24
+ index index.html index.htm;
25
+
26
+ try_files $uri/index.html $uri.html $uri @backend;
27
+
28
+ location ^~ /assets/ {
29
+ gzip_static on;
30
+ expires max;
31
+ add_header Cache-Control public;
32
+ }
33
+
34
+ location @backend {
35
+ expires -1;
36
+ add_header Cache-Control "max-age=0, no-store, must-revalidate";
37
+
38
+ proxy_set_header X-Forwarded-Proto https;
39
+ proxy_set_header X-Real-IP $remote_addr;
40
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
41
+ proxy_set_header Host $http_host;
42
+ proxy_redirect off;
43
+ proxy_pass http://<%= app_name %>-backend;
44
+ }
45
+
46
+ error_page 500 502 503 504 /50x.html;
47
+
48
+ location = /50x.html {
49
+ root html;
50
+ }
51
+ }
@@ -0,0 +1,25 @@
1
+ # Performance tuning
2
+ workers <%= @num_cpus %>
3
+ threads 8,16
4
+ worker_timeout 60
5
+
6
+ # Preload application
7
+ preload_app!
8
+
9
+ # Configuration
10
+ rails_env = ENV['RAILS_ENV'] || 'production'
11
+ working_directory = File.expand_path('../../../../../current', './scripts/production/puma.rb')
12
+
13
+ # General config
14
+ environment rails_env
15
+ directory working_directory
16
+ pidfile "#{working_directory}/tmp/pids/puma.pid"
17
+ state_path "#{working_directory}/tmp/pids/puma.state"
18
+ stdout_redirect "#{working_directory}/log/puma.stdout.log", "#{working_directory}/log/puma.stderr.log"
19
+ bind "unix://#{working_directory}/tmp/sockets/puma.sock"
20
+
21
+ on_worker_boot do
22
+ # ActiveSupport.on_load(:active_record) do
23
+ # ActiveRecord::Base.establish_connection
24
+ # end
25
+ end
@@ -0,0 +1,27 @@
1
+ #!/bin/bash
2
+ #
3
+ # Use this script to setup upstart, monit and any server related service
4
+
5
+ # Point upstart scripts
6
+ rm -f /etc/init/<%= app_name %>*
7
+ ln -s /apps/<%= app_name %>/current/scripts/<%= environment %>/upstart/app.conf /etc/init/<%= app_name %>.conf
8
+ ln -s /apps/<%= app_name %>/current/scripts/<%= environment %>/upstart/app-web.conf /etc/init/<%= app_name %>-web.conf
9
+ ln -s /apps/<%= app_name %>/current/scripts/<%= environment %>/upstart/app-web-server.conf /etc/init/<%= app_name %>-web-server.conf
10
+ ln -s /apps/<%= app_name %>/current/scripts/<%= environment %>/upstart/app-web-hotrestart.conf /etc/init/<%= app_name %>-web-hotrestart.conf
11
+
12
+ # Reload upstart
13
+ initctl reload-configuration
14
+
15
+ # Point monit scripts
16
+ rm -f /etc/monit/conf.d/<%= app_name %>*
17
+ ln -s /apps/<%= app_name %>/current/scripts/<%= environment %>/monit/app-server.conf /etc/monit/conf.d/<%= app_name %>-server.conf
18
+
19
+ # Reload monit
20
+ service monit reload
21
+
22
+ # Nginx
23
+ rm -f /etc/nginx/sites-available/<%= app_name %>
24
+ rm -f /etc/nginx/sites-enabled/<%= app_name %>
25
+ ln -s /apps/<%= app_name %>/current/scripts/<%= environment %>/nginx/app /etc/nginx/sites-available/<%= app_name %>
26
+ ln -s /etc/nginx/sites-available/<%= app_name %> /etc/nginx/sites-enabled/<%= app_name %>
27
+ service nginx reload
@@ -0,0 +1,26 @@
1
+ start on <%= app_name %>-hotrestart
2
+ task
3
+
4
+ # Set process owner
5
+ setuid app-deployer
6
+ setgid app-deployer
7
+
8
+ # Load App environment
9
+ env RAILS_ENV=<%= environment %>
10
+ env APP_HOME=/apps/<%= app_name %>/current
11
+ env USER=app-deployer
12
+ env HOME=/home/app-deployer
13
+
14
+ # Load ruby environment
15
+ env GEM_HOME=/usr/local/rvm/gems/ruby-2.1.2
16
+ env IRBRC=/usr/local/rvm/rubies/ruby-2.1.2/.irbrc
17
+ env MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.1.2
18
+ env PATH=/usr/local/rvm/gems/ruby-2.1.2/bin:/usr/local/rvm/gems/ruby-2.1.2@global/bin:/usr/local/rvm/rubies/ruby-2.1.2/bin:/usr/local/rvm/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/aws/bin
19
+ env GEM_PATH=/usr/local/rvm/gems/ruby-2.1.2:/usr/local/rvm/gems/ruby-2.1.2@global
20
+ env RUBY_VERSION=ruby-2.1.2
21
+
22
+ script
23
+ # Reload server
24
+ cd $APP_HOME
25
+ exec bundle exec pumactl -F scripts/<%= environment %>/puma.rb phased-restart
26
+ end script
@@ -0,0 +1,34 @@
1
+ start on starting <%= app_name %>-web
2
+ stop on stopping <%= app_name %>-web
3
+ respawn
4
+
5
+ # Set process owner
6
+ setuid app-deployer
7
+ setgid app-deployer
8
+
9
+ # Load App environment
10
+ env RAILS_ENV=<%= environment %>
11
+ env APP_HOME=/apps/<%= app_name %>/current
12
+ env USER=app-deployer
13
+ env HOME=/home/app-deployer
14
+
15
+ # Load ruby environment
16
+ env GEM_HOME=/usr/local/rvm/gems/ruby-2.1.2
17
+ env IRBRC=/usr/local/rvm/rubies/ruby-2.1.2/.irbrc
18
+ env MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.1.2
19
+ env PATH=/usr/local/rvm/gems/ruby-2.1.2/bin:/usr/local/rvm/gems/ruby-2.1.2@global/bin:/usr/local/rvm/rubies/ruby-2.1.2/bin:/usr/local/rvm/bin:/sbin:/bin:/usr/sbin:/usr/bin:/opt/aws/bin
20
+ env GEM_PATH=/usr/local/rvm/gems/ruby-2.1.2:/usr/local/rvm/gems/ruby-2.1.2@global
21
+ env RUBY_VERSION=ruby-2.1.2
22
+
23
+ pre-start script
24
+ # Enforce permissions
25
+ chown -R $USER.$USER $APP_HOME/log/
26
+ chown -R $USER.$USER $APP_HOME/tmp/pids/
27
+ chown -R $USER.$USER $APP_HOME/tmp/cache/
28
+ chown -R $USER.$USER $APP_HOME/tmp/sockets/
29
+ end script
30
+
31
+ script
32
+ cd $APP_HOME
33
+ exec bundle exec puma -C scripts/<%= environment %>/puma.rb
34
+ end script
@@ -0,0 +1,2 @@
1
+ start on starting <%= app_name %>
2
+ stop on stopping <%= app_name %>
@@ -0,0 +1,11 @@
1
+ start on runlevel [2345]
2
+ stop on runlevel [016]
3
+
4
+ pre-start script
5
+
6
+ bash << "EOF"
7
+ mkdir -p /apps/<%= app_name %>/current/log
8
+ chown -R app-deployer.app-deployer /apps/<%= app_name %>/current/log
9
+ EOF
10
+
11
+ end script
@@ -0,0 +1,54 @@
1
+ require 'orm_adapter'
2
+
3
+ # TODO: extract in gem orm_apdater-her
4
+ module Her
5
+ module Errors
6
+ class ResourceNotFound < StandardError
7
+ end
8
+ end
9
+
10
+ module Model
11
+ module ClassMethods
12
+ include OrmAdapter::ToAdapter
13
+ end
14
+
15
+ class OrmAdapter < ::OrmAdapter::Base
16
+ # get a list of column names for a given class
17
+ def column_names
18
+ @columns ||= klass.instance_methods.grep(/_will_change!$/).map { |e| e.to_s.gsub('_will_change!','') }
19
+ end
20
+
21
+ # @see OrmAdapter::Base#get!
22
+ def get!(id)
23
+ res = klass.find(wrap_key(id))
24
+ raise Her::Errors::ResourceNotFound, "resource not found" unless res
25
+ res
26
+ end
27
+
28
+ # @see OrmAdapter::Base#get
29
+ def get(id)
30
+ klass.find(wrap_key(id))
31
+ end
32
+
33
+ # @see OrmAdapter::Base#find_first
34
+ def find_first(options = {})
35
+ klass.where(options).limit(1).first
36
+ end
37
+
38
+ # @see OrmAdapter::Base#find_all
39
+ def find_all(options = {})
40
+ klass.where(options)
41
+ end
42
+
43
+ # @see OrmAdapter::Base#create!
44
+ def create!(attributes = {})
45
+ klass.create!(attributes)
46
+ end
47
+
48
+ # @see OrmAdapter::Base#destroy
49
+ def destroy(object)
50
+ object.destroy if valid_object?(object)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,54 @@
1
+ module Her
2
+ module Middleware
3
+ # This middleware expects the resource/collection data to be contained in the `data`
4
+ # key of the JSON object
5
+ class MnoeApiV1ParseJson < ParseJSON
6
+ # Parse the response body
7
+ #
8
+ # @param [String] body The response body
9
+ # @return [Mixed] the parsed response
10
+ # @private
11
+ def parse(body)
12
+ json = parse_json(body)
13
+ parse_types({
14
+ :data => json[:data] || {},
15
+ :errors => json[:errors] || {},
16
+ :metadata => json[:metadata] || {}
17
+ })
18
+ end
19
+
20
+ def parse_types(res)
21
+ case
22
+ when res.kind_of?(Array)
23
+ return res.map { |e| parse_types(e) }
24
+ when res.kind_of?(Hash) && res[:cents] && res[:currency]
25
+ Money.new(res[:cents],res[:currency])
26
+ when res.kind_of?(Hash)
27
+ hash = res.dup
28
+ hash.each do |k,v|
29
+ hash[k] = parse_types(v)
30
+ end
31
+ return hash
32
+ when res.is_a?(String) && res =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/i
33
+ return Time.iso8601(res)
34
+ else
35
+ return res
36
+ end
37
+ end
38
+
39
+ # This method is triggered when the response has been received. It modifies
40
+ # the value of `env[:body]`.
41
+ #
42
+ # @param [Hash] env The response environment
43
+ # @private
44
+ def on_complete(env)
45
+ env[:body] = case env[:status]
46
+ when 204
47
+ parse('{}')
48
+ else
49
+ parse(env[:body])
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,61 @@
1
+ # query methods should delegate to Relation
2
+ module Her
3
+ module Model
4
+ module Associations
5
+ class Association
6
+ # @private
7
+ attr_accessor :params
8
+ delegate :all, :order_by, :sort_by, :order, :sort, :limit, :skip, :where, to: :blank_relation
9
+
10
+ # Required by Relation methods
11
+ def build_request_path(params = {})
12
+ build_association_path lambda { "#{@parent.request_path(@params.merge(params))}#{@opts[:path]}" }
13
+ end
14
+
15
+ # Required by Relation methods
16
+ def method_for(meth)
17
+ @parent.class.method_for(meth)
18
+ end
19
+
20
+ # Required by Relation methods
21
+ def request(*args,&block)
22
+ @parent.class.request(*args,&block)
23
+ end
24
+
25
+ # Required by Relation methods
26
+ def new_collection(parsed_data)
27
+ Her::Model::Attributes.initialize_collection(@klass, parsed_data)
28
+ end
29
+
30
+ # Properly format the attributes to post/put
31
+ def to_params(attributes)
32
+ @parent.class.to_params(attributes,attributes)
33
+ end
34
+
35
+ # Reload the association from remote service
36
+ def reload
37
+ @klass.get(build_request_path, @params).tap do |result|
38
+ @parent.attributes[@name] = result
39
+ end
40
+ end
41
+
42
+ # Reset params when directly called on association class
43
+ # def where(*args)
44
+ # blank_relation.params = {}
45
+ # blank_relation.where(*args)
46
+ # end
47
+
48
+ def blank_relation
49
+ @blank_relation ||= Relation.new(self)
50
+ @blank_relation.params = {}
51
+ @blank_relation
52
+ end
53
+
54
+ def method_missing(name, *args, &block)
55
+ blank_relation.send(name, *args, &block)
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,34 @@
1
+ # Add reload to the list of proxy methods
2
+ module Her
3
+ module Model
4
+ module Associations
5
+ class AssociationProxy < (ActiveSupport.const_defined?('ProxyObject') ? ActiveSupport::ProxyObject : ActiveSupport::BasicObject)
6
+
7
+ install_proxy_methods :association,
8
+ :build, :create, :update, :destroy, :where, :find, :all, :assign_nested_attributes, :reload, :order, :order_by, :limit, :skip
9
+
10
+
11
+ def method_missing(name, *args, &block)
12
+ if :object_id == name # avoid redefining object_id
13
+ return association.fetch.object_id
14
+ end
15
+
16
+ # Check if a class scope has previously been defined
17
+ begin
18
+ if Relation.scopes.keys.grep(::Regexp.new(name.to_s)).any?
19
+ return self.association.send(name,*args,&block)
20
+ end
21
+ rescue ::NoMethodError => e
22
+ end
23
+
24
+ # create a proxy to the fetched object's method
25
+ # https://github.com/remiprev/her/pull/377
26
+ AssociationProxy.install_proxy_methods 'association.fetch', name
27
+
28
+ # resend message to fetched object
29
+ __send__(name, *args, &block)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end