From ed9838cd292ce78ae98079f513d0d1648b7f49f0 Mon Sep 17 00:00:00 2001
From: Felipe Artur <felipefac@gmail.com>
Date: Fri, 14 Oct 2016 19:38:41 -0300
Subject: [PATCH] Create project feature when project is created

---
 CHANGELOG.md                                  |  1 +
 app/models/project.rb                         |  7 +----
 ...5_generate_project_feature_for_projects.rb | 28 +++++++++++++++++++
 db/schema.rb                                  |  2 +-
 spec/models/project_spec.rb                   | 14 ++++++++--
 5 files changed, 42 insertions(+), 10 deletions(-)
 create mode 100644 db/migrate/20161019213545_generate_project_feature_for_projects.rb

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7b018fc0d57..e9d07ed0927 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,7 @@ Please view this file on the master branch, on stable branches it's out of date.
   - Add an example for testing a phoenix application with Gitlab CI in the docs (Manthan Mallikarjun)
   - Cancelled pipelines could be retried. !6927
   - Updating verbiage on git basics to be more intuitive
+  - Fix project_feature record not generated on project creation
   - Clarify documentation for Runners API (Gennady Trafimenkov)
   - The instrumentation for Banzai::Renderer has been restored
   - Change user & group landing page routing from /u/:username to /:username
diff --git a/app/models/project.rb b/app/models/project.rb
index 653c38322c5..6685baab699 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -32,8 +32,8 @@ class Project < ActiveRecord::Base
   default_value_for(:shared_runners_enabled) { current_application_settings.shared_runners_enabled }
 
   after_create :ensure_dir_exist
+  after_create :create_project_feature, unless: :project_feature
   after_save :ensure_dir_exist, if: :namespace_id_changed?
-  after_initialize :setup_project_feature
 
   # set last_activity_at to the same as created_at
   after_create :set_last_activity_at
@@ -1310,11 +1310,6 @@ class Project < ActiveRecord::Base
     "projects/#{id}/pushes_since_gc"
   end
 
-  # Prevents the creation of project_feature record for every project
-  def setup_project_feature
-    build_project_feature unless project_feature
-  end
-
   def default_branch_protected?
     current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL ||
       current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE
diff --git a/db/migrate/20161019213545_generate_project_feature_for_projects.rb b/db/migrate/20161019213545_generate_project_feature_for_projects.rb
new file mode 100644
index 00000000000..4554e14b0df
--- /dev/null
+++ b/db/migrate/20161019213545_generate_project_feature_for_projects.rb
@@ -0,0 +1,28 @@
+class GenerateProjectFeatureForProjects < ActiveRecord::Migration
+  DOWNTIME = true
+
+  DOWNTIME_REASON = <<-HEREDOC
+    Application was eager loading project_feature for all projects generating an extra query
+    everytime a project was fetched. We removed that behavior to avoid the extra query, this migration
+    makes sure all projects have a project_feature record associated.
+  HEREDOC
+
+  def up
+    # Generate enabled values for each project feature 20, 20, 20, 20, 20
+    # All features are enabled by default
+    enabled_values = [ProjectFeature::ENABLED] * 5
+
+    execute <<-EOF.strip_heredoc
+      INSERT INTO project_features
+      (project_id, merge_requests_access_level, builds_access_level,
+      issues_access_level, snippets_access_level, wiki_access_level)
+      (SELECT projects.id, #{enabled_values.join(',')} FROM projects LEFT OUTER JOIN project_features
+      ON project_features.project_id = projects.id
+      WHERE project_features.id IS NULL)
+    EOF
+  end
+
+  def down
+    "Not needed"
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 65f55aa109b..a3c7fc2fd57 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20161018024550) do
+ActiveRecord::Schema.define(version: 20161019213545) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index e6d98e25d0b..f4dda1ee558 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -67,6 +67,14 @@ describe Project, models: true do
     it { is_expected.to have_many(:notification_settings).dependent(:destroy) }
     it { is_expected.to have_many(:forks).through(:forked_project_links) }
 
+    context 'after create' do
+      it "creates project feature" do
+        project = FactoryGirl.build(:project)
+
+        expect { project.save }.to change{ project.project_feature.present? }.from(false).to(true)
+      end
+    end
+
     describe '#members & #requesters' do
       let(:project) { create(:project, :public) }
       let(:requester) { create(:user) }
@@ -531,9 +539,9 @@ describe Project, models: true do
   end
 
   describe '#has_wiki?' do
-    let(:no_wiki_project) { build(:project, wiki_enabled: false, has_external_wiki: false) }
-    let(:wiki_enabled_project) { build(:project) }
-    let(:external_wiki_project) { build(:project, has_external_wiki: true) }
+    let(:no_wiki_project)       { create(:project, wiki_access_level: ProjectFeature::DISABLED, has_external_wiki: false) }
+    let(:wiki_enabled_project)  { create(:project) }
+    let(:external_wiki_project) { create(:project, has_external_wiki: true) }
 
     it 'returns true if project is wiki enabled or has external wiki' do
       expect(wiki_enabled_project).to have_wiki
-- 
GitLab