Blob of app/models/project.rb (raw blob data)

1 class Project < ActiveRecord::Base
2 acts_as_taggable
3
4 belongs_to :user
5 has_many :comments, :dependent => :destroy
6 has_many :repositories, :order => "repositories.mainline desc, repositories.created_at asc",
7 :dependent => :destroy
8 has_one :mainline_repository, :conditions => ["mainline = ?", true],
9 :class_name => "Repository"
10 has_many :repository_clones, :conditions => ["mainline = ?", false],
11 :class_name => "Repository"
12 has_many :events, :order => "created_at asc", :dependent => :destroy
13
14 is_indexed :fields => ["title", "description", "slug"],
15 :concatenate => [
16 { :class_name => 'Tag',
17 :field => 'name',
18 :as => 'category',
19 :association_sql => "LEFT OUTER JOIN taggings ON taggings.taggable_id = projects.id " +
20 "AND taggings.taggable_type = 'Project' LEFT OUTER JOIN tags ON taggings.tag_id = tags.id"
21 }],
22 :include => [{
23 :association_name => "user",
24 :field => "login",
25 :as => "user"
26 }]
27
28
29 URL_FORMAT_RE = /^(http|https|nntp):\/\//.freeze
30 validates_presence_of :title, :user_id, :slug, :description
31 validates_uniqueness_of :slug, :case_sensitive => false
32 validates_format_of :slug, :with => /^[a-z0-9_\-]+$/i,
33 :message => "must match something in the range of [a-z0-9_\-]+"
34 validates_format_of :home_url, :with => URL_FORMAT_RE,
35 :if => proc{|record| !record.home_url.blank? },
36 :message => "Must begin with http(s)"
37 validates_format_of :mailinglist_url, :with => URL_FORMAT_RE,
38 :if => proc{|record| !record.mailinglist_url.blank? },
39 :message => "Must begin with http(s)"
40 validates_format_of :bugtracker_url, :with => URL_FORMAT_RE,
41 :if => proc{|record| !record.bugtracker_url.blank? },
42 :message => "Must begin with http(s)"
43
44 before_validation :downcase_slug
45 after_create :create_mainline_repository
46
47 LICENSES = [
48 'Academic Free License v3.0',
49 'MIT License',
50 'BSD License',
51 'Ruby License',
52 'GNU General Public License version 2(GPLv2)',
53 'GNU General Public License version 3 (GPLv3)',
54 'GNU Lesser General Public License (LGPL)',
55 'GNU Affero General Public License (AGPLv3)',
56 'Mozilla Public License 1.0 (MPL)',
57 'Mozilla Public License 1.1 (MPL 1.1)',
58 'Qt Public License (QPL)',
59 'Python License',
60 'zlib/libpng License',
61 'Apache Software License',
62 'Apple Public Source License',
63 'Perl Artistic License',
64 'Microsoft Permissive License (Ms-PL)',
65 'ISC License',
66 'Lisp Lesser License',
67 'Public Domain',
68 'Other Open Source Initiative Approved License',
69 'Other/Proprietary License',
70 'None',
71 ]
72
73 def self.find_by_slug!(slug, opts = {})
74 find_by_slug(slug, opts) || raise(ActiveRecord::RecordNotFound)
75 end
76
77 def self.per_page() 20 end
78
79 def self.top_tags(limit = 10)
80 tag_counts(:limit => limit, :order => "count desc")
81 end
82
83 def to_param
84 slug
85 end
86
87 def admin?(candidate)
88 candidate == user
89 end
90
91 def can_be_deleted_by?(candidate)
92 (candidate == user) && (repositories.size == 1)
93 end
94
95 def tag_list=(tag_list)
96 tag_list.gsub!(",", "")
97
98 super
99 end
100
101 def home_url=(url)
102 self[:home_url] = clean_url(url)
103 end
104
105 def mailinglist_url=(url)
106 self[:mailinglist_url] = clean_url(url)
107 end
108
109 def bugtracker_url=(url)
110 self[:bugtracker_url] = clean_url(url)
111 end
112
113 def stripped_description
114 description.gsub(/<\/?[^>]*>/, "")
115 # sanitizer = HTML::WhiteListSanitizer.new
116 # sanitizer.sanitize(description, :tags => %w(str), :attributes => %w(class))
117 end
118
119 def to_xml(opts = {})
120 info = Proc.new { |options|
121 builder = options[:builder]
122 builder.owner user.login
123
124 builder.repositories :type => "array" do
125 repositories.each { |repo|
126 builder.repository do
127 builder.id repo.id
128 builder.name repo.name
129 builder.owner repo.user.login
130 end
131 }
132 end
133 }
134 super({:procs => [info]}.merge(opts))
135 end
136
137 def create_event(action_id, target, user, data = nil, body = nil, date = Time.now.utc)
138 events.create(:action => action_id, :target => target, :user => user,
139 :body => body, :data => data, :created_at => date)
140 end
141
142 protected
143 def create_mainline_repository
144 self.repositories.create!(:user => self.user, :name => "mainline")
145 end
146
147 def downcase_slug
148 slug.downcase! if slug
149 end
150
151 # Try our best to guess the url
152 def clean_url(url)
153 return if url.blank?
154 begin
155 url = "http://#{url}" if URI.parse(url).class == URI::Generic
156 rescue
157 end
158 url
159 end
160 end