thredded 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
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: {}