Commit 0f2798d4 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'feature/refactoring_scopes_pr' of...

Merge branch 'feature/refactoring_scopes_pr' of https://github.com/Undev/gitlabhq into Undev-feature/refactoring_scopes_pr

Conflicts:
	db/schema.rb
parents 52cd655f 85e03904
...@@ -14,7 +14,7 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -14,7 +14,7 @@ class Admin::UsersController < Admin::ApplicationController
@not_in_projects = @not_in_projects.without_user(admin_user) if admin_user.authorized_projects.present? @not_in_projects = @not_in_projects.without_user(admin_user) if admin_user.authorized_projects.present?
# Projects he already own or joined # Projects he already own or joined
@projects = admin_user.authorized_projects.where('projects.id in (?)', admin_user.authorized_projects.map(&:id)) @projects = admin_user.authorized_projects
end end
def team_update def team_update
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
# #
class Group < Namespace class Group < Namespace
def add_users_to_project_teams(user_ids, project_access) def add_users_to_project_teams(user_ids, project_access)
UsersProject.add_users_into_projects( UsersProject.add_users_into_projects(
projects.map(&:id), projects.map(&:id),
......
...@@ -25,19 +25,9 @@ class Issue < ActiveRecord::Base ...@@ -25,19 +25,9 @@ class Issue < ActiveRecord::Base
acts_as_taggable_on :labels acts_as_taggable_on :labels
class << self scope :cared, ->(user) { where(assignee_id: user) }
def cared(user) scope :authored, ->(user) { where(author_id: user) }
where('assignee_id = :user', user: user.id) scope :open_for, ->(user) { opened.assigned(user) }
end
def authored(user)
where('author_id = :user', user: user.id)
end
def open_for(user)
opened.assigned(user)
end
end
state_machine :state, initial: :opened do state_machine :state, initial: :opened do
event :close do event :close do
......
...@@ -23,7 +23,7 @@ class Key < ActiveRecord::Base ...@@ -23,7 +23,7 @@ class Key < ActiveRecord::Base
before_validation :strip_white_space before_validation :strip_white_space
validates :title, presence: true, length: { within: 0..255 } validates :title, presence: true, length: { within: 0..255 }
validates :key, presence: true, length: { within: 0..5000 }, format: { :with => /ssh-.{3} / }, uniqueness: true validates :key, presence: true, length: { within: 0..5000 }, format: { with: /ssh-.{3} / }, uniqueness: true
validate :fingerprintable_key validate :fingerprintable_key
delegate :name, :email, to: :user, prefix: true delegate :name, :email, to: :user, prefix: true
...@@ -48,7 +48,7 @@ class Key < ActiveRecord::Base ...@@ -48,7 +48,7 @@ class Key < ActiveRecord::Base
end end
def is_deploy_key def is_deploy_key
!!project_id project.present?
end end
# projects that has this key # projects that has this key
......
...@@ -19,6 +19,7 @@ class Milestone < ActiveRecord::Base ...@@ -19,6 +19,7 @@ class Milestone < ActiveRecord::Base
belongs_to :project belongs_to :project
has_many :issues has_many :issues
has_many :merge_requests has_many :merge_requests
has_many :participants, through: :issues, source: :assignee
scope :active, -> { with_state(:active) } scope :active, -> { with_state(:active) }
scope :closed, -> { with_state(:closed) } scope :closed, -> { with_state(:closed) }
...@@ -48,10 +49,6 @@ class Milestone < ActiveRecord::Base ...@@ -48,10 +49,6 @@ class Milestone < ActiveRecord::Base
end end
end end
def participants
User.where(id: issues.pluck(:assignee_id))
end
def open_items_count def open_items_count
self.issues.opened.count + self.merge_requests.opened.count self.issues.opened.count + self.merge_requests.opened.count
end end
......
...@@ -30,7 +30,7 @@ class Project < ActiveRecord::Base ...@@ -30,7 +30,7 @@ class Project < ActiveRecord::Base
attr_accessible :name, :path, :description, :default_branch, :issues_tracker, attr_accessible :name, :path, :description, :default_branch, :issues_tracker,
:issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :issues_enabled, :wall_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id,
:wiki_enabled, :public, :import_url, as: [:default, :admin] :wiki_enabled, :public, :import_url, :last_activity_at, as: [:default, :admin]
attr_accessible :namespace_id, :creator_id, as: :admin attr_accessible :namespace_id, :creator_id, as: :admin
...@@ -87,17 +87,18 @@ class Project < ActiveRecord::Base ...@@ -87,17 +87,18 @@ class Project < ActiveRecord::Base
validate :check_limit, :repo_name validate :check_limit, :repo_name
# Scopes # Scopes
scope :without_user, ->(user) { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) } scope :without_user, ->(user) { where("projects.id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) } scope :without_team, ->(team) { team.projects.present? ? where("projects.id NOT IN (:ids)", ids: team.projects.map(&:id)) : scoped }
scope :without_team, ->(team) { team.projects.present? ? where("id NOT IN (:ids)", ids: team.projects.map(&:id)) : scoped } scope :not_in_group, ->(group) { where("projects.id NOT IN (:ids)", ids: group.project_ids ) }
scope :in_team, ->(team) { where("id IN (:ids)", ids: team.projects.map(&:id)) } scope :in_team, ->(team) { where("projects.id IN (:ids)", ids: team.projects.map(&:id)) }
scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) } scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") } scope :in_group_namespace, -> { joins(:group) }
scope :sorted_by_activity, -> { order("projects.last_activity_at DESC") }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) } scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) } scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
scope :public_only, -> { where(public: true) } scope :public_only, -> { where(public: true) }
enumerize :issues_tracker, :in => (Gitlab.config.issues_tracker.keys).append(:gitlab), :default => :gitlab enumerize :issues_tracker, in: (Gitlab.config.issues_tracker.keys).append(:gitlab), default: :gitlab
class << self class << self
def abandoned def abandoned
...@@ -190,7 +191,7 @@ class Project < ActiveRecord::Base ...@@ -190,7 +191,7 @@ class Project < ActiveRecord::Base
end end
def last_activity_date def last_activity_date
last_event.try(:created_at) || updated_at last_activity_at || updated_at
end end
def project_id def project_id
......
...@@ -59,11 +59,10 @@ class User < ActiveRecord::Base ...@@ -59,11 +59,10 @@ class User < ActiveRecord::Base
# #
# Namespace for personal projects # Namespace for personal projects
has_one :namespace, has_one :namespace, dependent: :destroy, foreign_key: :owner_id, class_name: "Namespace", conditions: 'type IS NULL'
dependent: :destroy,
foreign_key: :owner_id, # Namespaces (owned groups and own namespace)
class_name: "Namespace", has_many :namespaces, foreign_key: :owner_id
conditions: 'type IS NULL'
# Profile # Profile
has_many :keys, dependent: :destroy has_many :keys, dependent: :destroy
...@@ -72,11 +71,7 @@ class User < ActiveRecord::Base ...@@ -72,11 +71,7 @@ class User < ActiveRecord::Base
has_many :groups, class_name: "Group", foreign_key: :owner_id has_many :groups, class_name: "Group", foreign_key: :owner_id
# Teams # Teams
has_many :own_teams, has_many :own_teams, dependent: :destroy, class_name: "UserTeam", foreign_key: :owner_id
class_name: "UserTeam",
foreign_key: :owner_id,
dependent: :destroy
has_many :user_team_user_relationships, dependent: :destroy has_many :user_team_user_relationships, dependent: :destroy
has_many :user_teams, through: :user_team_user_relationships has_many :user_teams, through: :user_team_user_relationships
has_many :user_team_project_relationships, through: :user_teams has_many :user_team_project_relationships, through: :user_teams
...@@ -88,14 +83,14 @@ class User < ActiveRecord::Base ...@@ -88,14 +83,14 @@ class User < ActiveRecord::Base
has_many :notes, dependent: :destroy, foreign_key: :author_id has_many :notes, dependent: :destroy, foreign_key: :author_id
has_many :merge_requests, dependent: :destroy, foreign_key: :author_id has_many :merge_requests, dependent: :destroy, foreign_key: :author_id
has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event" has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event"
has_many :recent_events, foreign_key: :author_id, class_name: "Event", order: "id DESC"
has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue" has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue"
has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest"
has_many :projects, through: :users_projects
has_many :recent_events, has_many :personal_projects, through: :namespace, source: :projects
class_name: "Event", has_many :projects, through: :users_projects
foreign_key: :author_id, has_many :own_projects, foreign_key: :creator_id
order: "id DESC" has_many :owned_projects, through: :namespaces, source: :projects
# #
# Validations # Validations
...@@ -109,9 +104,7 @@ class User < ActiveRecord::Base ...@@ -109,9 +104,7 @@ class User < ActiveRecord::Base
format: { with: Gitlab::Regex.username_regex, format: { with: Gitlab::Regex.username_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
validates :notification_level, validates :notification_level, inclusion: { in: Notification.notification_levels }, presence: true
inclusion: { in: Notification.notification_levels },
presence: true
validate :namespace_uniq, if: ->(user) { user.username_changed? } validate :namespace_uniq, if: ->(user) { user.username_changed? }
...@@ -145,6 +138,9 @@ class User < ActiveRecord::Base ...@@ -145,6 +138,9 @@ class User < ActiveRecord::Base
scope :alphabetically, -> { order('name ASC') } scope :alphabetically, -> { order('name ASC') }
scope :in_team, ->(team){ where(id: team.member_ids) } scope :in_team, ->(team){ where(id: team.member_ids) }
scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) } scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) }
scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : scoped }
scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)') }
scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active } scope :potential_team_members, ->(team) { team.members.any? ? active.not_in_team(team) : active }
# #
...@@ -171,18 +167,6 @@ class User < ActiveRecord::Base ...@@ -171,18 +167,6 @@ class User < ActiveRecord::Base
end end
end end
def not_in_project(project)
if project.users.present?
where("id not in (:ids)", ids: project.users.map(&:id) )
else
scoped
end
end
def without_projects
where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
end
def create_from_omniauth(auth, ldap = false) def create_from_omniauth(auth, ldap = false)
gitlab_auth.create_from_omniauth(auth, ldap) gitlab_auth.create_from_omniauth(auth, ldap)
end end
...@@ -229,51 +213,31 @@ class User < ActiveRecord::Base ...@@ -229,51 +213,31 @@ class User < ActiveRecord::Base
end end
end end
# Namespaces user has access to
def namespaces
namespaces = []
# Add user account namespace
namespaces << self.namespace if self.namespace
# Add groups you can manage
namespaces += groups.all
namespaces
end
# Groups where user is an owner # Groups where user is an owner
def owned_groups def owned_groups
groups groups
end end
def owned_teams
own_teams
end
# Groups user has access to # Groups user has access to
def authorized_groups def authorized_groups
@authorized_groups ||= begin @group_ids ||= (groups.pluck(:id) + authorized_projects.pluck(:namespace_id))
groups = Group.where(id: self.authorized_projects.pluck(:namespace_id)).all Group.where(id: @group_ids)
groups = groups + self.groups
groups.uniq
end
end end
# Projects user has access to # Projects user has access to
def authorized_projects def authorized_projects
project_ids = users_projects.pluck(:project_id) @project_ids ||= (owned_projects.pluck(:id) + projects.pluck(:id)).uniq
project_ids = project_ids | owned_projects.pluck(:id) Project.where(id: @project_ids)
Project.where(id: project_ids)
end end
# Projects in user namespace def authorized_teams
def personal_projects @team_ids ||= (user_teams.pluck(:id) + own_teams.pluck(:id)).uniq
Project.personal(self) UserTeam.where(id: @team_ids)
end
# Projects where user is an owner
def owned_projects
Project.where("(projects.namespace_id IN (:namespaces)) OR
(projects.namespace_id IS NULL AND projects.creator_id = :user_id)",
namespaces: namespaces.map(&:id), user_id: self.id)
end end
# Team membership in authorized projects # Team membership in authorized projects
...@@ -348,28 +312,13 @@ class User < ActiveRecord::Base ...@@ -348,28 +312,13 @@ class User < ActiveRecord::Base
end end
def several_namespaces? def several_namespaces?
namespaces.size > 1 namespaces.many?
end end
def namespace_id def namespace_id
namespace.try :id namespace.try :id
end end
def authorized_teams
@authorized_teams ||= begin
ids = []
ids << UserTeam.with_member(self).pluck('user_teams.id')
ids << UserTeam.created_by(self).pluck('user_teams.id')
ids.flatten
UserTeam.where(id: ids)
end
end
def owned_teams
UserTeam.where(owner_id: self.id)
end
def name_with_username def name_with_username
"#{name} (#{username})" "#{name} (#{username})"
end end
......
class ProjectActivityCacheObserver < BaseObserver
observe :event
def after_create(event)
event.project.update_attribute(:last_activity_at, event.created_at) if event.project
end
end
...@@ -24,6 +24,7 @@ module Gitlab ...@@ -24,6 +24,7 @@ module Gitlab
# Activate observers that should always be running. # Activate observers that should always be running.
config.active_record.observers = :activity_observer, config.active_record.observers = :activity_observer,
:project_activity_cache_observer,
:issue_observer, :issue_observer,
:key_observer, :key_observer,
:merge_request_observer, :merge_request_observer,
......
class AddLastActivityColumnIntoProject < ActiveRecord::Migration
def up
add_column :projects, :last_activity_at, :datetime
add_index :projects, :last_activity_at
Project.find_each do |project|
project.update_attribute(:last_activity_at, project.last_activity_date)
end
end
def down
remove_index :projects, :last_activity_at
remove_column :projects, :last_activity_at
end
end
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130404164628) do ActiveRecord::Schema.define(:version => 20130404164628) do
create_table "events", :force => true do |t| create_table "events", :force => true do |t|
t.string "target_type" t.string "target_type"
t.integer "target_id" t.integer "target_id"
......
...@@ -109,8 +109,8 @@ describe Project do ...@@ -109,8 +109,8 @@ describe Project do
describe 'last_activity_date' do describe 'last_activity_date' do
it 'returns the creation date of the project\'s last event if present' do it 'returns the creation date of the project\'s last event if present' do
project.stub(last_event: last_event) last_activity_event = create(:event, project: project)
project.last_activity_date.should == last_event.created_at project.last_activity_date.to_s(:db).should == last_event.created_at.to_s(:db)
end end
it 'returns the project\'s last update date if it has no events' do it 'returns the project\'s last update date if it has no events' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment