thredded 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/README.md +1 -1
  4. data/app/assets/stylesheets/thredded/base/_buttons.scss +17 -0
  5. data/app/assets/stylesheets/thredded/base/_variables.scss +8 -1
  6. data/app/commands/thredded/mark_all_read.rb +21 -0
  7. data/app/controllers/thredded/messageboard_groups_controller.rb +1 -1
  8. data/app/controllers/thredded/moderation_controller.rb +1 -1
  9. data/app/controllers/thredded/read_states_controller.rb +12 -0
  10. data/app/forms/thredded/topic_form.rb +0 -1
  11. data/app/helpers/thredded/urls_helper.rb +1 -1
  12. data/app/models/concerns/thredded/post_common.rb +14 -2
  13. data/app/models/concerns/thredded/topic_common.rb +9 -1
  14. data/app/models/thredded/messageboard.rb +7 -0
  15. data/app/models/thredded/post.rb +11 -18
  16. data/app/models/thredded/private_post.rb +1 -5
  17. data/app/models/thredded/private_topic.rb +0 -4
  18. data/app/models/thredded/topic.rb +26 -12
  19. data/app/view_models/thredded/topic_view.rb +1 -0
  20. data/app/view_models/thredded/topics_page_view.rb +3 -2
  21. data/app/views/thredded/preferences/_form.html.erb +1 -1
  22. data/app/views/thredded/private_topic_mailer/message_notification.html.erb +1 -1
  23. data/app/views/thredded/private_topic_mailer/message_notification.text.erb +1 -1
  24. data/app/views/thredded/private_topics/index.html.erb +14 -6
  25. data/config/locales/en.yml +2 -1
  26. data/config/locales/pt-BR.yml +9 -10
  27. data/config/routes.rb +2 -1
  28. data/db/seeds.rb +1 -118
  29. data/heroku.gemfile +1 -2
  30. data/heroku.gemfile.lock +60 -64
  31. data/lib/thredded/database_seeder.rb +269 -0
  32. data/lib/thredded/main_app_route_delegator.rb +1 -1
  33. data/lib/thredded/version.rb +1 -1
  34. data/thredded.gemspec +3 -3
  35. metadata +12 -9
