From 8b699153cc37165111ea8d057d016431a5735ba5 Mon Sep 17 00:00:00 2001 From: Peng DU Date: Mon, 20 Jun 2016 19:41:05 +0200 Subject: [PATCH 01/12] update jbuilder and add cache in progress --- Gemfile | 3 ++- Gemfile.lock | 15 +++++++++------ app/views/api/groups/index.json.jbuilder | 4 +++- app/views/api/machines/index.json.jbuilder | 18 ++++++------------ app/views/api/prices/index.json.jbuilder | 4 +++- .../api/trainings_pricings/index.json.jbuilder | 4 +++- config/environments/development.rb | 2 +- 7 files changed, 27 insertions(+), 23 deletions(-) diff --git a/Gemfile b/Gemfile index b8aa689be..6b43fa216 100644 --- a/Gemfile +++ b/Gemfile @@ -16,7 +16,8 @@ gem 'therubyracer', '= 0.12.0', platforms: :ruby # Use jquery as the JavaScript library gem 'jquery-rails' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder -gem 'jbuilder', '~> 2.0' +gem 'jbuilder', '~> 2.5' +gem 'jbuilder_cache_multi' # bundle exec rake doc:rails generates the API under doc/api. gem 'sdoc', '~> 0.4.0', group: :doc #TODO remove unused ? diff --git a/Gemfile.lock b/Gemfile.lock index e11303514..655559e0a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -179,9 +179,11 @@ GEM multi_xml (>= 0.5.2) i18n (0.7.0) ice_nine (0.11.1) - jbuilder (2.2.12) - activesupport (>= 3.0.0, < 5) + jbuilder (2.5.0) + activesupport (>= 3.0.0, < 5.1) multi_json (~> 1.2) + jbuilder_cache_multi (0.0.3) + jbuilder (>= 1.5.0, < 3) jquery-rails (4.0.3) rails-dom-testing (~> 1.0) railties (>= 4.2.0) @@ -208,13 +210,13 @@ GEM mime-types (2.99) mini_magick (4.2.0) mini_portile2 (2.0.0) - minitest (5.8.4) + minitest (5.9.0) minitest-reporters (1.1.8) ansi builder minitest (>= 5.0) ruby-progressbar - multi_json (1.11.2) + multi_json (1.12.1) multi_xml (0.5.5) multipart-post (2.0.0) naught (1.0.0) @@ -452,7 +454,8 @@ DEPENDENCIES foreman forgery friendly_id (~> 5.1.0) - jbuilder (~> 2.0) + jbuilder (~> 2.5) + jbuilder_cache_multi jquery-rails kaminari letter_opener @@ -497,4 +500,4 @@ DEPENDENCIES webmock BUNDLED WITH - 1.11.2 + 1.12.5 diff --git a/app/views/api/groups/index.json.jbuilder b/app/views/api/groups/index.json.jbuilder index 544b158ea..fb5c92e77 100644 --- a/app/views/api/groups/index.json.jbuilder +++ b/app/views/api/groups/index.json.jbuilder @@ -1 +1,3 @@ -json.partial! 'api/groups/group', collection: @groups, as: :group +json.cache! @groups do + json.partial! 'api/groups/group', collection: @groups, as: :group +end diff --git a/app/views/api/machines/index.json.jbuilder b/app/views/api/machines/index.json.jbuilder index 25c92a1b3..c45e7965e 100644 --- a/app/views/api/machines/index.json.jbuilder +++ b/app/views/api/machines/index.json.jbuilder @@ -1,13 +1,7 @@ -user_is_admin = (current_user and current_user.is_admin?) - -json.array!(@machines) do |machine| - json.extract! machine, :id, :name, :description, :spec, :slug - json.url machine_url(machine, format: :json) - json.machine_image machine.machine_image.attachment.medium.url if machine.machine_image - json.current_user_is_training current_user.is_training_machine?(machine) if current_user - json.current_user_training_reservation do - json.partial! 'api/reservations/reservation', reservation: current_user.training_reservation_by_machine(machine) - end if current_user and !current_user.is_training_machine?(machine) and current_user.training_reservation_by_machine(machine) - - json.plan_ids machine.plan_ids if user_is_admin +json.cache! @machines do + json.array!(@machines) do |machine| + json.extract! machine, :id, :name, :description, :spec, :slug + json.url machine_url(machine, format: :json) + json.machine_image machine.machine_image.attachment.medium.url if machine.machine_image + end end diff --git a/app/views/api/prices/index.json.jbuilder b/app/views/api/prices/index.json.jbuilder index 5cd43fe7b..4f77c5ab7 100644 --- a/app/views/api/prices/index.json.jbuilder +++ b/app/views/api/prices/index.json.jbuilder @@ -1 +1,3 @@ -json.prices @prices, partial: 'api/prices/price', as: :price +json.cache! @prices do + json.prices @prices, partial: 'api/prices/price', as: :price +end diff --git a/app/views/api/trainings_pricings/index.json.jbuilder b/app/views/api/trainings_pricings/index.json.jbuilder index a091263a6..5ff1f0d04 100644 --- a/app/views/api/trainings_pricings/index.json.jbuilder +++ b/app/views/api/trainings_pricings/index.json.jbuilder @@ -1 +1,3 @@ -json.partial! 'api/trainings_pricings/trainings_pricing', collection: @trainings_pricings, as: :trainings_pricing +json.cache! @trainings_pricings do + json.partial! 'api/trainings_pricings/trainings_pricing', collection: @trainings_pricings, as: :trainings_pricing +end diff --git a/config/environments/development.rb b/config/environments/development.rb index e24f8414a..2e1262529 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -11,7 +11,7 @@ Rails.application.configure do # Show full error reports and disable caching. config.consider_all_requests_local = true - config.action_controller.perform_caching = false + config.action_controller.perform_caching = true # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false From 4d0d3d6af0d4fad44eb6dcf19b5b02724984de1a Mon Sep 17 00:00:00 2001 From: Peng DU Date: Tue, 21 Jun 2016 14:49:39 +0200 Subject: [PATCH 02/12] optimise load plans json --- .../controllers/admin/plans.coffee.erb | 19 ++++++++++--------- app/assets/javascripts/router.coffee.erb | 6 +++--- app/controllers/api/plans_controller.rb | 9 ++------- app/views/api/plans/_plan.json.jbuilder | 15 --------------- app/views/api/plans/index.json.jbuilder | 8 +++++++- app/views/api/prices/_price.json.jbuilder | 1 + 6 files changed, 23 insertions(+), 35 deletions(-) diff --git a/app/assets/javascripts/controllers/admin/plans.coffee.erb b/app/assets/javascripts/controllers/admin/plans.coffee.erb index c5bf1151b..d7b266f1a 100644 --- a/app/assets/javascripts/controllers/admin/plans.coffee.erb +++ b/app/assets/javascripts/controllers/admin/plans.coffee.erb @@ -175,8 +175,8 @@ Application.Controllers.controller 'NewPlanController', ['$scope', '$uibModal', ## # Controller used in the plan edition form ## -Application.Controllers.controller 'EditPlanController', ['$scope', 'groups', 'plans', 'planPromise', 'machines', 'prices', 'partners', 'CSRF', '$state', '$stateParams', 'growl', '$filter', '_t', '$locale' -, ($scope, groups, plans, planPromise, machines, prices, partners, CSRF, $state, $stateParams, growl, $filter, _t, $locale) -> +Application.Controllers.controller 'EditPlanController', ['$scope', 'groups', 'plans', 'planPromise', 'machines', 'prices', 'partners', 'CSRF', '$state', '$stateParams', 'growl', '$filter', '_t', '$locale', 'Plan' +, ($scope, groups, plans, planPromise, machines, prices, partners, CSRF, $state, $stateParams, growl, $filter, _t, $locale, Plan) -> @@ -207,12 +207,13 @@ Application.Controllers.controller 'EditPlanController', ['$scope', 'groups', 'p ## $scope.copyPricesFromPlan = -> if $scope.plan.parent - parentPlan = $scope.getPlanFromId($scope.plan.parent) - for parentPrice in parentPlan.prices - for childKey, childPrice of $scope.plan.prices - if childPrice.priceable_type == parentPrice.priceable_type and childPrice.priceable_id == parentPrice.priceable_id - $scope.plan.prices[childKey].amount = parentPrice.amount - break + Plan.get {id: $scope.plan.parent}, (parentPlan) -> + for parentPrice in parentPlan.prices + for childKey, childPrice of $scope.plan.prices + if childPrice.priceable_type == parentPrice.priceable_type and childPrice.priceable_id == parentPrice.priceable_id + $scope.plan.prices[childKey].amount = parentPrice.amount + break + # if no plan were selected, unset every prices else for key, price of $scope.plan.prices @@ -257,4 +258,4 @@ Application.Controllers.controller 'EditPlanController', ['$scope', 'groups', 'p ## !!! MUST BE CALLED AT THE END of the controller initialize() -] \ No newline at end of file +] diff --git a/app/assets/javascripts/router.coffee.erb b/app/assets/javascripts/router.coffee.erb index 7f1416510..e3d47ad4c 100644 --- a/app/assets/javascripts/router.coffee.erb +++ b/app/assets/javascripts/router.coffee.erb @@ -330,7 +330,7 @@ angular.module('application.router', ['ui.router']). controller: 'ReserveMachineController' resolve: plansPromise: ['Plan', (Plan)-> - Plan.query(attributes_requested: "['machines_credits']").$promise + Plan.query().$promise ] groupsPromise: ['Group', (Group)-> Group.query().$promise @@ -375,7 +375,7 @@ angular.module('application.router', ['ui.router']). Setting.get(name: 'training_explications_alert').$promise ] plansPromise: ['Plan', (Plan)-> - Plan.query(attributes_requested: "['trainings_credits']").$promise + Plan.query().$promise ] groupsPromise: ['Group', (Group)-> Group.query().$promise @@ -423,7 +423,7 @@ angular.module('application.router', ['ui.router']). Setting.get(name: 'subscription_explications_alert').$promise ] plansPromise: ['Plan', (Plan)-> - Plan.query(shallow: true).$promise + Plan.query().$promise ] groupsPromise: ['Group', (Group)-> Group.query().$promise diff --git a/app/controllers/api/plans_controller.rb b/app/controllers/api/plans_controller.rb index b9b922112..7b7f0d203 100644 --- a/app/controllers/api/plans_controller.rb +++ b/app/controllers/api/plans_controller.rb @@ -2,14 +2,9 @@ before_action :authenticate_user!, except: [:index] def index - @attributes_requested = params[:attributes_requested] - @plans = Plan.all + @plans = Plan.includes(:plan_file) @plans = @plans.where(group_id: params[:group_id]) if params[:group_id] - if params[:shallow] - render :shallow_index - else - render :index - end + render :index end def show diff --git a/app/views/api/plans/_plan.json.jbuilder b/app/views/api/plans/_plan.json.jbuilder index bda984fbe..ca0eb1292 100644 --- a/app/views/api/plans/_plan.json.jbuilder +++ b/app/views/api/plans/_plan.json.jbuilder @@ -6,23 +6,8 @@ json.plan_file_attributes do json.attachment_identifier plan.plan_file.attachment_identifier end if plan.plan_file -json.prices plan.prices do |price| - json.extract! price, :id, :group_id, :plan_id, :priceable_type, :priceable_id - json.amount price.amount / 100.0 - json.priceable_name price.priceable.name -end - json.partners plan.partners do |partner| json.first_name partner.first_name json.last_name partner.last_name json.email partner.email end if plan.respond_to?(:partners) - -json.training_credits plan.training_credits do |tc| - json.training_id tc.creditable_id -end if attribute_requested?(@attributes_requested, 'trainings_credits') - -json.machine_credits plan.machine_credits do |mc| - json.machine_id mc.creditable_id - json.hours mc.hours -end if attribute_requested?(@attributes_requested, 'machines_credits') diff --git a/app/views/api/plans/index.json.jbuilder b/app/views/api/plans/index.json.jbuilder index a63916500..46e7fb9bd 100644 --- a/app/views/api/plans/index.json.jbuilder +++ b/app/views/api/plans/index.json.jbuilder @@ -1 +1,7 @@ -json.partial! 'api/plans/plan', collection: @plans, as: :plan +json.cache! @plans do + json.array!(@plans) do |plan| + json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :description, :type, :ui_weight + json.amount (plan.amount / 100.00) + json.plan_file_url plan.plan_file.attachment_url if plan.plan_file + end +end diff --git a/app/views/api/prices/_price.json.jbuilder b/app/views/api/prices/_price.json.jbuilder index 19a0ffc06..ca3aea1c4 100644 --- a/app/views/api/prices/_price.json.jbuilder +++ b/app/views/api/prices/_price.json.jbuilder @@ -1,2 +1,3 @@ json.extract! price, :id, :group_id, :plan_id, :priceable_type, :priceable_id json.amount price.amount / 100.0 +json.priceable_name price.priceable.name From 85a40db603c262671118668ee79d95a69093f914 Mon Sep 17 00:00:00 2001 From: Peng DU Date: Tue, 21 Jun 2016 16:04:44 +0200 Subject: [PATCH 03/12] price cache --- app/assets/javascripts/controllers/admin/pricing.coffee.erb | 2 +- app/assets/javascripts/services/price.coffee | 2 +- app/controllers/api/trainings_pricings_controller.rb | 2 +- app/views/api/prices/_price.json.jbuilder | 1 - app/views/api/prices/index.json.jbuilder | 2 +- .../api/trainings_pricings/_trainings_pricing.json.jbuilder | 3 --- 6 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/controllers/admin/pricing.coffee.erb b/app/assets/javascripts/controllers/admin/pricing.coffee.erb index c6b959c4a..99f6b9475 100644 --- a/app/assets/javascripts/controllers/admin/pricing.coffee.erb +++ b/app/assets/javascripts/controllers/admin/pricing.coffee.erb @@ -8,7 +8,7 @@ Application.Controllers.controller "EditPricingController", ["$scope", "$state", ### PUBLIC SCOPE ### ## List of machines prices (not considering any plan) - $scope.machinesPrices = machinesPricesPromise.prices + $scope.machinesPrices = machinesPricesPromise ## List of trainings pricing $scope.trainingsPricings = trainingsPricingsPromise diff --git a/app/assets/javascripts/services/price.coffee b/app/assets/javascripts/services/price.coffee index 66b8270fe..f836f943e 100644 --- a/app/assets/javascripts/services/price.coffee +++ b/app/assets/javascripts/services/price.coffee @@ -4,7 +4,7 @@ Application.Services.factory 'Price', ["$resource", ($resource)-> $resource "/api/prices/:id", {}, query: - isArray: false + isArray: true update: method: 'PUT' compute: diff --git a/app/controllers/api/trainings_pricings_controller.rb b/app/controllers/api/trainings_pricings_controller.rb index 367b1f72d..2db646e72 100644 --- a/app/controllers/api/trainings_pricings_controller.rb +++ b/app/controllers/api/trainings_pricings_controller.rb @@ -2,7 +2,7 @@ class API::TrainingsPricingsController < API::ApiController before_action :authenticate_user! def index - @trainings_pricings = TrainingsPricing.includes(:training) + @trainings_pricings = TrainingsPricing.all end def update diff --git a/app/views/api/prices/_price.json.jbuilder b/app/views/api/prices/_price.json.jbuilder index ca3aea1c4..19a0ffc06 100644 --- a/app/views/api/prices/_price.json.jbuilder +++ b/app/views/api/prices/_price.json.jbuilder @@ -1,3 +1,2 @@ json.extract! price, :id, :group_id, :plan_id, :priceable_type, :priceable_id json.amount price.amount / 100.0 -json.priceable_name price.priceable.name diff --git a/app/views/api/prices/index.json.jbuilder b/app/views/api/prices/index.json.jbuilder index 4f77c5ab7..8a03cbb34 100644 --- a/app/views/api/prices/index.json.jbuilder +++ b/app/views/api/prices/index.json.jbuilder @@ -1,3 +1,3 @@ json.cache! @prices do - json.prices @prices, partial: 'api/prices/price', as: :price + json.partial! 'api/prices/price', collection: @prices, as: :price end diff --git a/app/views/api/trainings_pricings/_trainings_pricing.json.jbuilder b/app/views/api/trainings_pricings/_trainings_pricing.json.jbuilder index 221217ac2..1d215bd50 100644 --- a/app/views/api/trainings_pricings/_trainings_pricing.json.jbuilder +++ b/app/views/api/trainings_pricings/_trainings_pricing.json.jbuilder @@ -1,5 +1,2 @@ json.extract! trainings_pricing, :id, :group_id, :training_id json.amount trainings_pricing.amount / 100.0 -json.training do - json.name trainings_pricing.training.name -end From d65ecf437b4c214bf5d901959b0595d819c842e9 Mon Sep 17 00:00:00 2001 From: Peng DU Date: Tue, 21 Jun 2016 17:02:44 +0200 Subject: [PATCH 04/12] cache training json --- app/views/api/trainings/index.json.jbuilder | 28 ++++++++------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/app/views/api/trainings/index.json.jbuilder b/app/views/api/trainings/index.json.jbuilder index 72ff1ff85..02cdd42b4 100644 --- a/app/views/api/trainings/index.json.jbuilder +++ b/app/views/api/trainings/index.json.jbuilder @@ -1,19 +1,13 @@ -json.array!(@trainings) do |training| - json.id training.id - json.name training.name - json.description training.description - json.machine_ids training.machine_ids - json.availabilities training.availabilities do |a| - json.id a.id - json.start_at a.start_at.iso8601 - json.end_at a.end_at.iso8601 - json.reservation_users a.slots.map do |slot| - json.id slot.reservation.user.id - json.full_name slot.reservation.user.profile.full_name - json.is_valid slot.reservation.user.trainings.include?(training) - end - end if attribute_requested?(@requested_attributes, 'availabilities') - json.nb_total_places training.nb_total_places +role = (current_user and current_user.is_admin?) ? 'admin' : 'user' - json.plan_ids training.plan_ids if current_user and current_user.is_admin? +json.cache! [@trainings, role] do + json.array!(@trainings) do |training| + json.id training.id + json.name training.name + json.description training.description + json.machine_ids training.machine_ids + json.nb_total_places training.nb_total_places + + json.plan_ids training.plan_ids if role === 'admin' + end end From e82372fb7b2919e20b60624698946d43f7a54a12 Mon Sep 17 00:00:00 2001 From: Peng DU Date: Tue, 21 Jun 2016 19:07:47 +0200 Subject: [PATCH 05/12] optimise machine availabilities query --- app/controllers/api/availabilities_controller.rb | 12 ++++++------ app/views/api/machines/show.json.jbuilder | 10 ---------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index 51f3c94ea..665ef7263 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -49,9 +49,10 @@ class API::AvailabilitiesController < API::ApiController else @user = current_user end + current_user_role = current_user.is_admin? ? 'admin' : 'user' @machine = Machine.find(params[:machine_id]) @slots = [] - @reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @machine.class.to_s, @machine.id).joins(:slots).where('slots.start_at > ?', Time.now) + @reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @machine.class.to_s, @machine.id).includes(:slots, :user).references(:slots, :user).where('slots.start_at > ?', Time.now) if @user.is_admin? @availabilities = @machine.availabilities.where("end_at > ? AND available_type = 'machines'", Time.now) else @@ -62,8 +63,8 @@ class API::AvailabilitiesController < API::ApiController @availabilities.each do |a| ((a.end_at - a.start_at)/SLOT_DURATION.minutes).to_i.times do |i| if (a.start_at + (i * SLOT_DURATION).minutes) > Time.now - slot = Slot.new(start_at: a.start_at + (i*SLOT_DURATION).minutes, end_at: a.start_at + (i*SLOT_DURATION).minutes + SLOT_DURATION.minutes, availability_id: a.id, machine: @machine, title: '') - slot = verify_machine_is_reserved(slot, @reservations) + slot = Slot.new(start_at: a.start_at + (i*SLOT_DURATION).minutes, end_at: a.start_at + (i*SLOT_DURATION).minutes + SLOT_DURATION.minutes, availability_id: a.id, availability: a, machine: @machine, title: '') + slot = verify_machine_is_reserved(slot, @reservations, current_user, current_user_role) @slots << slot end end @@ -115,15 +116,14 @@ class API::AvailabilitiesController < API::ApiController is_reserved end - def verify_machine_is_reserved(slot, reservations) - user = current_user + def verify_machine_is_reserved(slot, reservations, user, user_role) reservations.each do |r| r.slots.each do |s| if s.start_at == slot.start_at and s.canceled_at == nil slot.id = s.id slot.is_reserved = true slot.title = t('availabilities.not_available') - slot.can_modify = true if user.is_admin? + slot.can_modify = true if user_role === 'admin' slot.reservation = r end if s.start_at == slot.start_at and r.user == user and s.canceled_at == nil diff --git a/app/views/api/machines/show.json.jbuilder b/app/views/api/machines/show.json.jbuilder index 1e6d8760a..bfb4ab07a 100644 --- a/app/views/api/machines/show.json.jbuilder +++ b/app/views/api/machines/show.json.jbuilder @@ -11,16 +11,6 @@ json.current_user_training_reservation do json.partial! 'api/reservations/reservation', reservation: current_user.training_reservation_by_machine(@machine) end if current_user and !current_user.is_training_machine?(@machine) and current_user.training_reservation_by_machine(@machine) -json.amount_by_group Group.all do |g| - json.id g.id - json.name g.name - json.not_subscribe_amount @machine.not_subscribe_price(g.id).amount/100.0 - - json.amount_by_plan @machine.prices_by_group(g.id) do |price| - json.plan_id price.plan_id - json.amount price.amount/100.0 - end -end json.machine_projects @machine.projects.published.last(10) do |p| json.id p.id json.name p.name From 4dff74827bb0311c27d391af303e5d46ef5c6663 Mon Sep 17 00:00:00 2001 From: Peng DU Date: Wed, 22 Jun 2016 12:54:12 +0200 Subject: [PATCH 06/12] optimise machine/training availabilities query --- app/controllers/api/availabilities_controller.rb | 16 ++++++++-------- app/models/availability.rb | 5 +++-- .../api/availabilities/machine.json.jbuilder | 2 +- .../api/availabilities/trainings.json.jbuilder | 16 +++++----------- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index 665ef7263..177e1f16f 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -49,22 +49,22 @@ class API::AvailabilitiesController < API::ApiController else @user = current_user end - current_user_role = current_user.is_admin? ? 'admin' : 'user' + @current_user_role = current_user.is_admin? ? 'admin' : 'user' @machine = Machine.find(params[:machine_id]) @slots = [] - @reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @machine.class.to_s, @machine.id).includes(:slots, :user).references(:slots, :user).where('slots.start_at > ?', Time.now) + @reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @machine.class.to_s, @machine.id).includes(:slots, user: [:profile]).references(:slots, :user).where('slots.start_at > ?', Time.now) if @user.is_admin? - @availabilities = @machine.availabilities.where("end_at > ? AND available_type = 'machines'", Time.now) + @availabilities = @machine.availabilities.includes(:tags).where("end_at > ? AND available_type = 'machines'", Time.now) else end_at = 1.month.since end_at = 3.months.since if is_subscription_year(@user) - @availabilities = @machine.availabilities.includes(:availability_tags).where("end_at > ? AND end_at < ? AND available_type = 'machines'", Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) + @availabilities = @machine.availabilities.includes(:tags).where("end_at > ? AND end_at < ? AND available_type = 'machines'", Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) end @availabilities.each do |a| ((a.end_at - a.start_at)/SLOT_DURATION.minutes).to_i.times do |i| if (a.start_at + (i * SLOT_DURATION).minutes) > Time.now slot = Slot.new(start_at: a.start_at + (i*SLOT_DURATION).minutes, end_at: a.start_at + (i*SLOT_DURATION).minutes + SLOT_DURATION.minutes, availability_id: a.id, availability: a, machine: @machine, title: '') - slot = verify_machine_is_reserved(slot, @reservations, current_user, current_user_role) + slot = verify_machine_is_reserved(slot, @reservations, current_user, @current_user_role) @slots << slot end end @@ -78,13 +78,13 @@ class API::AvailabilitiesController < API::ApiController @user = current_user end @slots = [] - @reservations = @user.reservations.where("reservable_type = 'Training'").joins(:slots).where('slots.start_at > ?', Time.now) + @reservations = @user.reservations.includes(:slots).references(:slots).where("reservable_type = 'Training' AND slots.start_at > ?", Time.now) if @user.is_admin? - @availabilities = Availability.trainings.where('start_at > ?', Time.now) + @availabilities = Availability.includes(:tags, :slots, trainings: [:machines]).trainings.where('availabilities.start_at > ?', Time.now) else end_at = 1.month.since end_at = 3.months.since if can_show_slot_plus_three_months(@user) - @availabilities = Availability.trainings.includes(:availability_tags).where('start_at > ? AND start_at < ?', Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) + @availabilities = Availability.includes(:tags, :slots, trainings: [:machines]).trainings.where('start_at > ? AND start_at < ?', Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) end @availabilities.each do |a| a = verify_training_is_reserved(a, @reservations) diff --git a/app/models/availability.rb b/app/models/availability.rb index 0790fdc8f..03b8f2984 100644 --- a/app/models/availability.rb +++ b/app/models/availability.rb @@ -16,7 +16,7 @@ class Availability < ActiveRecord::Base accepts_nested_attributes_for :tags, allow_destroy: true scope :machines, -> { where(available_type: 'machines') } - scope :trainings, -> { where(available_type: 'training') } + scope :trainings, -> { includes(:trainings).where(available_type: 'training') } attr_accessor :is_reserved, :slot_id, :can_modify @@ -51,9 +51,10 @@ class Availability < ActiveRecord::Base # if haven't defined a nb_total_places, places are unlimited def is_completed return false if nb_total_places.blank? - nb_total_places <= slots.where(canceled_at: nil).size + nb_total_places <= slots.to_a.select {|s| s.canceled_at == nil }.size end + # TODO: refactoring this function for avoid N+1 query def nb_total_places if read_attribute(:nb_total_places).present? read_attribute(:nb_total_places) diff --git a/app/views/api/availabilities/machine.json.jbuilder b/app/views/api/availabilities/machine.json.jbuilder index c1811d812..c068a649d 100644 --- a/app/views/api/availabilities/machine.json.jbuilder +++ b/app/views/api/availabilities/machine.json.jbuilder @@ -17,7 +17,7 @@ json.array!(@slots) do |slot| json.user do json.id slot.reservation.user.id json.name slot.reservation.user.profile.full_name - end if slot.reservation # ... if the slot was reserved + end if @current_user_role == 'admin' and slot.reservation # ... if the slot was reserved json.tag_ids slot.availability.tag_ids json.tags slot.availability.tags do |t| json.id t.id diff --git a/app/views/api/availabilities/trainings.json.jbuilder b/app/views/api/availabilities/trainings.json.jbuilder index b180a6248..1cbee8169 100644 --- a/app/views/api/availabilities/trainings.json.jbuilder +++ b/app/views/api/availabilities/trainings.json.jbuilder @@ -2,26 +2,21 @@ json.array!(@availabilities) do |a| json.id a.id json.slot_id a.slot_id if a.slot_id if a.is_reserved + json.is_reserved true json.title "#{a.trainings[0].name}' - #{t('trainings.i_ve_reserved')}" + json.borderColor '#b2e774' elsif a.is_completed + json.is_completed true json.title "#{a.trainings[0].name} - #{t('trainings.completed')}" + json.borderColor '#eeeeee' else json.title a.trainings[0].name + json.borderColor '#bd7ae9' end json.start a.start_at.iso8601 json.end a.end_at.iso8601 - json.is_reserved a.is_reserved json.backgroundColor 'white' - json.borderColor a.is_reserved ? '#b2e774' : '#bd7ae9' - if a.is_reserved - json.borderColor '#b2e774' - elsif a.is_completed - json.borderColor '#eeeeee' - else - json.borderColor '#bd7ae9' - end json.can_modify a.can_modify - json.is_completed a.is_completed json.nb_total_places a.nb_total_places json.training do @@ -32,7 +27,6 @@ json.array!(@availabilities) do |a| json.id m.id json.name m.name end - json.amount a.trainings.first.amount_by_group(@user.group_id).amount_by_plan(nil)/100.0 if @user end json.tag_ids a.tag_ids json.tags a.tags do |t| From 702e35650f8662d964d7137a66db740ded682988 Mon Sep 17 00:00:00 2001 From: Peng DU Date: Fri, 24 Jun 2016 18:26:11 +0200 Subject: [PATCH 07/12] event cache --- app/models/event.rb | 2 ++ app/policies/event_policy.rb | 4 ++-- app/views/api/events/index.json.jbuilder | 13 +++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/models/event.rb b/app/models/event.rb index 8007f6a4e..412580b70 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -14,6 +14,8 @@ class Event < ActiveRecord::Base after_create :event_recurrence before_save :update_nb_free_places + # update event updated_at for index cache + after_save -> { self.touch } def name title diff --git a/app/policies/event_policy.rb b/app/policies/event_policy.rb index fc140bb42..d317c1b96 100644 --- a/app/policies/event_policy.rb +++ b/app/policies/event_policy.rb @@ -2,12 +2,12 @@ class EventPolicy < ApplicationPolicy class Scope < Scope def resolve if user.nil? or (user and !user.is_admin?) - scope.includes(:event_image, :event_files, :availability) + scope.includes(:event_image, :event_files, :availability, :categories) .where('availabilities.start_at >= ?', Time.now) .order('availabilities.start_at ASC') .references(:availabilities) else - scope.includes(:event_image, :event_files, :availability) + scope.includes(:event_image, :event_files, :availability, :categories) .order('availabilities.start_at DESC') .references(:availabilities) end diff --git a/app/views/api/events/index.json.jbuilder b/app/views/api/events/index.json.jbuilder index 4a24caedc..c95bf00a7 100644 --- a/app/views/api/events/index.json.jbuilder +++ b/app/views/api/events/index.json.jbuilder @@ -1,7 +1,8 @@ -json.array!(@events) do |event| - json.partial! 'api/events/event', event: event - json.event_image_small event.event_image.attachment.small.url if event.event_image - json.url event_url(event, format: :json) - json.nb_total_events @total +json.cache! [@events, @page] do + json.array!(@events) do |event| + json.partial! 'api/events/event', event: event + json.event_image_small event.event_image.attachment.small.url if event.event_image + json.url event_url(event, format: :json) + json.nb_total_events @total + end end - From d64e8a291bb2c7bb373bdfea8a5d963b9e9785a5 Mon Sep 17 00:00:00 2001 From: Peng DU Date: Fri, 24 Jun 2016 18:36:36 +0200 Subject: [PATCH 08/12] remove order for avoid N+1 --- app/views/api/trainings/show.json.jbuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/api/trainings/show.json.jbuilder b/app/views/api/trainings/show.json.jbuilder index 6afadde51..fbc0587b2 100644 --- a/app/views/api/trainings/show.json.jbuilder +++ b/app/views/api/trainings/show.json.jbuilder @@ -1,5 +1,5 @@ json.extract! @training, :id, :name, :machine_ids, :nb_total_places -json.availabilities @training.availabilities.order('start_at DESC') do |a| +json.availabilities @training.availabilities do |a| json.id a.id json.start_at a.start_at.iso8601 json.end_at a.end_at.iso8601 From 0bb4665b4a3e0fe7dab6e3b32da9faf40383f7be Mon Sep 17 00:00:00 2001 From: Peng DU Date: Fri, 24 Jun 2016 18:43:22 +0200 Subject: [PATCH 09/12] avoid N+1 for users list --- app/controllers/api/admins_controller.rb | 2 +- app/controllers/api/members_controller.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/admins_controller.rb b/app/controllers/api/admins_controller.rb index 7f254bda7..175d6b4e5 100644 --- a/app/controllers/api/admins_controller.rb +++ b/app/controllers/api/admins_controller.rb @@ -3,7 +3,7 @@ class API::AdminsController < API::ApiController def index authorize :admin - @admins = User.admins + @admins = User.includes(profile: [:user_avatar]).admins end def create diff --git a/app/controllers/api/members_controller.rb b/app/controllers/api/members_controller.rb index 8950d019f..d47dac177 100644 --- a/app/controllers/api/members_controller.rb +++ b/app/controllers/api/members_controller.rb @@ -169,7 +169,7 @@ class API::MembersController < API::ApiController order_key = 'users.id' end - @members = User.includes(:profile, :group) + @members = User.includes(:profile, :group, :subscriptions) .joins(:profile, :group, :roles, 'LEFT JOIN "subscriptions" ON "subscriptions"."user_id" = "users"."id" LEFT JOIN "plans" ON "plans"."id" = "subscriptions"."plan_id"') .where("users.is_active = 'true' AND roles.name = 'member'") .order("#{order_key} #{direction}") From 68e45c0460010095614e31ef159b0bba4fc89cbf Mon Sep 17 00:00:00 2001 From: Peng DU Date: Mon, 27 Jun 2016 10:55:51 +0200 Subject: [PATCH 10/12] cache last event and optimise last subscript api --- app/controllers/api/events_controller.rb | 5 +++-- app/controllers/api/members_controller.rb | 2 +- app/views/api/events/upcoming.json.jbuilder | 11 ++++++----- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/events_controller.rb b/app/controllers/api/events_controller.rb index d24573eee..b17dd3b6f 100644 --- a/app/controllers/api/events_controller.rb +++ b/app/controllers/api/events_controller.rb @@ -4,13 +4,14 @@ class API::EventsController < API::ApiController def index @events = policy_scope(Event) @total = @events.count - @events = @events.page(params[:page]).per(12) + @page = params[:page] + @events = @events.page(@page).per(12) end # GET /events/upcoming/:limit def upcoming limit = params[:limit] - @events = Event.includes(:event_image, :event_files, :availability) + @events = Event.includes(:event_image, :event_files, :availability, :categories) .where('availabilities.start_at >= ?', Time.now) .order('availabilities.start_at ASC').references(:availabilities).limit(limit) end diff --git a/app/controllers/api/members_controller.rb b/app/controllers/api/members_controller.rb index d47dac177..103a83f5f 100644 --- a/app/controllers/api/members_controller.rb +++ b/app/controllers/api/members_controller.rb @@ -13,7 +13,7 @@ class API::MembersController < API::ApiController end def last_subscribed - @members = User.active.with_role(:member).includes(:profile).where('is_allow_contact = true AND confirmed_at IS NOT NULL').order('created_at desc').limit(params[:last]) + @members = User.active.with_role(:member).includes(profile: [:user_avatar]).where('is_allow_contact = true AND confirmed_at IS NOT NULL').order('created_at desc').limit(params[:last]) @requested_attributes = ['profile'] render :index end diff --git a/app/views/api/events/upcoming.json.jbuilder b/app/views/api/events/upcoming.json.jbuilder index 97d32bc8c..4d97b3978 100644 --- a/app/views/api/events/upcoming.json.jbuilder +++ b/app/views/api/events/upcoming.json.jbuilder @@ -1,6 +1,7 @@ -json.array!(@events) do |event| - json.partial! 'api/events/event', event: event - json.event_image_medium event.event_image.attachment.medium.url if event.event_image - json.url event_url(event, format: :json) +json.cache! @events do + json.array!(@events) do |event| + json.partial! 'api/events/event', event: event + json.event_image_medium event.event_image.attachment.medium.url if event.event_image + json.url event_url(event, format: :json) + end end - From b4773532866e345d112541a1e1674f5333ed4a2f Mon Sep 17 00:00:00 2001 From: Peng DU Date: Mon, 27 Jun 2016 12:37:44 +0200 Subject: [PATCH 11/12] cancel cache for plant and training_prcings --- app/views/api/plans/index.json.jbuilder | 10 ++++------ app/views/api/trainings_pricings/index.json.jbuilder | 4 +--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/app/views/api/plans/index.json.jbuilder b/app/views/api/plans/index.json.jbuilder index 46e7fb9bd..fe6c2f366 100644 --- a/app/views/api/plans/index.json.jbuilder +++ b/app/views/api/plans/index.json.jbuilder @@ -1,7 +1,5 @@ -json.cache! @plans do - json.array!(@plans) do |plan| - json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :description, :type, :ui_weight - json.amount (plan.amount / 100.00) - json.plan_file_url plan.plan_file.attachment_url if plan.plan_file - end +json.array!(@plans) do |plan| + json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :description, :type, :ui_weight + json.amount (plan.amount / 100.00) + json.plan_file_url plan.plan_file.attachment_url if plan.plan_file end diff --git a/app/views/api/trainings_pricings/index.json.jbuilder b/app/views/api/trainings_pricings/index.json.jbuilder index 5ff1f0d04..a091263a6 100644 --- a/app/views/api/trainings_pricings/index.json.jbuilder +++ b/app/views/api/trainings_pricings/index.json.jbuilder @@ -1,3 +1 @@ -json.cache! @trainings_pricings do - json.partial! 'api/trainings_pricings/trainings_pricing', collection: @trainings_pricings, as: :trainings_pricing -end +json.partial! 'api/trainings_pricings/trainings_pricing', collection: @trainings_pricings, as: :trainings_pricing From 07f231cb1fc0ecc0349ca440d2f7b1e8ccc75cbd Mon Sep 17 00:00:00 2001 From: Peng DU Date: Mon, 27 Jun 2016 12:41:54 +0200 Subject: [PATCH 12/12] update changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbfebd902..38e9ee69e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog Fab Manager +- add json cache for machines, events, trainings +- optimise sql query, avoid to N+1 + ## v2.2.0 2016 June 16 - Built-in support for extensions plug-ins - User profile form: social networks links, personal website link, job and change profile visibility (public / private) @@ -30,4 +33,4 @@ - Fix a bug: custom asset favicon-file favicon file is not set - Fix a security issue: stripe card token is now checked on server side on new/renew subscription - Translated notification e-mails into english language -- Subscription extension logic has been extracted into a microservice \ No newline at end of file +- Subscription extension logic has been extracted into a microservice