Commit 76e29aed97e98044fede7f4a280abc96b80d58a6
1 parent
f678092a
Exists in
profile_api_improvements
and in
1 other branch
concerns: move most lib files models concerns
Showing
55 changed files
with
841 additions
and
831 deletions
Show diff stats
app/mailers/mailing.rb
@@ -2,7 +2,8 @@ require_dependency 'mailing_job' | @@ -2,7 +2,8 @@ require_dependency 'mailing_job' | ||
2 | 2 | ||
3 | class Mailing < ApplicationRecord | 3 | class Mailing < ApplicationRecord |
4 | 4 | ||
5 | - acts_as_having_settings :field => :data | 5 | + extend ActsAsHavingSettings::ClassMethods |
6 | + acts_as_having_settings field: :data | ||
6 | 7 | ||
7 | attr_accessible :subject, :body, :data | 8 | attr_accessible :subject, :body, :data |
8 | 9 |
app/models/article.rb
@@ -13,7 +13,9 @@ class Article < ApplicationRecord | @@ -13,7 +13,9 @@ class Article < ApplicationRecord | ||
13 | :image_builder, :show_to_followers, :archived, | 13 | :image_builder, :show_to_followers, :archived, |
14 | :author, :display_preview, :published_at, :person_followers | 14 | :author, :display_preview, :published_at, :person_followers |
15 | 15 | ||
16 | + extend ActsAsHavingImage::ClassMethods | ||
16 | acts_as_having_image | 17 | acts_as_having_image |
18 | + | ||
17 | include Noosfero::Plugin::HotSpot | 19 | include Noosfero::Plugin::HotSpot |
18 | 20 | ||
19 | SEARCHABLE_FIELDS = { | 21 | SEARCHABLE_FIELDS = { |
@@ -91,7 +93,8 @@ class Article < ApplicationRecord | @@ -91,7 +93,8 @@ class Article < ApplicationRecord | ||
91 | has_many :article_categorizations_including_virtual, :class_name => 'ArticleCategorization' | 93 | has_many :article_categorizations_including_virtual, :class_name => 'ArticleCategorization' |
92 | has_many :categories_including_virtual, :through => :article_categorizations_including_virtual, :source => :category | 94 | has_many :categories_including_virtual, :through => :article_categorizations_including_virtual, :source => :category |
93 | 95 | ||
94 | - acts_as_having_settings :field => :setting | 96 | + extend ActsAsHavingSettings::ClassMethods |
97 | + acts_as_having_settings field: :setting | ||
95 | 98 | ||
96 | settings_items :display_hits, :type => :boolean, :default => true | 99 | settings_items :display_hits, :type => :boolean, :default => true |
97 | settings_items :author_name, :type => :string, :default => "" | 100 | settings_items :author_name, :type => :string, :default => "" |
@@ -242,6 +245,7 @@ class Article < ApplicationRecord | @@ -242,6 +245,7 @@ class Article < ApplicationRecord | ||
242 | acts_as_taggable | 245 | acts_as_taggable |
243 | N_('Tag list') | 246 | N_('Tag list') |
244 | 247 | ||
248 | + extend ActsAsFilesystem::ActsMethods | ||
245 | acts_as_filesystem | 249 | acts_as_filesystem |
246 | 250 | ||
247 | acts_as_versioned | 251 | acts_as_versioned |
app/models/block.rb
@@ -17,6 +17,7 @@ class Block < ApplicationRecord | @@ -17,6 +17,7 @@ class Block < ApplicationRecord | ||
17 | belongs_to :mirror_block, :class_name => "Block" | 17 | belongs_to :mirror_block, :class_name => "Block" |
18 | has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id" | 18 | has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id" |
19 | 19 | ||
20 | + extend ActsAsHavingSettings::ClassMethods | ||
20 | acts_as_having_settings | 21 | acts_as_having_settings |
21 | 22 | ||
22 | scope :enabled, -> { where :enabled => true } | 23 | scope :enabled, -> { where :enabled => true } |
app/models/blog.rb
@@ -2,7 +2,9 @@ class Blog < Folder | @@ -2,7 +2,9 @@ class Blog < Folder | ||
2 | 2 | ||
3 | attr_accessible :visualization_format | 3 | attr_accessible :visualization_format |
4 | 4 | ||
5 | + extend ActsAsHavingPosts::ClassMethods | ||
5 | acts_as_having_posts | 6 | acts_as_having_posts |
7 | + | ||
6 | include PostsLimit | 8 | include PostsLimit |
7 | 9 | ||
8 | #FIXME This should be used until there is a migration to fix all blogs that | 10 | #FIXME This should be used until there is a migration to fix all blogs that |
app/models/category.rb
@@ -21,6 +21,7 @@ class Category < ApplicationRecord | @@ -21,6 +21,7 @@ class Category < ApplicationRecord | ||
21 | 21 | ||
22 | scope :on_level, -> parent { where :parent_id => parent } | 22 | scope :on_level, -> parent { where :parent_id => parent } |
23 | 23 | ||
24 | + extend ActsAsFilesystem::ActsMethods | ||
24 | acts_as_filesystem | 25 | acts_as_filesystem |
25 | 26 | ||
26 | has_many :article_categorizations | 27 | has_many :article_categorizations |
@@ -35,6 +36,7 @@ class Category < ApplicationRecord | @@ -35,6 +36,7 @@ class Category < ApplicationRecord | ||
35 | has_many :people, :through => :profile_categorizations, :source => :profile, :class_name => 'Person' | 36 | has_many :people, :through => :profile_categorizations, :source => :profile, :class_name => 'Person' |
36 | has_many :communities, :through => :profile_categorizations, :source => :profile, :class_name => 'Community' | 37 | has_many :communities, :through => :profile_categorizations, :source => :profile, :class_name => 'Community' |
37 | 38 | ||
39 | + extend ActsAsHavingImage::ClassMethods | ||
38 | acts_as_having_image | 40 | acts_as_having_image |
39 | 41 | ||
40 | before_save :normalize_display_color | 42 | before_save :normalize_display_color |
app/models/comment.rb
@@ -38,6 +38,7 @@ class Comment < ApplicationRecord | @@ -38,6 +38,7 @@ class Comment < ApplicationRecord | ||
38 | 38 | ||
39 | validate :article_archived? | 39 | validate :article_archived? |
40 | 40 | ||
41 | + extend ActsAsHavingSettings::ClassMethods | ||
41 | acts_as_having_settings | 42 | acts_as_having_settings |
42 | 43 | ||
43 | xss_terminate :only => [ :body, :title, :name ], :on => 'validation' | 44 | xss_terminate :only => [ :body, :title, :name ], :on => 'validation' |
@@ -0,0 +1,265 @@ | @@ -0,0 +1,265 @@ | ||
1 | +module ActsAsFilesystem | ||
2 | + | ||
3 | + module ActsMethods | ||
4 | + | ||
5 | + # Declares the ActiveRecord model to acts like a filesystem: objects are | ||
6 | + # arranged in a tree (liks acts_as_tree), and . The underlying table must | ||
7 | + # have the following fields: | ||
8 | + # | ||
9 | + # * name (+:string+) - the title of the object | ||
10 | + # * slug (+:string+)- the title turned in a URL-friendly string (downcased, | ||
11 | + # non-ascii chars transliterated into ascii, all sequences of | ||
12 | + # non-alphanumericd characters changed into dashed) | ||
13 | + # * path (+:text+)- stores the full path of the object (the full path of | ||
14 | + # the parent, a "/" and the slug of the object) | ||
15 | + # * children_count - a cache of the number of children elements. | ||
16 | + def acts_as_filesystem | ||
17 | + # a filesystem is a tree | ||
18 | + acts_as_tree :counter_cache => :children_count | ||
19 | + | ||
20 | + extend ClassMethods | ||
21 | + include InstanceMethods | ||
22 | + if self.has_path? | ||
23 | + after_update :update_children_path | ||
24 | + before_create :set_path | ||
25 | + include InstanceMethods::PathMethods | ||
26 | + end | ||
27 | + | ||
28 | + before_save :set_ancestry | ||
29 | + end | ||
30 | + | ||
31 | + end | ||
32 | + | ||
33 | + module ClassMethods | ||
34 | + | ||
35 | + def build_ancestry(parent_id = nil, ancestry = '') | ||
36 | + ActiveRecord::Base.transaction do | ||
37 | + self.base_class.where(parent_id: parent_id).each do |node| | ||
38 | + node.update_column :ancestry, ancestry | ||
39 | + | ||
40 | + build_ancestry node.id, (ancestry.empty? ? "#{node.formatted_ancestry_id}" : | ||
41 | + "#{ancestry}#{node.ancestry_sep}#{node.formatted_ancestry_id}") | ||
42 | + end | ||
43 | + end | ||
44 | + | ||
45 | + #raise "Couldn't reach and set ancestry on every record" if self.base_class.where('ancestry is null').count != 0 | ||
46 | + end | ||
47 | + | ||
48 | + def has_path? | ||
49 | + (['name', 'slug', 'path'] - self.column_names).blank? | ||
50 | + end | ||
51 | + | ||
52 | + end | ||
53 | + | ||
54 | + module InstanceMethods | ||
55 | + | ||
56 | + def ancestry_column | ||
57 | + 'ancestry' | ||
58 | + end | ||
59 | + def ancestry_sep | ||
60 | + '.' | ||
61 | + end | ||
62 | + def has_ancestry? | ||
63 | + self.class.column_names.include? self.ancestry_column | ||
64 | + end | ||
65 | + | ||
66 | + def formatted_ancestry_id | ||
67 | + "%010d" % self.id if self.id | ||
68 | + end | ||
69 | + | ||
70 | + def ancestry | ||
71 | + self[ancestry_column] | ||
72 | + end | ||
73 | + def ancestor_ids | ||
74 | + return nil if !has_ancestry? or ancestry.nil? | ||
75 | + @ancestor_ids ||= ancestry.split(ancestry_sep).map{ |id| id.to_i } | ||
76 | + end | ||
77 | + | ||
78 | + def ancestry=(value) | ||
79 | + self[ancestry_column] = value | ||
80 | + end | ||
81 | + def set_ancestry | ||
82 | + return unless self.has_ancestry? | ||
83 | + if self.ancestry.nil? or (new_record? or parent_id_changed?) or recalculate_path | ||
84 | + self.ancestry = self.hierarchy(true)[0...-1].map{ |p| p.formatted_ancestry_id }.join(ancestry_sep) | ||
85 | + end | ||
86 | + end | ||
87 | + | ||
88 | + def descendents_options | ||
89 | + ["#{self.ancestry_column} LIKE ?", "%#{self.formatted_ancestry_id}%"] | ||
90 | + end | ||
91 | + def descendents | ||
92 | + self.class.where descendents_options | ||
93 | + end | ||
94 | + | ||
95 | + # calculates the level of the record in the records hierarchy. Top-level | ||
96 | + # records have level 0; the children of the top-level records have | ||
97 | + # level 1; the children of records with level 1 have level 2, and so on. | ||
98 | + # | ||
99 | + # A level 0 | ||
100 | + # / \ | ||
101 | + # B C level 1 | ||
102 | + # / \ / \ | ||
103 | + # E F G H level 2 | ||
104 | + # ... | ||
105 | + def level | ||
106 | + self.hierarchy.size - 1 | ||
107 | + end | ||
108 | + | ||
109 | + # Is this record a top-level record? | ||
110 | + def top_level? | ||
111 | + self.parent.nil? | ||
112 | + end | ||
113 | + | ||
114 | + # Is this record a leaf in the hierarchy tree of records? | ||
115 | + # | ||
116 | + # Being a leaf means that this record has no subrecord. | ||
117 | + def leaf? | ||
118 | + self.children.empty? | ||
119 | + end | ||
120 | + | ||
121 | + def top_ancestor | ||
122 | + if has_ancestry? and !ancestry.blank? | ||
123 | + self.class.base_class.find_by id: self.top_ancestor_id | ||
124 | + else | ||
125 | + self.hierarchy.first | ||
126 | + end | ||
127 | + end | ||
128 | + def top_ancestor_id | ||
129 | + if has_ancestry? and !ancestry.nil? | ||
130 | + self.ancestor_ids.first | ||
131 | + else | ||
132 | + self.hierarchy.first.id | ||
133 | + end | ||
134 | + end | ||
135 | + | ||
136 | + # returns the full hierarchy from the top-level item to this one. For | ||
137 | + # example, if item1 has a children item2 and item2 has a children item3, | ||
138 | + # then item3's hierarchy would be [item1, item2, item3]. | ||
139 | + # | ||
140 | + # If +reload+ is passed as +true+, then the hierarchy is reload (usefull | ||
141 | + # when the ActiveRecord object was modified in some way, or just after | ||
142 | + # changing parent) | ||
143 | + def hierarchy(reload = false) | ||
144 | + @hierarchy = nil if reload or recalculate_path | ||
145 | + | ||
146 | + if @hierarchy.nil? | ||
147 | + @hierarchy = [] | ||
148 | + | ||
149 | + if !reload and !recalculate_path and ancestor_ids | ||
150 | + objects = self.class.base_class.where(id: ancestor_ids) | ||
151 | + ancestor_ids.each{ |id| @hierarchy << objects.find{ |t| t.id == id } } | ||
152 | + @hierarchy << self | ||
153 | + else | ||
154 | + item = self | ||
155 | + while item | ||
156 | + @hierarchy.unshift(item) | ||
157 | + item = item.parent | ||
158 | + end | ||
159 | + end | ||
160 | + end | ||
161 | + | ||
162 | + @hierarchy | ||
163 | + end | ||
164 | + | ||
165 | + def map_traversal(&block) | ||
166 | + result = [] | ||
167 | + current_level = [self] | ||
168 | + | ||
169 | + while !current_level.empty? | ||
170 | + result += current_level | ||
171 | + ids = current_level.select {|item| item.children_count > 0}.map(&:id) | ||
172 | + break if ids.empty? | ||
173 | + current_level = self.class.base_class.where(parent_id: ids) | ||
174 | + end | ||
175 | + block ||= (lambda { |x| x }) | ||
176 | + result.map(&block) | ||
177 | + end | ||
178 | + | ||
179 | + def all_children | ||
180 | + res = map_traversal | ||
181 | + res.shift | ||
182 | + res | ||
183 | + end | ||
184 | + | ||
185 | + ##### | ||
186 | + # Path methods | ||
187 | + # These methods are used when _path_, _name_ and _slug_ attributes exist | ||
188 | + # and should be calculated based on the tree | ||
189 | + ##### | ||
190 | + module PathMethods | ||
191 | + # used to know when to trigger batch renaming | ||
192 | + attr_accessor :recalculate_path | ||
193 | + | ||
194 | + # calculates the full path to this record using parent's path. | ||
195 | + def calculate_path | ||
196 | + self.hierarchy.map{ |obj| obj.slug }.join('/') | ||
197 | + end | ||
198 | + def set_path | ||
199 | + if self.path == self.slug && !self.top_level? | ||
200 | + self.path = self.calculate_path | ||
201 | + end | ||
202 | + end | ||
203 | + def explode_path | ||
204 | + path.split(/\//) | ||
205 | + end | ||
206 | + | ||
207 | + def update_children_path | ||
208 | + if self.recalculate_path | ||
209 | + self.children.each do |child| | ||
210 | + child.path = child.calculate_path | ||
211 | + child.recalculate_path = true | ||
212 | + child.save! | ||
213 | + end | ||
214 | + end | ||
215 | + self.recalculate_path = false | ||
216 | + end | ||
217 | + | ||
218 | + # calculates the full name of a record by accessing the name of all its | ||
219 | + # ancestors. | ||
220 | + # | ||
221 | + # If you have this record hierarchy: | ||
222 | + # Record "A" | ||
223 | + # Record "B" | ||
224 | + # Record "C" | ||
225 | + # | ||
226 | + # Then Record "C" will have "A/B/C" as its full name. | ||
227 | + def full_name(sep = '/') | ||
228 | + self.hierarchy.map {|item| item.name || '?' }.join(sep) | ||
229 | + end | ||
230 | + | ||
231 | + # gets the name without leading parents. Useful when dividing records | ||
232 | + # in top-level groups and full names must not include the top-level | ||
233 | + # record which is already a emphasized label | ||
234 | + def full_name_without_leading(count, sep = '/') | ||
235 | + parts = self.full_name(sep).split(sep) | ||
236 | + count.times { parts.shift } | ||
237 | + parts.join(sep) | ||
238 | + end | ||
239 | + | ||
240 | + def set_name(value) | ||
241 | + if self.name != value | ||
242 | + self.recalculate_path = true | ||
243 | + end | ||
244 | + self[:name] = value | ||
245 | + end | ||
246 | + | ||
247 | + # sets the name of the record. Also sets #slug accordingly. | ||
248 | + def name=(value) | ||
249 | + self.set_name(value) | ||
250 | + unless self.name.blank? | ||
251 | + self.slug = self.name.to_slug | ||
252 | + end | ||
253 | + end | ||
254 | + | ||
255 | + # sets the slug of the record. Also sets the path with the new slug value. | ||
256 | + def slug=(value) | ||
257 | + self[:slug] = value | ||
258 | + unless self.slug.blank? | ||
259 | + self.path = self.calculate_path | ||
260 | + end | ||
261 | + end | ||
262 | + end | ||
263 | + end | ||
264 | +end | ||
265 | + |
@@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
1 | +module ActsAsHavingBoxes | ||
2 | + | ||
3 | + module ClassMethods | ||
4 | + def acts_as_having_boxes | ||
5 | + has_many :boxes, -> { order :position }, as: :owner, dependent: :destroy | ||
6 | + self.send(:include, ActsAsHavingBoxes) | ||
7 | + end | ||
8 | + end | ||
9 | + | ||
10 | + module BlockArray | ||
11 | + def find(id) | ||
12 | + select { |item| item.id == id.to_i }.first | ||
13 | + end | ||
14 | + end | ||
15 | + | ||
16 | + def blocks(reload = false) | ||
17 | + if (reload) | ||
18 | + @blocks = nil | ||
19 | + end | ||
20 | + if @blocks.nil? | ||
21 | + @blocks = boxes.includes(:blocks).inject([]) do |acc,obj| | ||
22 | + acc.concat(obj.blocks) | ||
23 | + end | ||
24 | + @blocks.send(:extend, BlockArray) | ||
25 | + end | ||
26 | + @blocks | ||
27 | + end | ||
28 | + | ||
29 | + # returns 3 unless the class table has a boxes_limit column. In that case | ||
30 | + # return the value of the column. | ||
31 | + def boxes_limit layout_template = nil | ||
32 | + layout_template ||= self.layout_template | ||
33 | + @boxes_limit ||= LayoutTemplate.find(layout_template).number_of_boxes || 3 | ||
34 | + end | ||
35 | + | ||
36 | +end | ||
37 | + |
@@ -0,0 +1,25 @@ | @@ -0,0 +1,25 @@ | ||
1 | +module ActsAsHavingImage | ||
2 | + | ||
3 | + module ClassMethods | ||
4 | + def acts_as_having_image | ||
5 | + belongs_to :image, dependent: :destroy | ||
6 | + scope :with_image, -> { where "#{table_name}.image_id IS NOT NULL" } | ||
7 | + scope :without_image, -> { where "#{table_name}.image_id IS NULL" } | ||
8 | + attr_accessible :image_builder | ||
9 | + include ActsAsHavingImage | ||
10 | + end | ||
11 | + end | ||
12 | + | ||
13 | + def image_builder=(img) | ||
14 | + if image && image.id == img[:id] | ||
15 | + image.attributes = img | ||
16 | + else | ||
17 | + build_image(img) | ||
18 | + end unless img[:uploaded_data].blank? | ||
19 | + if img[:remove_image] == 'true' | ||
20 | + self.image_id = nil | ||
21 | + end | ||
22 | + end | ||
23 | + | ||
24 | +end | ||
25 | + |
@@ -0,0 +1,49 @@ | @@ -0,0 +1,49 @@ | ||
1 | +module ActsAsHavingPosts | ||
2 | + | ||
3 | + module ClassMethods | ||
4 | + def acts_as_having_posts(scope = nil) | ||
5 | + has_many :posts, -> { | ||
6 | + s = order('published_at DESC, id DESC').where('articles.type != ?', 'RssFeed') | ||
7 | + s = s.instance_exec(&scope) if scope | ||
8 | + s | ||
9 | + }, class_name: 'Article', foreign_key: 'parent_id', source: :children | ||
10 | + | ||
11 | + attr_accessor :feed_attrs | ||
12 | + | ||
13 | + after_create do |blog| | ||
14 | + blog.children << RssFeed.new(:name => 'feed', :profile => blog.profile) | ||
15 | + blog.feed = blog.feed_attrs | ||
16 | + end | ||
17 | + | ||
18 | + settings_items :posts_per_page, :type => :integer, :default => 5 | ||
19 | + | ||
20 | + self.send(:include, ActsAsHavingPosts) | ||
21 | + end | ||
22 | + end | ||
23 | + | ||
24 | + def has_posts? | ||
25 | + true | ||
26 | + end | ||
27 | + | ||
28 | + def feed | ||
29 | + children.where(:type => 'RssFeed').first | ||
30 | + end | ||
31 | + | ||
32 | + def feed=(attrs) | ||
33 | + if attrs | ||
34 | + if self.feed | ||
35 | + self.feed.update(attrs) | ||
36 | + else | ||
37 | + self.feed_attrs = attrs | ||
38 | + end | ||
39 | + end | ||
40 | + self.feed | ||
41 | + end | ||
42 | + | ||
43 | + def name=(value) | ||
44 | + self.set_name(value) | ||
45 | + self.slug = self.slug.blank? ? self.name.to_slug : self.slug.to_slug | ||
46 | + end | ||
47 | + | ||
48 | +end | ||
49 | + |
@@ -0,0 +1,89 @@ | @@ -0,0 +1,89 @@ | ||
1 | +# declare missing types | ||
2 | +module ActiveRecord | ||
3 | + module Type | ||
4 | + class Symbol < Value | ||
5 | + def cast_value value | ||
6 | + value.to_sym | ||
7 | + end | ||
8 | + end | ||
9 | + class Array < Value | ||
10 | + def cast_value value | ||
11 | + ::Array.wrap(value) | ||
12 | + end | ||
13 | + end | ||
14 | + class Hash < Value | ||
15 | + def cast_value value | ||
16 | + h = ::Hash[value] | ||
17 | + h.symbolize_keys! | ||
18 | + h | ||
19 | + end | ||
20 | + end | ||
21 | + end | ||
22 | +end | ||
23 | + | ||
24 | +module ActsAsHavingSettings | ||
25 | + | ||
26 | + def self.type_cast value, type | ||
27 | + # do not cast nil | ||
28 | + return value if value.nil? | ||
29 | + type.send :cast_value, value | ||
30 | + end | ||
31 | + | ||
32 | + module ClassMethods | ||
33 | + | ||
34 | + def acts_as_having_settings(*args) | ||
35 | + options = args.last.is_a?(Hash) ? args.pop : {} | ||
36 | + field = (options[:field] || :settings).to_sym | ||
37 | + | ||
38 | + serialize field, Hash | ||
39 | + class_attribute :settings_field | ||
40 | + self.settings_field = field | ||
41 | + | ||
42 | + class_eval do | ||
43 | + def settings_field | ||
44 | + self[self.class.settings_field] ||= Hash.new | ||
45 | + end | ||
46 | + | ||
47 | + def setting_changed? setting_field | ||
48 | + setting_field = setting_field.to_sym | ||
49 | + changed_settings = self.changes[self.class.settings_field] | ||
50 | + return false if changed_settings.nil? | ||
51 | + | ||
52 | + old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field] | ||
53 | + new_setting_value = changed_settings.last[setting_field] | ||
54 | + old_setting_value != new_setting_value | ||
55 | + end | ||
56 | + end | ||
57 | + | ||
58 | + settings_items *args | ||
59 | + end | ||
60 | + | ||
61 | + def settings_items *names | ||
62 | + | ||
63 | + options = names.extract_options! | ||
64 | + default = options[:default] | ||
65 | + type = options[:type] | ||
66 | + type = if type.present? then ActiveRecord::Type.const_get(type.to_s.camelize.to_sym).new else nil end | ||
67 | + | ||
68 | + names.each do |setting| | ||
69 | + # symbolize key | ||
70 | + setting = setting.to_sym | ||
71 | + | ||
72 | + define_method setting do | ||
73 | + h = send self.class.settings_field | ||
74 | + val = h[setting] | ||
75 | + # translate default value if it is used | ||
76 | + if not val.nil? then val elsif default.is_a? String then gettext default else default end | ||
77 | + end | ||
78 | + | ||
79 | + define_method "#{setting}=" do |value| | ||
80 | + h = send self.class.settings_field | ||
81 | + h[setting] = if type then ActsAsHavingSettings.type_cast value, type else value end | ||
82 | + end | ||
83 | + end | ||
84 | + end | ||
85 | + | ||
86 | + end | ||
87 | + | ||
88 | +end | ||
89 | + |
@@ -0,0 +1,57 @@ | @@ -0,0 +1,57 @@ | ||
1 | +module CodeNumbering | ||
2 | + module ClassMethods | ||
3 | + def code_numbering field, options = {} | ||
4 | + class_attribute :code_numbering_field | ||
5 | + class_attribute :code_numbering_options | ||
6 | + | ||
7 | + self.code_numbering_field = field | ||
8 | + self.code_numbering_options = options | ||
9 | + | ||
10 | + before_create :create_code_numbering | ||
11 | + | ||
12 | + include CodeNumbering::InstanceMethods | ||
13 | + end | ||
14 | + end | ||
15 | + | ||
16 | + module InstanceMethods | ||
17 | + | ||
18 | + def code | ||
19 | + self.attributes[self.code_numbering_field.to_s] | ||
20 | + end | ||
21 | + | ||
22 | + def code_scope | ||
23 | + scope = self.code_numbering_options[:scope] | ||
24 | + case scope | ||
25 | + when Symbol | ||
26 | + self.send scope | ||
27 | + when Proc | ||
28 | + instance_exec &scope | ||
29 | + else | ||
30 | + self.class | ||
31 | + end | ||
32 | + end | ||
33 | + | ||
34 | + def code_maximum | ||
35 | + self.code_scope.maximum(self.code_numbering_field) || 0 | ||
36 | + end | ||
37 | + | ||
38 | + def create_code_numbering | ||
39 | + max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start] | ||
40 | + max = self.code_maximum | ||
41 | + self.send "#{self.code_numbering_field}=", max+1 | ||
42 | + end | ||
43 | + | ||
44 | + def reset_scope_code_numbering | ||
45 | + max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start] | ||
46 | + max ||= 1 | ||
47 | + | ||
48 | + self.code_scope.order(:created_at).each do |record| | ||
49 | + record.update_column self.code_numbering_field, max | ||
50 | + max += 1 | ||
51 | + end | ||
52 | + self.reload | ||
53 | + end | ||
54 | + | ||
55 | + end | ||
56 | +end | ||
57 | + |
@@ -0,0 +1,124 @@ | @@ -0,0 +1,124 @@ | ||
1 | +module Customizable | ||
2 | + | ||
3 | + def self.included(base) | ||
4 | + base.attr_accessible :custom_values | ||
5 | + base.extend ClassMethods | ||
6 | + end | ||
7 | + | ||
8 | + module ClassMethods | ||
9 | + def acts_as_customizable(options = {}) | ||
10 | + attr_accessor :custom_values | ||
11 | + has_many :custom_field_values, :dependent => :delete_all, :as => :customized | ||
12 | + send :include, Customizable::InstanceMethods | ||
13 | + after_save :save_custom_values | ||
14 | + validate :valid_custom_values? | ||
15 | + end | ||
16 | + | ||
17 | + def active_custom_fields environment | ||
18 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.active} | ||
19 | + end | ||
20 | + | ||
21 | + def required_custom_fields environment | ||
22 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.required} | ||
23 | + end | ||
24 | + | ||
25 | + def signup_custom_fields environment | ||
26 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.signup} | ||
27 | + end | ||
28 | + | ||
29 | + def custom_fields environment | ||
30 | + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type)} | ||
31 | + end | ||
32 | + | ||
33 | + def customized_ancestors_list | ||
34 | + current=self | ||
35 | + result=[] | ||
36 | + while current.instance_methods.include? :custom_value do | ||
37 | + result << current.name | ||
38 | + current=current.superclass | ||
39 | + end | ||
40 | + result | ||
41 | + end | ||
42 | + | ||
43 | + end | ||
44 | + | ||
45 | + module InstanceMethods | ||
46 | + | ||
47 | + def valid_custom_values? | ||
48 | + is_valid = true | ||
49 | + parse_custom_values.each do |cv| | ||
50 | + unless cv.valid? | ||
51 | + name = cv.custom_field.name | ||
52 | + errors.add(name, cv.errors.messages[name.to_sym].first) | ||
53 | + is_valid = false | ||
54 | + end | ||
55 | + end | ||
56 | + is_valid | ||
57 | + end | ||
58 | + | ||
59 | + def customized_class | ||
60 | + current=self.class | ||
61 | + while current.instance_methods.include? :custom_fields do | ||
62 | + result=current | ||
63 | + current=current.superclass | ||
64 | + end | ||
65 | + result.name | ||
66 | + end | ||
67 | + | ||
68 | + def is_public(field_name) | ||
69 | + cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name} | ||
70 | + cv.nil? ? false : cv.public | ||
71 | + end | ||
72 | + | ||
73 | + def public_values | ||
74 | + self.custom_field_values.select{|cv| cv.public} | ||
75 | + end | ||
76 | + | ||
77 | + def custom_value(field_name) | ||
78 | + cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name} | ||
79 | + cv.nil? ? default_value_for(field_name) : cv.value | ||
80 | + end | ||
81 | + | ||
82 | + def default_value_for(field_name) | ||
83 | + field=self.class.custom_fields(environment).detect {|c| c.name == field_name} | ||
84 | + field.nil? ? nil : field.default_value | ||
85 | + end | ||
86 | + | ||
87 | + def parse_custom_values | ||
88 | + return_list = [] | ||
89 | + return return_list if custom_values.blank? | ||
90 | + custom_values.each_pair do |key, value| | ||
91 | + custom_field = environment.custom_fields.detect{|cf|cf.name==key} | ||
92 | + next if custom_field.blank? | ||
93 | + custom_field_value = self.custom_field_values(true).detect{|cv| cv.custom_field.name==key} | ||
94 | + | ||
95 | + if custom_field_value.nil? | ||
96 | + custom_field_value = CustomFieldValue.new | ||
97 | + custom_field_value.custom_field = custom_field | ||
98 | + custom_field_value.customized = self | ||
99 | + end | ||
100 | + | ||
101 | + if value.is_a?(Hash) | ||
102 | + custom_field_value.value = value['value'].to_s | ||
103 | + if value.has_key?('public') | ||
104 | + is_public = value['public']=="true" || value['public']==true | ||
105 | + custom_field_value.public = is_public | ||
106 | + else | ||
107 | + custom_field_value.public = false | ||
108 | + end | ||
109 | + else | ||
110 | + custom_field_value.value = value.to_s | ||
111 | + custom_field_value.public = false | ||
112 | + end | ||
113 | + return_list << custom_field_value | ||
114 | + end | ||
115 | + return_list | ||
116 | + end | ||
117 | + | ||
118 | + def save_custom_values | ||
119 | + parse_custom_values.each(&:save) | ||
120 | + end | ||
121 | + | ||
122 | + end | ||
123 | +end | ||
124 | + |
@@ -0,0 +1,55 @@ | @@ -0,0 +1,55 @@ | ||
1 | +module DelayedAttachmentFu | ||
2 | + | ||
3 | + module ClassMethods | ||
4 | + def delay_attachment_fu_thumbnails | ||
5 | + include DelayedAttachmentFu::InstanceMethods | ||
6 | + after_create do |file| | ||
7 | + if file.thumbnailable? | ||
8 | + Delayed::Job.enqueue CreateThumbnailsJob.new(file.class.name, file.id) | ||
9 | + end | ||
10 | + end | ||
11 | + end | ||
12 | + end | ||
13 | + | ||
14 | + module InstanceMethods | ||
15 | + # skip processing with RMagick | ||
16 | + def process_attachment | ||
17 | + end | ||
18 | + | ||
19 | + def after_process_attachment | ||
20 | + save_to_storage | ||
21 | + @temp_paths.clear | ||
22 | + @saved_attachment = nil | ||
23 | + run_callbacks :after_attachment_saved | ||
24 | + end | ||
25 | + | ||
26 | + def create_thumbnails | ||
27 | + if thumbnailable? | ||
28 | + self.class.with_image(full_filename) do |img| | ||
29 | + self.width = img.columns | ||
30 | + self.height = img.rows | ||
31 | + self.save! | ||
32 | + end | ||
33 | + self.class.attachment_options[:thumbnails].each do |suffix, size| | ||
34 | + self.create_or_update_thumbnail(self.full_filename, suffix, size) | ||
35 | + end | ||
36 | + self.thumbnails_processed = true | ||
37 | + self.save! | ||
38 | + end | ||
39 | + end | ||
40 | + | ||
41 | + def public_filename(size=nil) | ||
42 | + force, size = true, nil if size == :uploaded | ||
43 | + if !self.thumbnailable? || self.thumbnails_processed || force | ||
44 | + super size | ||
45 | + else | ||
46 | + size ||= :thumb | ||
47 | + '/images/icons-app/image-loading-%s.png' % size | ||
48 | + end | ||
49 | + end | ||
50 | + | ||
51 | + | ||
52 | + end | ||
53 | +end | ||
54 | + | ||
55 | + |
app/models/concerns/set_profile_region_from_city_state.rb
0 → 100644
@@ -0,0 +1,44 @@ | @@ -0,0 +1,44 @@ | ||
1 | +module SetProfileRegionFromCityState | ||
2 | + | ||
3 | + module ClassMethods | ||
4 | + def set_profile_region_from_city_state | ||
5 | + before_save :region_from_city_and_state | ||
6 | + | ||
7 | + include InstanceMethods | ||
8 | + alias_method_chain :city=, :region | ||
9 | + alias_method_chain :state=, :region | ||
10 | + end | ||
11 | + end | ||
12 | + | ||
13 | + module InstanceMethods | ||
14 | + include Noosfero::Plugin::HotSpot | ||
15 | + | ||
16 | + def city_with_region=(value) | ||
17 | + self.city_without_region = value | ||
18 | + @change_region = true | ||
19 | + end | ||
20 | + | ||
21 | + def state_with_region=(value) | ||
22 | + self.state_without_region = value | ||
23 | + @change_region = true | ||
24 | + end | ||
25 | + | ||
26 | + def region_from_city_and_state | ||
27 | + if @change_region | ||
28 | + self.region = nil | ||
29 | + state = search_region(State, self.state) | ||
30 | + self.region = search_region(City.where(:parent_id => state.id), self.city) if state | ||
31 | + end | ||
32 | + end | ||
33 | + | ||
34 | + private | ||
35 | + | ||
36 | + def search_region(scope, query) | ||
37 | + return nil if !query | ||
38 | + query = query.downcase.strip | ||
39 | + scope.where(['lower(name)=? OR lower(abbreviation)=? OR lower(acronym)=?', query, query, query]).first | ||
40 | + end | ||
41 | + | ||
42 | + end | ||
43 | + | ||
44 | +end |
@@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
1 | +module WhiteListFilter | ||
2 | + | ||
3 | + def check_iframe_on_content(content, trusted_sites) | ||
4 | + if content.blank? || !content.include?('iframe') | ||
5 | + return content | ||
6 | + end | ||
7 | + content.gsub!(/<iframe[^>]*>\s*<\/iframe>/i) do |iframe| | ||
8 | + result = '' | ||
9 | + unless iframe =~ /src=['"].*src=['"]/ | ||
10 | + trusted_sites.each do |trusted_site| | ||
11 | + re_dom = trusted_site.gsub('.', '\.') | ||
12 | + if iframe =~ /src=["'](https?:)?\/\/(www\.)?#{re_dom}\// | ||
13 | + result = iframe | ||
14 | + end | ||
15 | + end | ||
16 | + end | ||
17 | + result | ||
18 | + end | ||
19 | + content | ||
20 | + end | ||
21 | + | ||
22 | + module ClassMethods | ||
23 | + def filter_iframes(*opts) | ||
24 | + options = opts.last.is_a?(Hash) && opts.pop || {} | ||
25 | + white_list_method = options[:whitelist] || :iframe_whitelist | ||
26 | + opts.each do |field| | ||
27 | + before_validation do |obj| | ||
28 | + obj.check_iframe_on_content(obj.send(field), obj.send(white_list_method)) | ||
29 | + end | ||
30 | + end | ||
31 | + end | ||
32 | + end | ||
33 | + | ||
34 | + def self.included(c) | ||
35 | + c.send(:extend, WhiteListFilter::ClassMethods) | ||
36 | + end | ||
37 | +end |
app/models/create_community.rb
@@ -12,6 +12,7 @@ class CreateCommunity < Task | @@ -12,6 +12,7 @@ class CreateCommunity < Task | ||
12 | attr_accessible :environment, :requestor, :target | 12 | attr_accessible :environment, :requestor, :target |
13 | attr_accessible :reject_explanation, :template_id | 13 | attr_accessible :reject_explanation, :template_id |
14 | 14 | ||
15 | + extend ActsAsHavingImage::ClassMethods | ||
15 | acts_as_having_image | 16 | acts_as_having_image |
16 | 17 | ||
17 | DATA_FIELDS = Community.fields + ['name', 'closed', 'description'] | 18 | DATA_FIELDS = Community.fields + ['name', 'closed', 'description'] |
app/models/environment.rb
@@ -200,6 +200,7 @@ class Environment < ApplicationRecord | @@ -200,6 +200,7 @@ class Environment < ApplicationRecord | ||
200 | # Relationships and applied behaviour | 200 | # Relationships and applied behaviour |
201 | # ################################################# | 201 | # ################################################# |
202 | 202 | ||
203 | + extend ActsAsHavingBoxes::ClassMethods | ||
203 | acts_as_having_boxes | 204 | acts_as_having_boxes |
204 | 205 | ||
205 | after_create do |env| | 206 | after_create do |env| |
@@ -251,7 +252,8 @@ class Environment < ApplicationRecord | @@ -251,7 +252,8 @@ class Environment < ApplicationRecord | ||
251 | # ################################################# | 252 | # ################################################# |
252 | 253 | ||
253 | # store the Environment settings as YAML-serialized Hash. | 254 | # store the Environment settings as YAML-serialized Hash. |
254 | - acts_as_having_settings :field => :settings | 255 | + extend ActsAsHavingSettings::ClassMethods |
256 | + acts_as_having_settings field: :settings | ||
255 | 257 | ||
256 | # introduce and explain to users something about the signup | 258 | # introduce and explain to users something about the signup |
257 | settings_items :signup_intro, :type => String | 259 | settings_items :signup_intro, :type => String |
app/models/event.rb
1 | -require 'noosfero/translatable_content' | ||
2 | require 'builder' | 1 | require 'builder' |
3 | 2 | ||
4 | class Event < Article | 3 | class Event < Article |
@@ -138,7 +137,7 @@ class Event < Article | @@ -138,7 +137,7 @@ class Event < Article | ||
138 | false | 137 | false |
139 | end | 138 | end |
140 | 139 | ||
141 | - include Noosfero::TranslatableContent | 140 | + include TranslatableContent |
142 | include MaybeAddHttp | 141 | include MaybeAddHttp |
143 | 142 | ||
144 | end | 143 | end |
app/models/folder.rb
@@ -10,7 +10,8 @@ class Folder < Article | @@ -10,7 +10,8 @@ class Folder < Article | ||
10 | errors.add(:parent, "A folder should not belong to a blog.") if parent && parent.blog? | 10 | errors.add(:parent, "A folder should not belong to a blog.") if parent && parent.blog? |
11 | end | 11 | end |
12 | 12 | ||
13 | - acts_as_having_settings :field => :setting | 13 | + extend ActsAsHavingSettings::ClassMethods |
14 | + acts_as_having_settings field: :setting | ||
14 | 15 | ||
15 | xss_terminate :only => [ :name, :body ], :with => 'white_list', :on => 'validation' | 16 | xss_terminate :only => [ :name, :body ], :with => 'white_list', :on => 'validation' |
16 | 17 |
app/models/forum.rb
1 | class Forum < Folder | 1 | class Forum < Folder |
2 | 2 | ||
3 | + extend ActsAsHavingPosts::ClassMethods | ||
3 | acts_as_having_posts -> { reorder 'updated_at DESC' } | 4 | acts_as_having_posts -> { reorder 'updated_at DESC' } |
5 | + | ||
4 | include PostsLimit | 6 | include PostsLimit |
5 | 7 | ||
6 | attr_accessible :has_terms_of_use, :terms_of_use, :topic_creation | 8 | attr_accessible :has_terms_of_use, :terms_of_use, :topic_creation |
app/models/image.rb
@@ -23,6 +23,7 @@ class Image < ApplicationRecord | @@ -23,6 +23,7 @@ class Image < ApplicationRecord | ||
23 | 23 | ||
24 | validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n | 24 | validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n |
25 | 25 | ||
26 | + extend DelayedAttachmentFu::ClassMethods | ||
26 | delay_attachment_fu_thumbnails | 27 | delay_attachment_fu_thumbnails |
27 | 28 | ||
28 | postgresql_attachment_fu | 29 | postgresql_attachment_fu |
app/models/profile.rb
@@ -88,6 +88,8 @@ class Profile < ApplicationRecord | @@ -88,6 +88,8 @@ class Profile < ApplicationRecord | ||
88 | } | 88 | } |
89 | 89 | ||
90 | acts_as_accessible | 90 | acts_as_accessible |
91 | + | ||
92 | + include Customizable | ||
91 | acts_as_customizable | 93 | acts_as_customizable |
92 | 94 | ||
93 | include Noosfero::Plugin::HotSpot | 95 | include Noosfero::Plugin::HotSpot |
@@ -185,6 +187,7 @@ class Profile < ApplicationRecord | @@ -185,6 +187,7 @@ class Profile < ApplicationRecord | ||
185 | Person.members_of(self).by_role(roles) | 187 | Person.members_of(self).by_role(roles) |
186 | end | 188 | end |
187 | 189 | ||
190 | + extend ActsAsHavingBoxes::ClassMethods | ||
188 | acts_as_having_boxes | 191 | acts_as_having_boxes |
189 | 192 | ||
190 | acts_as_taggable | 193 | acts_as_taggable |
@@ -231,7 +234,8 @@ class Profile < ApplicationRecord | @@ -231,7 +234,8 @@ class Profile < ApplicationRecord | ||
231 | scrap.nil? ? Scrap.all_scraps(self) : Scrap.all_scraps(self).find(scrap) | 234 | scrap.nil? ? Scrap.all_scraps(self) : Scrap.all_scraps(self).find(scrap) |
232 | end | 235 | end |
233 | 236 | ||
234 | - acts_as_having_settings :field => :data | 237 | + extend ActsAsHavingSettings::ClassMethods |
238 | + acts_as_having_settings field: :data | ||
235 | 239 | ||
236 | def settings | 240 | def settings |
237 | data | 241 | data |
@@ -285,6 +289,7 @@ class Profile < ApplicationRecord | @@ -285,6 +289,7 @@ class Profile < ApplicationRecord | ||
285 | 289 | ||
286 | has_many :files, :class_name => 'UploadedFile' | 290 | has_many :files, :class_name => 'UploadedFile' |
287 | 291 | ||
292 | + extend ActsAsHavingImage::ClassMethods | ||
288 | acts_as_having_image | 293 | acts_as_having_image |
289 | 294 | ||
290 | has_many :tasks, :dependent => :destroy, :as => 'target' | 295 | has_many :tasks, :dependent => :destroy, :as => 'target' |
app/models/profile_suggestion.rb
@@ -17,7 +17,8 @@ class ProfileSuggestion < ApplicationRecord | @@ -17,7 +17,8 @@ class ProfileSuggestion < ApplicationRecord | ||
17 | self.class.generate_profile_suggestions(profile_suggestion.person) | 17 | self.class.generate_profile_suggestions(profile_suggestion.person) |
18 | end | 18 | end |
19 | 19 | ||
20 | - acts_as_having_settings :field => :categories | 20 | + extend ActsAsHavingSettings::ClassMethods |
21 | + acts_as_having_settings field: :categories | ||
21 | 22 | ||
22 | validate :must_be_a_valid_category, :on => :create | 23 | validate :must_be_a_valid_category, :on => :create |
23 | def must_be_a_valid_category | 24 | def must_be_a_valid_category |
app/models/task.rb
@@ -11,7 +11,8 @@ | @@ -11,7 +11,8 @@ | ||
11 | # will need to declare <ttserialize</tt> itself). | 11 | # will need to declare <ttserialize</tt> itself). |
12 | class Task < ApplicationRecord | 12 | class Task < ApplicationRecord |
13 | 13 | ||
14 | - acts_as_having_settings :field => :data | 14 | + extend ActsAsHavingSettings::ClassMethods |
15 | + acts_as_having_settings field: :data | ||
15 | 16 | ||
16 | module Status | 17 | module Status |
17 | # the status of tasks just created | 18 | # the status of tasks just created |
app/models/text_article.rb
1 | -require 'noosfero/translatable_content' | ||
2 | - | ||
3 | # a base class for all text article types. | 1 | # a base class for all text article types. |
4 | class TextArticle < Article | 2 | class TextArticle < Article |
5 | 3 | ||
@@ -9,7 +7,7 @@ class TextArticle < Article | @@ -9,7 +7,7 @@ class TextArticle < Article | ||
9 | _('Article') | 7 | _('Article') |
10 | end | 8 | end |
11 | 9 | ||
12 | - include Noosfero::TranslatableContent | 10 | + include TranslatableContent |
13 | 11 | ||
14 | def self.icon_name(article = nil) | 12 | def self.icon_name(article = nil) |
15 | if article && !article.parent.nil? && article.parent.kind_of?(Blog) | 13 | if article && !article.parent.nil? && article.parent.kind_of?(Blog) |
app/models/tiny_mce_article.rb
app/models/uploaded_file.rb
@@ -84,6 +84,7 @@ class UploadedFile < Article | @@ -84,6 +84,7 @@ class UploadedFile < Article | ||
84 | 84 | ||
85 | validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of %{size}").sub('%{size}', self.max_size.to_humanreadable).fix_i18n | 85 | validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of %{size}").sub('%{size}', self.max_size.to_humanreadable).fix_i18n |
86 | 86 | ||
87 | + extend DelayedAttachmentFu::ClassMethods | ||
87 | delay_attachment_fu_thumbnails | 88 | delay_attachment_fu_thumbnails |
88 | 89 | ||
89 | postgresql_attachment_fu | 90 | postgresql_attachment_fu |
config/initializers/00_dependencies.rb
@@ -16,14 +16,6 @@ end | @@ -16,14 +16,6 @@ end | ||
16 | require 'extensions' | 16 | require 'extensions' |
17 | 17 | ||
18 | # locally-developed modules | 18 | # locally-developed modules |
19 | -require 'acts_as_filesystem' | ||
20 | -require 'acts_as_having_settings' | ||
21 | -require 'acts_as_having_boxes' | ||
22 | -require 'acts_as_having_image' | ||
23 | -require 'acts_as_having_posts' | ||
24 | -require 'acts_as_customizable' | ||
25 | require 'route_if' | 19 | require 'route_if' |
26 | require 'maybe_add_http' | 20 | require 'maybe_add_http' |
27 | -require 'set_profile_region_from_city_state' | ||
28 | -require 'white_list_filter' | ||
29 | 21 |
config/initializers/delayed_attachment_fu.rb
@@ -1 +0,0 @@ | @@ -1 +0,0 @@ | ||
1 | -require 'delayed_attachment_fu' |
db/migrate/20160422163123_enable_products_plugin_on_environments.rb
@@ -7,6 +7,7 @@ class Environment < ApplicationRecord | @@ -7,6 +7,7 @@ class Environment < ApplicationRecord | ||
7 | has_many :profiles | 7 | has_many :profiles |
8 | has_many :products, through: :profiles | 8 | has_many :products, through: :profiles |
9 | 9 | ||
10 | + extend ActsAsHavingSettings::ClassMethods | ||
10 | acts_as_having_settings field: :settings | 11 | acts_as_having_settings field: :settings |
11 | settings_items :enabled_plugins, type: Array | 12 | settings_items :enabled_plugins, type: Array |
12 | end | 13 | end |
lib/acts_as_customizable.rb
@@ -1,125 +0,0 @@ | @@ -1,125 +0,0 @@ | ||
1 | -module Customizable | ||
2 | - | ||
3 | - def self.included(base) | ||
4 | - base.attr_accessible :custom_values | ||
5 | - base.extend ClassMethods | ||
6 | - end | ||
7 | - | ||
8 | - module ClassMethods | ||
9 | - def acts_as_customizable(options = {}) | ||
10 | - attr_accessor :custom_values | ||
11 | - has_many :custom_field_values, :dependent => :delete_all, :as => :customized | ||
12 | - send :include, Customizable::InstanceMethods | ||
13 | - after_save :save_custom_values | ||
14 | - validate :valid_custom_values? | ||
15 | - end | ||
16 | - | ||
17 | - def active_custom_fields environment | ||
18 | - environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.active} | ||
19 | - end | ||
20 | - | ||
21 | - def required_custom_fields environment | ||
22 | - environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.required} | ||
23 | - end | ||
24 | - | ||
25 | - def signup_custom_fields environment | ||
26 | - environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.signup} | ||
27 | - end | ||
28 | - | ||
29 | - def custom_fields environment | ||
30 | - environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type)} | ||
31 | - end | ||
32 | - | ||
33 | - def customized_ancestors_list | ||
34 | - current=self | ||
35 | - result=[] | ||
36 | - while current.instance_methods.include? :custom_value do | ||
37 | - result << current.name | ||
38 | - current=current.superclass | ||
39 | - end | ||
40 | - result | ||
41 | - end | ||
42 | - | ||
43 | - end | ||
44 | - | ||
45 | - module InstanceMethods | ||
46 | - | ||
47 | - def valid_custom_values? | ||
48 | - is_valid = true | ||
49 | - parse_custom_values.each do |cv| | ||
50 | - unless cv.valid? | ||
51 | - name = cv.custom_field.name | ||
52 | - errors.add(name, cv.errors.messages[name.to_sym].first) | ||
53 | - is_valid = false | ||
54 | - end | ||
55 | - end | ||
56 | - is_valid | ||
57 | - end | ||
58 | - | ||
59 | - def customized_class | ||
60 | - current=self.class | ||
61 | - while current.instance_methods.include? :custom_fields do | ||
62 | - result=current | ||
63 | - current=current.superclass | ||
64 | - end | ||
65 | - result.name | ||
66 | - end | ||
67 | - | ||
68 | - def is_public(field_name) | ||
69 | - cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name} | ||
70 | - cv.nil? ? false : cv.public | ||
71 | - end | ||
72 | - | ||
73 | - def public_values | ||
74 | - self.custom_field_values.select{|cv| cv.public} | ||
75 | - end | ||
76 | - | ||
77 | - def custom_value(field_name) | ||
78 | - cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name} | ||
79 | - cv.nil? ? default_value_for(field_name) : cv.value | ||
80 | - end | ||
81 | - | ||
82 | - def default_value_for(field_name) | ||
83 | - field=self.class.custom_fields(environment).detect {|c| c.name == field_name} | ||
84 | - field.nil? ? nil : field.default_value | ||
85 | - end | ||
86 | - | ||
87 | - def parse_custom_values | ||
88 | - return_list = [] | ||
89 | - return return_list if custom_values.blank? | ||
90 | - custom_values.each_pair do |key, value| | ||
91 | - custom_field = environment.custom_fields.detect{|cf|cf.name==key} | ||
92 | - next if custom_field.blank? | ||
93 | - custom_field_value = self.custom_field_values(true).detect{|cv| cv.custom_field.name==key} | ||
94 | - | ||
95 | - if custom_field_value.nil? | ||
96 | - custom_field_value = CustomFieldValue.new | ||
97 | - custom_field_value.custom_field = custom_field | ||
98 | - custom_field_value.customized = self | ||
99 | - end | ||
100 | - | ||
101 | - if value.is_a?(Hash) | ||
102 | - custom_field_value.value = value['value'].to_s | ||
103 | - if value.has_key?('public') | ||
104 | - is_public = value['public']=="true" || value['public']==true | ||
105 | - custom_field_value.public = is_public | ||
106 | - else | ||
107 | - custom_field_value.public = false | ||
108 | - end | ||
109 | - else | ||
110 | - custom_field_value.value = value.to_s | ||
111 | - custom_field_value.public = false | ||
112 | - end | ||
113 | - return_list << custom_field_value | ||
114 | - end | ||
115 | - return_list | ||
116 | - end | ||
117 | - | ||
118 | - def save_custom_values | ||
119 | - parse_custom_values.each(&:save) | ||
120 | - end | ||
121 | - | ||
122 | - end | ||
123 | -end | ||
124 | - | ||
125 | -ActiveRecord::Base.include Customizable |
lib/acts_as_filesystem.rb
@@ -1,267 +0,0 @@ | @@ -1,267 +0,0 @@ | ||
1 | -module ActsAsFileSystem | ||
2 | - | ||
3 | - module ActsMethods | ||
4 | - | ||
5 | - # Declares the ActiveRecord model to acts like a filesystem: objects are | ||
6 | - # arranged in a tree (liks acts_as_tree), and . The underlying table must | ||
7 | - # have the following fields: | ||
8 | - # | ||
9 | - # * name (+:string+) - the title of the object | ||
10 | - # * slug (+:string+)- the title turned in a URL-friendly string (downcased, | ||
11 | - # non-ascii chars transliterated into ascii, all sequences of | ||
12 | - # non-alphanumericd characters changed into dashed) | ||
13 | - # * path (+:text+)- stores the full path of the object (the full path of | ||
14 | - # the parent, a "/" and the slug of the object) | ||
15 | - # * children_count - a cache of the number of children elements. | ||
16 | - def acts_as_filesystem | ||
17 | - # a filesystem is a tree | ||
18 | - acts_as_tree :counter_cache => :children_count | ||
19 | - | ||
20 | - extend ClassMethods | ||
21 | - include InstanceMethods | ||
22 | - if self.has_path? | ||
23 | - after_update :update_children_path | ||
24 | - before_create :set_path | ||
25 | - include InstanceMethods::PathMethods | ||
26 | - end | ||
27 | - | ||
28 | - before_save :set_ancestry | ||
29 | - end | ||
30 | - | ||
31 | - end | ||
32 | - | ||
33 | - module ClassMethods | ||
34 | - | ||
35 | - def build_ancestry(parent_id = nil, ancestry = '') | ||
36 | - ActiveRecord::Base.transaction do | ||
37 | - self.base_class.where(parent_id: parent_id).each do |node| | ||
38 | - node.update_column :ancestry, ancestry | ||
39 | - | ||
40 | - build_ancestry node.id, (ancestry.empty? ? "#{node.formatted_ancestry_id}" : | ||
41 | - "#{ancestry}#{node.ancestry_sep}#{node.formatted_ancestry_id}") | ||
42 | - end | ||
43 | - end | ||
44 | - | ||
45 | - #raise "Couldn't reach and set ancestry on every record" if self.base_class.where('ancestry is null').count != 0 | ||
46 | - end | ||
47 | - | ||
48 | - def has_path? | ||
49 | - (['name', 'slug', 'path'] - self.column_names).blank? | ||
50 | - end | ||
51 | - | ||
52 | - end | ||
53 | - | ||
54 | - module InstanceMethods | ||
55 | - | ||
56 | - def ancestry_column | ||
57 | - 'ancestry' | ||
58 | - end | ||
59 | - def ancestry_sep | ||
60 | - '.' | ||
61 | - end | ||
62 | - def has_ancestry? | ||
63 | - self.class.column_names.include? self.ancestry_column | ||
64 | - end | ||
65 | - | ||
66 | - def formatted_ancestry_id | ||
67 | - "%010d" % self.id if self.id | ||
68 | - end | ||
69 | - | ||
70 | - def ancestry | ||
71 | - self[ancestry_column] | ||
72 | - end | ||
73 | - def ancestor_ids | ||
74 | - return nil if !has_ancestry? or ancestry.nil? | ||
75 | - @ancestor_ids ||= ancestry.split(ancestry_sep).map{ |id| id.to_i } | ||
76 | - end | ||
77 | - | ||
78 | - def ancestry=(value) | ||
79 | - self[ancestry_column] = value | ||
80 | - end | ||
81 | - def set_ancestry | ||
82 | - return unless self.has_ancestry? | ||
83 | - if self.ancestry.nil? or (new_record? or parent_id_changed?) or recalculate_path | ||
84 | - self.ancestry = self.hierarchy(true)[0...-1].map{ |p| p.formatted_ancestry_id }.join(ancestry_sep) | ||
85 | - end | ||
86 | - end | ||
87 | - | ||
88 | - def descendents_options | ||
89 | - ["#{self.ancestry_column} LIKE ?", "%#{self.formatted_ancestry_id}%"] | ||
90 | - end | ||
91 | - def descendents | ||
92 | - self.class.where descendents_options | ||
93 | - end | ||
94 | - | ||
95 | - # calculates the level of the record in the records hierarchy. Top-level | ||
96 | - # records have level 0; the children of the top-level records have | ||
97 | - # level 1; the children of records with level 1 have level 2, and so on. | ||
98 | - # | ||
99 | - # A level 0 | ||
100 | - # / \ | ||
101 | - # B C level 1 | ||
102 | - # / \ / \ | ||
103 | - # E F G H level 2 | ||
104 | - # ... | ||
105 | - def level | ||
106 | - self.hierarchy.size - 1 | ||
107 | - end | ||
108 | - | ||
109 | - # Is this record a top-level record? | ||
110 | - def top_level? | ||
111 | - self.parent.nil? | ||
112 | - end | ||
113 | - | ||
114 | - # Is this record a leaf in the hierarchy tree of records? | ||
115 | - # | ||
116 | - # Being a leaf means that this record has no subrecord. | ||
117 | - def leaf? | ||
118 | - self.children.empty? | ||
119 | - end | ||
120 | - | ||
121 | - def top_ancestor | ||
122 | - if has_ancestry? and !ancestry.blank? | ||
123 | - self.class.base_class.find_by id: self.top_ancestor_id | ||
124 | - else | ||
125 | - self.hierarchy.first | ||
126 | - end | ||
127 | - end | ||
128 | - def top_ancestor_id | ||
129 | - if has_ancestry? and !ancestry.nil? | ||
130 | - self.ancestor_ids.first | ||
131 | - else | ||
132 | - self.hierarchy.first.id | ||
133 | - end | ||
134 | - end | ||
135 | - | ||
136 | - # returns the full hierarchy from the top-level item to this one. For | ||
137 | - # example, if item1 has a children item2 and item2 has a children item3, | ||
138 | - # then item3's hierarchy would be [item1, item2, item3]. | ||
139 | - # | ||
140 | - # If +reload+ is passed as +true+, then the hierarchy is reload (usefull | ||
141 | - # when the ActiveRecord object was modified in some way, or just after | ||
142 | - # changing parent) | ||
143 | - def hierarchy(reload = false) | ||
144 | - @hierarchy = nil if reload or recalculate_path | ||
145 | - | ||
146 | - if @hierarchy.nil? | ||
147 | - @hierarchy = [] | ||
148 | - | ||
149 | - if !reload and !recalculate_path and ancestor_ids | ||
150 | - objects = self.class.base_class.where(id: ancestor_ids) | ||
151 | - ancestor_ids.each{ |id| @hierarchy << objects.find{ |t| t.id == id } } | ||
152 | - @hierarchy << self | ||
153 | - else | ||
154 | - item = self | ||
155 | - while item | ||
156 | - @hierarchy.unshift(item) | ||
157 | - item = item.parent | ||
158 | - end | ||
159 | - end | ||
160 | - end | ||
161 | - | ||
162 | - @hierarchy | ||
163 | - end | ||
164 | - | ||
165 | - def map_traversal(&block) | ||
166 | - result = [] | ||
167 | - current_level = [self] | ||
168 | - | ||
169 | - while !current_level.empty? | ||
170 | - result += current_level | ||
171 | - ids = current_level.select {|item| item.children_count > 0}.map(&:id) | ||
172 | - break if ids.empty? | ||
173 | - current_level = self.class.base_class.where(parent_id: ids) | ||
174 | - end | ||
175 | - block ||= (lambda { |x| x }) | ||
176 | - result.map(&block) | ||
177 | - end | ||
178 | - | ||
179 | - def all_children | ||
180 | - res = map_traversal | ||
181 | - res.shift | ||
182 | - res | ||
183 | - end | ||
184 | - | ||
185 | - ##### | ||
186 | - # Path methods | ||
187 | - # These methods are used when _path_, _name_ and _slug_ attributes exist | ||
188 | - # and should be calculated based on the tree | ||
189 | - ##### | ||
190 | - module PathMethods | ||
191 | - # used to know when to trigger batch renaming | ||
192 | - attr_accessor :recalculate_path | ||
193 | - | ||
194 | - # calculates the full path to this record using parent's path. | ||
195 | - def calculate_path | ||
196 | - self.hierarchy.map{ |obj| obj.slug }.join('/') | ||
197 | - end | ||
198 | - def set_path | ||
199 | - if self.path == self.slug && !self.top_level? | ||
200 | - self.path = self.calculate_path | ||
201 | - end | ||
202 | - end | ||
203 | - def explode_path | ||
204 | - path.split(/\//) | ||
205 | - end | ||
206 | - | ||
207 | - def update_children_path | ||
208 | - if self.recalculate_path | ||
209 | - self.children.each do |child| | ||
210 | - child.path = child.calculate_path | ||
211 | - child.recalculate_path = true | ||
212 | - child.save! | ||
213 | - end | ||
214 | - end | ||
215 | - self.recalculate_path = false | ||
216 | - end | ||
217 | - | ||
218 | - # calculates the full name of a record by accessing the name of all its | ||
219 | - # ancestors. | ||
220 | - # | ||
221 | - # If you have this record hierarchy: | ||
222 | - # Record "A" | ||
223 | - # Record "B" | ||
224 | - # Record "C" | ||
225 | - # | ||
226 | - # Then Record "C" will have "A/B/C" as its full name. | ||
227 | - def full_name(sep = '/') | ||
228 | - self.hierarchy.map {|item| item.name || '?' }.join(sep) | ||
229 | - end | ||
230 | - | ||
231 | - # gets the name without leading parents. Useful when dividing records | ||
232 | - # in top-level groups and full names must not include the top-level | ||
233 | - # record which is already a emphasized label | ||
234 | - def full_name_without_leading(count, sep = '/') | ||
235 | - parts = self.full_name(sep).split(sep) | ||
236 | - count.times { parts.shift } | ||
237 | - parts.join(sep) | ||
238 | - end | ||
239 | - | ||
240 | - def set_name(value) | ||
241 | - if self.name != value | ||
242 | - self.recalculate_path = true | ||
243 | - end | ||
244 | - self[:name] = value | ||
245 | - end | ||
246 | - | ||
247 | - # sets the name of the record. Also sets #slug accordingly. | ||
248 | - def name=(value) | ||
249 | - self.set_name(value) | ||
250 | - unless self.name.blank? | ||
251 | - self.slug = self.name.to_slug | ||
252 | - end | ||
253 | - end | ||
254 | - | ||
255 | - # sets the slug of the record. Also sets the path with the new slug value. | ||
256 | - def slug=(value) | ||
257 | - self[:slug] = value | ||
258 | - unless self.slug.blank? | ||
259 | - self.path = self.calculate_path | ||
260 | - end | ||
261 | - end | ||
262 | - end | ||
263 | - end | ||
264 | -end | ||
265 | - | ||
266 | -ActiveRecord::Base.extend ActsAsFileSystem::ActsMethods | ||
267 | - |
lib/acts_as_having_boxes.rb
@@ -1,38 +0,0 @@ | @@ -1,38 +0,0 @@ | ||
1 | -module ActsAsHavingBoxes | ||
2 | - | ||
3 | - module ClassMethods | ||
4 | - def acts_as_having_boxes | ||
5 | - has_many :boxes, -> { order :position }, as: :owner, dependent: :destroy | ||
6 | - self.send(:include, ActsAsHavingBoxes) | ||
7 | - end | ||
8 | - end | ||
9 | - | ||
10 | - module BlockArray | ||
11 | - def find(id) | ||
12 | - select { |item| item.id == id.to_i }.first | ||
13 | - end | ||
14 | - end | ||
15 | - | ||
16 | - def blocks(reload = false) | ||
17 | - if (reload) | ||
18 | - @blocks = nil | ||
19 | - end | ||
20 | - if @blocks.nil? | ||
21 | - @blocks = boxes.includes(:blocks).inject([]) do |acc,obj| | ||
22 | - acc.concat(obj.blocks) | ||
23 | - end | ||
24 | - @blocks.send(:extend, BlockArray) | ||
25 | - end | ||
26 | - @blocks | ||
27 | - end | ||
28 | - | ||
29 | - # returns 3 unless the class table has a boxes_limit column. In that case | ||
30 | - # return the value of the column. | ||
31 | - def boxes_limit layout_template = nil | ||
32 | - layout_template ||= self.layout_template | ||
33 | - @boxes_limit ||= LayoutTemplate.find(layout_template).number_of_boxes || 3 | ||
34 | - end | ||
35 | - | ||
36 | -end | ||
37 | - | ||
38 | -ActiveRecord::Base.extend ActsAsHavingBoxes::ClassMethods |
lib/acts_as_having_image.rb
@@ -1,27 +0,0 @@ | @@ -1,27 +0,0 @@ | ||
1 | -module ActsAsHavingImage | ||
2 | - | ||
3 | - module ClassMethods | ||
4 | - def acts_as_having_image | ||
5 | - belongs_to :image, dependent: :destroy | ||
6 | - scope :with_image, -> { where "#{table_name}.image_id IS NOT NULL" } | ||
7 | - scope :without_image, -> { where "#{table_name}.image_id IS NULL" } | ||
8 | - attr_accessible :image_builder | ||
9 | - include ActsAsHavingImage | ||
10 | - end | ||
11 | - end | ||
12 | - | ||
13 | - def image_builder=(img) | ||
14 | - if image && image.id == img[:id] | ||
15 | - image.attributes = img | ||
16 | - else | ||
17 | - build_image(img) | ||
18 | - end unless img[:uploaded_data].blank? | ||
19 | - if img[:remove_image] == 'true' | ||
20 | - self.image_id = nil | ||
21 | - end | ||
22 | - end | ||
23 | - | ||
24 | -end | ||
25 | - | ||
26 | -ActiveRecord::Base.extend ActsAsHavingImage::ClassMethods | ||
27 | - |
lib/acts_as_having_posts.rb
@@ -1,51 +0,0 @@ | @@ -1,51 +0,0 @@ | ||
1 | -module ActsAsHavingPosts | ||
2 | - | ||
3 | - module ClassMethods | ||
4 | - def acts_as_having_posts(scope = nil) | ||
5 | - has_many :posts, -> { | ||
6 | - s = order('published_at DESC, id DESC').where('articles.type != ?', 'RssFeed') | ||
7 | - s = s.instance_exec(&scope) if scope | ||
8 | - s | ||
9 | - }, class_name: 'Article', foreign_key: 'parent_id', source: :children | ||
10 | - | ||
11 | - attr_accessor :feed_attrs | ||
12 | - | ||
13 | - after_create do |blog| | ||
14 | - blog.children << RssFeed.new(:name => 'feed', :profile => blog.profile) | ||
15 | - blog.feed = blog.feed_attrs | ||
16 | - end | ||
17 | - | ||
18 | - settings_items :posts_per_page, :type => :integer, :default => 5 | ||
19 | - | ||
20 | - self.send(:include, ActsAsHavingPosts) | ||
21 | - end | ||
22 | - end | ||
23 | - | ||
24 | - def has_posts? | ||
25 | - true | ||
26 | - end | ||
27 | - | ||
28 | - def feed | ||
29 | - children.where(:type => 'RssFeed').first | ||
30 | - end | ||
31 | - | ||
32 | - def feed=(attrs) | ||
33 | - if attrs | ||
34 | - if self.feed | ||
35 | - self.feed.update(attrs) | ||
36 | - else | ||
37 | - self.feed_attrs = attrs | ||
38 | - end | ||
39 | - end | ||
40 | - self.feed | ||
41 | - end | ||
42 | - | ||
43 | - def name=(value) | ||
44 | - self.set_name(value) | ||
45 | - self.slug = self.slug.blank? ? self.name.to_slug : self.slug.to_slug | ||
46 | - end | ||
47 | - | ||
48 | -end | ||
49 | - | ||
50 | -ActiveRecord::Base.extend ActsAsHavingPosts::ClassMethods | ||
51 | - |
lib/acts_as_having_settings.rb
@@ -1,91 +0,0 @@ | @@ -1,91 +0,0 @@ | ||
1 | -# declare missing types | ||
2 | -module ActiveRecord | ||
3 | - module Type | ||
4 | - class Symbol < Value | ||
5 | - def cast_value value | ||
6 | - value.to_sym | ||
7 | - end | ||
8 | - end | ||
9 | - class Array < Value | ||
10 | - def cast_value value | ||
11 | - ::Array.wrap(value) | ||
12 | - end | ||
13 | - end | ||
14 | - class Hash < Value | ||
15 | - def cast_value value | ||
16 | - h = ::Hash[value] | ||
17 | - h.symbolize_keys! | ||
18 | - h | ||
19 | - end | ||
20 | - end | ||
21 | - end | ||
22 | -end | ||
23 | - | ||
24 | -module ActsAsHavingSettings | ||
25 | - | ||
26 | - def self.type_cast value, type | ||
27 | - # do not cast nil | ||
28 | - return value if value.nil? | ||
29 | - type.send :cast_value, value | ||
30 | - end | ||
31 | - | ||
32 | - module ClassMethods | ||
33 | - | ||
34 | - def acts_as_having_settings(*args) | ||
35 | - options = args.last.is_a?(Hash) ? args.pop : {} | ||
36 | - field = (options[:field] || :settings).to_sym | ||
37 | - | ||
38 | - serialize field, Hash | ||
39 | - class_attribute :settings_field | ||
40 | - self.settings_field = field | ||
41 | - | ||
42 | - class_eval do | ||
43 | - def settings_field | ||
44 | - self[self.class.settings_field] ||= Hash.new | ||
45 | - end | ||
46 | - | ||
47 | - def setting_changed? setting_field | ||
48 | - setting_field = setting_field.to_sym | ||
49 | - changed_settings = self.changes[self.class.settings_field] | ||
50 | - return false if changed_settings.nil? | ||
51 | - | ||
52 | - old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field] | ||
53 | - new_setting_value = changed_settings.last[setting_field] | ||
54 | - old_setting_value != new_setting_value | ||
55 | - end | ||
56 | - end | ||
57 | - | ||
58 | - settings_items *args | ||
59 | - end | ||
60 | - | ||
61 | - def settings_items *names | ||
62 | - | ||
63 | - options = names.extract_options! | ||
64 | - default = options[:default] | ||
65 | - type = options[:type] | ||
66 | - type = if type.present? then ActiveRecord::Type.const_get(type.to_s.camelize.to_sym).new else nil end | ||
67 | - | ||
68 | - names.each do |setting| | ||
69 | - # symbolize key | ||
70 | - setting = setting.to_sym | ||
71 | - | ||
72 | - define_method setting do | ||
73 | - h = send self.class.settings_field | ||
74 | - val = h[setting] | ||
75 | - # translate default value if it is used | ||
76 | - if not val.nil? then val elsif default.is_a? String then gettext default else default end | ||
77 | - end | ||
78 | - | ||
79 | - define_method "#{setting}=" do |value| | ||
80 | - h = send self.class.settings_field | ||
81 | - h[setting] = if type then ActsAsHavingSettings.type_cast value, type else value end | ||
82 | - end | ||
83 | - end | ||
84 | - end | ||
85 | - | ||
86 | - end | ||
87 | - | ||
88 | -end | ||
89 | - | ||
90 | -ActiveRecord::Base.extend ActsAsHavingSettings::ClassMethods | ||
91 | - |
lib/code_numbering.rb
@@ -1,58 +0,0 @@ | @@ -1,58 +0,0 @@ | ||
1 | -module CodeNumbering | ||
2 | - module ClassMethods | ||
3 | - def code_numbering field, options = {} | ||
4 | - class_attribute :code_numbering_field | ||
5 | - class_attribute :code_numbering_options | ||
6 | - | ||
7 | - self.code_numbering_field = field | ||
8 | - self.code_numbering_options = options | ||
9 | - | ||
10 | - before_create :create_code_numbering | ||
11 | - | ||
12 | - include CodeNumbering::InstanceMethods | ||
13 | - end | ||
14 | - end | ||
15 | - | ||
16 | - module InstanceMethods | ||
17 | - | ||
18 | - def code | ||
19 | - self.attributes[self.code_numbering_field.to_s] | ||
20 | - end | ||
21 | - | ||
22 | - def code_scope | ||
23 | - scope = self.code_numbering_options[:scope] | ||
24 | - case scope | ||
25 | - when Symbol | ||
26 | - self.send scope | ||
27 | - when Proc | ||
28 | - instance_exec &scope | ||
29 | - else | ||
30 | - self.class | ||
31 | - end | ||
32 | - end | ||
33 | - | ||
34 | - def code_maximum | ||
35 | - self.code_scope.maximum(self.code_numbering_field) || 0 | ||
36 | - end | ||
37 | - | ||
38 | - def create_code_numbering | ||
39 | - max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start] | ||
40 | - max = self.code_maximum | ||
41 | - self.send "#{self.code_numbering_field}=", max+1 | ||
42 | - end | ||
43 | - | ||
44 | - def reset_scope_code_numbering | ||
45 | - max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start] | ||
46 | - max ||= 1 | ||
47 | - | ||
48 | - self.code_scope.order(:created_at).each do |record| | ||
49 | - record.update_column self.code_numbering_field, max | ||
50 | - max += 1 | ||
51 | - end | ||
52 | - self.reload | ||
53 | - end | ||
54 | - | ||
55 | - end | ||
56 | -end | ||
57 | - | ||
58 | -ActiveRecord::Base.extend CodeNumbering::ClassMethods |
lib/delayed_attachment_fu.rb
@@ -1,56 +0,0 @@ | @@ -1,56 +0,0 @@ | ||
1 | -module DelayedAttachmentFu | ||
2 | - | ||
3 | - module ClassMethods | ||
4 | - def delay_attachment_fu_thumbnails | ||
5 | - include DelayedAttachmentFu::InstanceMethods | ||
6 | - after_create do |file| | ||
7 | - if file.thumbnailable? | ||
8 | - Delayed::Job.enqueue CreateThumbnailsJob.new(file.class.name, file.id) | ||
9 | - end | ||
10 | - end | ||
11 | - end | ||
12 | - end | ||
13 | - | ||
14 | - module InstanceMethods | ||
15 | - # skip processing with RMagick | ||
16 | - def process_attachment | ||
17 | - end | ||
18 | - | ||
19 | - def after_process_attachment | ||
20 | - save_to_storage | ||
21 | - @temp_paths.clear | ||
22 | - @saved_attachment = nil | ||
23 | - run_callbacks :after_attachment_saved | ||
24 | - end | ||
25 | - | ||
26 | - def create_thumbnails | ||
27 | - if thumbnailable? | ||
28 | - self.class.with_image(full_filename) do |img| | ||
29 | - self.width = img.columns | ||
30 | - self.height = img.rows | ||
31 | - self.save! | ||
32 | - end | ||
33 | - self.class.attachment_options[:thumbnails].each do |suffix, size| | ||
34 | - self.create_or_update_thumbnail(self.full_filename, suffix, size) | ||
35 | - end | ||
36 | - self.thumbnails_processed = true | ||
37 | - self.save! | ||
38 | - end | ||
39 | - end | ||
40 | - | ||
41 | - def public_filename(size=nil) | ||
42 | - force, size = true, nil if size == :uploaded | ||
43 | - if !self.thumbnailable? || self.thumbnails_processed || force | ||
44 | - super size | ||
45 | - else | ||
46 | - size ||= :thumb | ||
47 | - '/images/icons-app/image-loading-%s.png' % size | ||
48 | - end | ||
49 | - end | ||
50 | - | ||
51 | - | ||
52 | - end | ||
53 | -end | ||
54 | - | ||
55 | -ActiveRecord::Base.extend DelayedAttachmentFu::ClassMethods | ||
56 | - |
lib/noosfero/translatable_content.rb
lib/set_profile_region_from_city_state.rb
@@ -1,44 +0,0 @@ | @@ -1,44 +0,0 @@ | ||
1 | -module SetProfileRegionFromCityState | ||
2 | - | ||
3 | - module ClassMethods | ||
4 | - def set_profile_region_from_city_state | ||
5 | - before_save :region_from_city_and_state | ||
6 | - | ||
7 | - include InstanceMethods | ||
8 | - alias_method_chain :city=, :region | ||
9 | - alias_method_chain :state=, :region | ||
10 | - end | ||
11 | - end | ||
12 | - | ||
13 | - module InstanceMethods | ||
14 | - include Noosfero::Plugin::HotSpot | ||
15 | - | ||
16 | - def city_with_region=(value) | ||
17 | - self.city_without_region = value | ||
18 | - @change_region = true | ||
19 | - end | ||
20 | - | ||
21 | - def state_with_region=(value) | ||
22 | - self.state_without_region = value | ||
23 | - @change_region = true | ||
24 | - end | ||
25 | - | ||
26 | - def region_from_city_and_state | ||
27 | - if @change_region | ||
28 | - self.region = nil | ||
29 | - state = search_region(State, self.state) | ||
30 | - self.region = search_region(City.where(:parent_id => state.id), self.city) if state | ||
31 | - end | ||
32 | - end | ||
33 | - | ||
34 | - private | ||
35 | - | ||
36 | - def search_region(scope, query) | ||
37 | - return nil if !query | ||
38 | - query = query.downcase.strip | ||
39 | - scope.where(['lower(name)=? OR lower(abbreviation)=? OR lower(acronym)=?', query, query, query]).first | ||
40 | - end | ||
41 | - | ||
42 | - end | ||
43 | - | ||
44 | -end |
lib/white_list_filter.rb
@@ -1,37 +0,0 @@ | @@ -1,37 +0,0 @@ | ||
1 | -module WhiteListFilter | ||
2 | - | ||
3 | - def check_iframe_on_content(content, trusted_sites) | ||
4 | - if content.blank? || !content.include?('iframe') | ||
5 | - return content | ||
6 | - end | ||
7 | - content.gsub!(/<iframe[^>]*>\s*<\/iframe>/i) do |iframe| | ||
8 | - result = '' | ||
9 | - unless iframe =~ /src=['"].*src=['"]/ | ||
10 | - trusted_sites.each do |trusted_site| | ||
11 | - re_dom = trusted_site.gsub('.', '\.') | ||
12 | - if iframe =~ /src=["'](https?:)?\/\/(www\.)?#{re_dom}\// | ||
13 | - result = iframe | ||
14 | - end | ||
15 | - end | ||
16 | - end | ||
17 | - result | ||
18 | - end | ||
19 | - content | ||
20 | - end | ||
21 | - | ||
22 | - module ClassMethods | ||
23 | - def filter_iframes(*opts) | ||
24 | - options = opts.last.is_a?(Hash) && opts.pop || {} | ||
25 | - white_list_method = options[:whitelist] || :iframe_whitelist | ||
26 | - opts.each do |field| | ||
27 | - before_validation do |obj| | ||
28 | - obj.check_iframe_on_content(obj.send(field), obj.send(white_list_method)) | ||
29 | - end | ||
30 | - end | ||
31 | - end | ||
32 | - end | ||
33 | - | ||
34 | - def self.included(c) | ||
35 | - c.send(:extend, WhiteListFilter::ClassMethods) | ||
36 | - end | ||
37 | -end |
plugins/analytics/models/analytics_plugin/page_view.rb
@@ -8,6 +8,7 @@ class AnalyticsPlugin::PageView < ApplicationRecord | @@ -8,6 +8,7 @@ class AnalyticsPlugin::PageView < ApplicationRecord | ||
8 | attr_accessor :request | 8 | attr_accessor :request |
9 | attr_accessible :request | 9 | attr_accessible :request |
10 | 10 | ||
11 | + extend ActsAsHavingSettings::ClassMethods | ||
11 | acts_as_having_settings field: :options | 12 | acts_as_having_settings field: :options |
12 | 13 | ||
13 | belongs_to :profile, validate: true | 14 | belongs_to :profile, validate: true |
plugins/fb_app/models/fb_app_plugin/page_tab.rb
@@ -9,6 +9,7 @@ class FbAppPlugin::PageTab < ApplicationRecord | @@ -9,6 +9,7 @@ class FbAppPlugin::PageTab < ApplicationRecord | ||
9 | 9 | ||
10 | belongs_to :owner_profile, foreign_key: :profile_id, class_name: 'Profile' | 10 | belongs_to :owner_profile, foreign_key: :profile_id, class_name: 'Profile' |
11 | 11 | ||
12 | + extend ActsAsHavingSettings::ClassMethods | ||
12 | acts_as_having_settings field: :config | 13 | acts_as_having_settings field: :config |
13 | 14 | ||
14 | ConfigTypes = [:profile, :profiles, :query] | 15 | ConfigTypes = [:profile, :profiles, :query] |
plugins/newsletter/lib/newsletter_plugin/newsletter.rb
@@ -167,6 +167,7 @@ class NewsletterPlugin::Newsletter < ApplicationRecord | @@ -167,6 +167,7 @@ class NewsletterPlugin::Newsletter < ApplicationRecord | ||
167 | end | 167 | end |
168 | end | 168 | end |
169 | 169 | ||
170 | + extend ActsAsHavingImage::ClassMethods | ||
170 | acts_as_having_image | 171 | acts_as_having_image |
171 | 172 | ||
172 | def last_send_at | 173 | def last_send_at |
plugins/oauth_client/models/oauth_client_plugin/auth.rb
@@ -10,6 +10,7 @@ class OauthClientPlugin::Auth < ApplicationRecord | @@ -10,6 +10,7 @@ class OauthClientPlugin::Auth < ApplicationRecord | ||
10 | validates_presence_of :provider | 10 | validates_presence_of :provider |
11 | validates_uniqueness_of :profile_id, scope: :provider_id | 11 | validates_uniqueness_of :profile_id, scope: :provider_id |
12 | 12 | ||
13 | + extend ActsAsHavingSettings::ClassMethods | ||
13 | acts_as_having_settings field: :data | 14 | acts_as_having_settings field: :data |
14 | 15 | ||
15 | def expires_in | 16 | def expires_in |
plugins/oauth_client/models/oauth_client_plugin/provider.rb
@@ -4,7 +4,10 @@ class OauthClientPlugin::Provider < ApplicationRecord | @@ -4,7 +4,10 @@ class OauthClientPlugin::Provider < ApplicationRecord | ||
4 | 4 | ||
5 | validates_presence_of :name, :strategy | 5 | validates_presence_of :name, :strategy |
6 | 6 | ||
7 | + extend ActsAsHavingImage::ClassMethods | ||
7 | acts_as_having_image | 8 | acts_as_having_image |
9 | + | ||
10 | + extend ActsAsHavingSettings::ClassMethods | ||
8 | acts_as_having_settings field: :options | 11 | acts_as_having_settings field: :options |
9 | 12 | ||
10 | settings_items :site, type: String | 13 | settings_items :site, type: String |
@@ -16,6 +19,4 @@ class OauthClientPlugin::Provider < ApplicationRecord | @@ -16,6 +19,4 @@ class OauthClientPlugin::Provider < ApplicationRecord | ||
16 | 19 | ||
17 | scope :enabled, -> { where enabled: true } | 20 | scope :enabled, -> { where enabled: true } |
18 | 21 | ||
19 | - acts_as_having_image | ||
20 | - | ||
21 | end | 22 | end |
plugins/products/models/products_plugin/product.rb
@@ -45,6 +45,7 @@ class ProductsPlugin::Product < ApplicationRecord | @@ -45,6 +45,7 @@ class ProductsPlugin::Product < ApplicationRecord | ||
45 | has_many :qualifiers, through: :product_qualifiers | 45 | has_many :qualifiers, through: :product_qualifiers |
46 | has_many :certifiers, through: :product_qualifiers | 46 | has_many :certifiers, through: :product_qualifiers |
47 | 47 | ||
48 | + extend ActsAsHavingSettings::ClassMethods | ||
48 | acts_as_having_settings field: :data | 49 | acts_as_having_settings field: :data |
49 | 50 | ||
50 | track_actions :create_product, :after_create, keep_params: [:name, :url ], if: Proc.new { |a| a.is_trackable? }, custom_user: :action_tracker_user | 51 | track_actions :create_product, :after_create, keep_params: [:name, :url ], if: Proc.new { |a| a.is_trackable? }, custom_user: :action_tracker_user |
@@ -129,6 +130,7 @@ class ProductsPlugin::Product < ApplicationRecord | @@ -129,6 +130,7 @@ class ProductsPlugin::Product < ApplicationRecord | ||
129 | image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size | 130 | image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size |
130 | end | 131 | end |
131 | 132 | ||
133 | + extend ActsAsHavingImage::ClassMethods | ||
132 | acts_as_having_image | 134 | acts_as_having_image |
133 | 135 | ||
134 | def save_image | 136 | def save_image |
plugins/shopping_cart/db/migrate/20131226125124_move_shopping_cart_purchase_order_to_orders_plugin_order.rb
@@ -2,6 +2,7 @@ OrdersPlugin.send :remove_const, :Item if defined? OrdersPlugin::Item | @@ -2,6 +2,7 @@ OrdersPlugin.send :remove_const, :Item if defined? OrdersPlugin::Item | ||
2 | OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order | 2 | OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order |
3 | 3 | ||
4 | class ShoppingCartPlugin::PurchaseOrder < ApplicationRecord | 4 | class ShoppingCartPlugin::PurchaseOrder < ApplicationRecord |
5 | + extend ActsAsHavingSettings::ClassMethods | ||
5 | acts_as_having_settings field: :data | 6 | acts_as_having_settings field: :data |
6 | 7 | ||
7 | module Status | 8 | module Status |
plugins/video/lib/video_plugin/video.rb
plugins/video/lib/video_plugin/video_gallery.rb
@@ -14,7 +14,8 @@ class VideoPlugin::VideoGallery < Folder | @@ -14,7 +14,8 @@ class VideoPlugin::VideoGallery < Folder | ||
14 | errors.add(:parent, "A video gallery should not belong to a blog.") if parent && parent.blog? | 14 | errors.add(:parent, "A video gallery should not belong to a blog.") if parent && parent.blog? |
15 | end | 15 | end |
16 | 16 | ||
17 | - acts_as_having_settings :field => :setting | 17 | + extend ActsAsHavingSettings::ClassMethods |
18 | + acts_as_having_settings field: :setting | ||
18 | 19 | ||
19 | xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation' | 20 | xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation' |
20 | 21 |
test/unit/event_test.rb
@@ -282,7 +282,7 @@ class EventTest < ActiveSupport::TestCase | @@ -282,7 +282,7 @@ class EventTest < ActiveSupport::TestCase | ||
282 | end | 282 | end |
283 | 283 | ||
284 | should 'be translatable' do | 284 | should 'be translatable' do |
285 | - assert_kind_of Noosfero::TranslatableContent, Event.new | 285 | + assert_kind_of TranslatableContent, Event.new |
286 | end | 286 | end |
287 | 287 | ||
288 | should 'tiny mce editor is enabled' do | 288 | should 'tiny mce editor is enabled' do |
test/unit/text_article_test.rb
@@ -15,7 +15,7 @@ class TextArticleTest < ActiveSupport::TestCase | @@ -15,7 +15,7 @@ class TextArticleTest < ActiveSupport::TestCase | ||
15 | end | 15 | end |
16 | 16 | ||
17 | should 'be translatable' do | 17 | should 'be translatable' do |
18 | - assert_kind_of Noosfero::TranslatableContent, TextArticle.new | 18 | + assert_kind_of TranslatableContent, TextArticle.new |
19 | end | 19 | end |
20 | 20 | ||
21 | should 'return article icon name' do | 21 | should 'return article icon name' do |
test/unit/translatable_content_test.rb
@@ -4,7 +4,7 @@ class TranslatableContentTest < ActiveSupport::TestCase | @@ -4,7 +4,7 @@ class TranslatableContentTest < ActiveSupport::TestCase | ||
4 | 4 | ||
5 | class Content | 5 | class Content |
6 | attr_accessor :parent, :profile | 6 | attr_accessor :parent, :profile |
7 | - include Noosfero::TranslatableContent | 7 | + include TranslatableContent |
8 | end | 8 | end |
9 | 9 | ||
10 | def setup | 10 | def setup |