@@ -0,0 +1,269 @@
1
+ # frozen_string_literal: true
2
+ require 'factory_girl_rails'
3
+
4
+ # rubocop:disable HandleExceptions
5
+ begin
6
+ if FactoryGirl.factories.instance_variable_get(:@items).none?
7
+ require_relative '../../spec/factories'
8
+ end
9
+ rescue NameError
10
+ end
11
+ # rubocop:enable HandleExceptions
12
+ module Thredded
13
+ class DatabaseSeeder
14
+ SKIP_CALLBACKS = [
15
+ [Thredded::Post, :commit, :after, :auto_follow_and_notify],
16
+ [Thredded::PrivatePost, :commit, :after, :notify_users],
17
+ ].freeze
18
+
19
+ def self.run(users: 200, topics: 55, posts: (1..60))
20
+ STDERR.puts 'Seeding the database...'
21
+ # Disable callbacks to avoid creating notifications and performing unnecessary updates
22
+ SKIP_CALLBACKS.each { |(klass, *args)| klass.skip_callback(*args) }
23
+ s = new
24
+ Messageboard.transaction do
25
+ s.seed(users: users, topics: topics, posts: posts)
26
+ s.log 'Running after_commit callbacks'
27
+ end
28
+ ensure
29
+ # Re-enable callbacks
30
+ SKIP_CALLBACKS.each { |(klass, *args)| klass.set_callback(*args) }
31
+ end
32
+
33
+ def seed(users: 200, topics: 55, posts: (1..60))
34
+ users(count: users)
35
+ first_messageboard
36
+ topics(count: topics)
37
+ private_topics(count: topics)
38
+ posts(count: posts)
39
+ private_posts(count: posts)
40
+ create_additional_messageboards
41
+ follow_some_topics
42
+ read_some_topics
43
+ end
44
+
45
+ def log(message)
46
+ STDERR.puts "- #{message}"
47
+ end
48
+
49
+ def first_user
50
+ @first_user ||= FirstUser.new(self).find_or_create
51
+ end
52
+
53
+ def users(count: 1)
54
+ @users ||= Users.new(self).find_or_create(count: count)
55
+ end
56
+
57
+ def first_messageboard
58
+ @first_messageboard ||= FirstMessageboard.new(self).find_or_create
59
+ end
60
+
61
+ def create_additional_messageboards
62
+ meta_group_id = MessageboardGroup.create!(name: 'Meta').id
63
+ additional_messageboards = [
64
+ ['Off-Topic', "Talk about whatever here, it's all good."],
65
+ ['Help, Bugs, and Suggestions',
66
+ 'Need help using the forum? Want to report a bug or make a suggestion? This is the place.', meta_group_id],
67
+ ['Praise', 'Want to tell us how great we are? This is the place.', meta_group_id]
68
+ ]
69
+ log "Creating #{additional_messageboards.length} additional messageboards..."
70
+ additional_messageboards.each do |(name, description, group_id)|
71
+ messageboard = Messageboard.create!(name: name, description: description, messageboard_group_id: group_id)
72
+ FactoryGirl.create_list(:topic, 1 + rand(3), messageboard: messageboard, with_posts: 1)
73
+ end
74
+ end
75
+
76
+ def topics(count: 1)
77
+ @topics ||= Topics.new(self).find_or_create(count: count)
78
+ end
79
+
80
+ def private_topics(count: 1)
81
+ @private_topics ||= PrivateTopics.new(self).find_or_create(count: count)
82
+ end
83
+
84
+ def posts(count: (1..1))
85
+ @posts ||= Posts.new(self).find_or_create(count: count)
86
+ end
87
+
88
+ def private_posts(count: (1..1))
89
+ @private_posts ||= PrivatePosts.new(self).find_or_create(count: count)
90
+ end
91
+
92
+ def follow_some_topics(count: (5..10), count_users: (1..5))
93
+ log 'Following some topics...'
94
+ posts.each do |post|
95
+ Thredded::UserTopicFollow.create_unless_exists(post.user_id, post.postable_id, :posted) if post.user_id
96
+ end
97
+ follow_some_topics_by_user(first_user, count: count)
98
+ users.sample(count_users.min + rand(count_users.max - count_users.min + 2)).each do |user|
99
+ follow_some_topics_by_user(user, count: count)
100
+ end
101
+ end
102
+
103
+ def follow_some_topics_by_user(user, count: (1..10))
104
+ topics.sample(count.min + rand(count.max - count.min + 2)).each do |topic|
105
+ Thredded::UserTopicFollow.create_unless_exists(user.id, topic.id)
106
+ end
107
+ end
108
+
109
+ def read_some_topics(count: (5..10), count_users: (1..5))
110
+ log 'Reading some topics...'
111
+ topics.each do |topic|
112
+ read_topic(topic, topic.last_user_id) if topic.last_user_id
113
+ end
114
+ read_some_topics_by_user(first_user, count: count)
115
+ @users.sample(count_users.min + rand(count_users.max - count_users.min + 2)).each do |user|
116
+ read_some_topics_by_user(user, count: count)
117
+ end
118
+ end
119
+
120
+ def read_some_topics_by_user(user, count: (1..10))
121
+ topics.sample(count.min + rand(count.max - count.min + 2)).each do |topic|
122
+ read_topic(topic, user.id)
123
+ end
124
+ end
125
+
126
+ def read_topic(topic, user_id)
127
+ Thredded::UserTopicReadState.find_or_initialize_by(user_id: user_id, postable_id: topic.id)
128
+ .update!(read_at: topic.updated_at, page: 1)
129
+ end
130
+
131
+ class BaseSeedData
132
+ attr_reader :seeder
133
+
134
+ def initialize(seed_database)
135
+ @seeder = seed_database
136
+ end
137
+
138
+ delegate :log, to: :seeder
139
+
140
+ def find_or_create(*args)
141
+ return @stored if @stored
142
+ @stored = (find || create(*args))
143
+ end
144
+
145
+ protected
146
+
147
+ def model_class
148
+ self.class::MODEL_CLASS
149
+ end
150
+
151
+ # @abstract
152
+ def create(*_args)
153
+ fail 'Unimplemented'
154
+ end
155
+
156
+ # @abstract
157
+ def find
158
+ fail 'Unimplemented'
159
+ end
160
+ end
161
+
162
+ class FirstSeedData < BaseSeedData
163
+ def find
164
+ model_class.first
165
+ end
166
+ end
167
+
168
+ class CollectionSeedData < BaseSeedData
169
+ def find
170
+ return nil unless model_class.exists?
171
+ model_class.all.to_a
172
+ end
173
+ end
174
+
175
+ class FirstUser < FirstSeedData
176
+ MODEL_CLASS = User
177
+
178
+ def create
179
+ log 'Creating first user...'
180
+ FactoryGirl.create(:user, :approved, :admin, name: 'Joe', email: 'joe@example.com')
181
+ end
182
+ end
183
+
184
+ class Users < CollectionSeedData
185
+ MODEL_CLASS = User
186
+
187
+ def create(count: 1)
188
+ log "Creating #{count} users..."
189
+ approved_users_count = (count * 0.97).round
190
+ [seeder.first_user] +
191
+ FactoryGirl.create_list(:user, approved_users_count, :approved) +
192
+ FactoryGirl.create_list(:user, count - approved_users_count)
193
+ end
194
+ end
195
+
196
+ class FirstMessageboard < FirstSeedData
197
+ MODEL_CLASS = Messageboard
198
+
199
+ def create
200
+ log 'Creating a messageboard...'
201
+ @first_messageboard = FactoryGirl.create(
202
+ :messageboard,
203
+ name: 'Main Board',
204
+ slug: 'main-board',
205
+ description: 'A board is not a board without some posts'
206
+ )
207
+ end
208
+ end
209
+
210
+ class Topics < CollectionSeedData
211
+ MODEL_CLASS = Topic
212
+
213
+ def create(count: 1, messageboard: seeder.first_messageboard)
214
+ log "Creating #{count} topics in #{messageboard.name}..."
215
+ FactoryGirl.create_list(
216
+ :topic, count,
217
+ messageboard: messageboard,
218
+ user: seeder.users.sample,
219
+ last_user: seeder.users.sample
220
+ )
221
+ end
222
+ end
223
+
224
+ class PrivateTopics < CollectionSeedData
225
+ MODEL_CLASS = PrivateTopic
226
+
227
+ def create(count: 1)
228
+ FactoryGirl.create_list(
229
+ :private_topic, count,
230
+ user: seeder.users[1..-1].sample,
231
+ last_user: seeder.users.sample,
232
+ users: [seeder.first_user]
233
+ )
234
+ end
235
+ end
236
+
237
+ class Posts < CollectionSeedData
238
+ MODEL_CLASS = Post
239
+
240
+ def create(count: (1..1))
241
+ log "Creating #{count} additional posts in each topic..."
242
+ seeder.topics.flat_map do |topic|
243
+ written = (1 + rand(5)).days.ago
244
+ posts = Array.new((count.min + rand(count.max + 1))) do
245
+ written += (1 + rand(60)).minutes
246
+ FactoryGirl.create(:post, postable: topic, messageboard: seeder.first_messageboard,
247
+ user: seeder.users.sample, created_at: written, updated_at: written)
248
+ end
249
+ topic.update!(last_user_id: posts.last.user.id, updated_at: written)
250
+ posts
251
+ end
252
+ end
253
+ end
254
+
255
+ class PrivatePosts < CollectionSeedData
256
+ MODEL_CLASS = PrivatePost
257
+
258
+ def create(count: (1..1))
259
+ log "Creating #{count} additional posts in each private topic..."
260
+ seeder.private_topics.flat_map do |topic|
261
+ (count.min + rand(count.max + 1)).times do
262
+ FactoryGirl.create(:private_post, postable: topic, user: seeder.users.sample)
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end
269
+ # rubocop:enable Metrics/ClassLength
@@ -12,7 +12,7 @@ module Thredded
12
12
  end
