mno-enterprise-core 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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