13
13
  end
14
14
 
15
- def respond_to?(method, *args)
15
+ def respond_to_missing?(method, *args)
16
16
  super || main_app_route_method?(method)
17
17
  end
18
18
 
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Thredded
3
- VERSION = '0.6.2'
3
+ VERSION = '0.6.3'
4
4
  end
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.version = Thredded::VERSION
10
10
  s.authors = ['Joel Oliveira', 'Gleb Mazovetskiy']
11
11
  s.email = ['joel@thredded.com', 'glex.spb@gmail.com']
12
- s.homepage = 'https://www.thredded.com'
12
+ s.homepage = 'https://thredded.org'
13
13
  s.summary = 'The best Rails forums engine ever.'
14
14
  s.license = 'MIT'
15
15
  s.description = 'The best Rails 4.2+ forums engine ever. Its goal is to be as simple and feature rich as possible.
@@ -56,8 +56,8 @@ Thredded works with SQLite, MySQL (v5.6.4+), and PostgreSQL. See the demo at htt
56
56
  s.add_development_dependency 'factory_girl_rails'
57
57
  s.add_development_dependency 'faker', '>= 1.6.2'
58
58
  s.add_development_dependency 'launchy'
59
- s.add_development_dependency 'rspec-rails'
60
- s.add_development_dependency 'rubocop', '~> 0.39'
59
+ s.add_development_dependency 'rspec-rails', '>= 3.5.0'
60
+ s.add_development_dependency 'rubocop', '= 0.42.0'
61
61
  s.add_development_dependency 'test-unit'
62
62
 
63
63
  # dummy app dependencies
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thredded
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Oliveira
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-06-30 00:00:00.000000000 Z
12
+ date: 2016-08-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bbcoder
@@ -423,28 +423,28 @@ dependencies:
423
423
  requirements:
424
424
  - - ">="
425
425
  - !ruby/object:Gem::Version
426
- version: '0'
426
+ version: 3.5.0
427
427
  type: :development
428
428
  prerelease: false
429
429
  version_requirements: !ruby/object:Gem::Requirement
430
430
  requirements:
431
431
  - - ">="
432
432
  - !ruby/object:Gem::Version
433
- version: '0'
433
+ version: 3.5.0
434
434
  - !ruby/object:Gem::Dependency
435
435
  name: rubocop
436
436
  requirement: !ruby/object:Gem::Requirement
437
437
  requirements:
438
- - - "~>"
438
+ - - '='
439
439
  - !ruby/object:Gem::Version
440
- version: '0.39'
440
+ version: 0.42.0
441
441
  type: :development
442
442
  prerelease: false
443
443
  version_requirements: !ruby/object:Gem::Requirement
444
444
  requirements:
445
- - - "~>"
445
+ - - '='
446
446
  - !ruby/object:Gem::Version
447
- version: '0.39'
447
+ version: 0.42.0
448
448
  - !ruby/object:Gem::Dependency
449
449
  name: test-unit
450
450
  requirement: !ruby/object:Gem::Requirement
@@ -668,6 +668,7 @@ files:
668
668
  - app/assets/stylesheets/thredded/utilities/_is-expanded.scss
669
669
  - app/commands/thredded/at_notification_extractor.rb
670
670
  - app/commands/thredded/autofollow_mentioned_users.rb
671
+ - app/commands/thredded/mark_all_read.rb
671
672
  - app/commands/thredded/members_marked_notified.rb
672
673
  - app/commands/thredded/messageboard_destroyer.rb
673
674
  - app/commands/thredded/moderate_post.rb
@@ -683,6 +684,7 @@ files:
683
684
  - app/controllers/thredded/preferences_controller.rb
684
685
  - app/controllers/thredded/private_post_permalinks_controller.rb
685
686
  - app/controllers/thredded/private_topics_controller.rb
687
+ - app/controllers/thredded/read_states_controller.rb
686
688
  - app/controllers/thredded/theme_previews_controller.rb
687
689
  - app/controllers/thredded/topics_controller.rb
688
690
  - app/forms/thredded/private_topic_form.rb
@@ -861,6 +863,7 @@ files:
861
863
  - lib/tasks/thredded_tasks.rake
862
864
  - lib/thredded.rb
863
865
  - lib/thredded/content_formatter.rb
866
+ - lib/thredded/database_seeder.rb
864
867
  - lib/thredded/engine.rb
865
868
  - lib/thredded/errors.rb
866
869
  - lib/thredded/main_app_route_delegator.rb
@@ -868,7 +871,7 @@ files:
868
871
  - lib/thredded/topics_search.rb
869
872
  - lib/thredded/version.rb
870
873
  - thredded.gemspec
871
- homepage: https://www.thredded.com
874
+ homepage: https://thredded.org
872
875
  licenses:
873
876
  - MIT
874
877
  metadata: {}