interest 0.0.1

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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +26 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +329 -0
  7. data/Rakefile +2 -0
  8. data/interest.gemspec +29 -0
  9. data/lib/generators/interest_generator.rb +18 -0
  10. data/lib/generators/templates/migrations/blockings.rb +14 -0
  11. data/lib/generators/templates/migrations/followings.rb +15 -0
  12. data/lib/generators/templates/models/blocking.rb +3 -0
  13. data/lib/generators/templates/models/following.rb +4 -0
  14. data/lib/interest.rb +49 -0
  15. data/lib/interest/base.rb +49 -0
  16. data/lib/interest/blockable.rb +25 -0
  17. data/lib/interest/blockable/blockee.rb +40 -0
  18. data/lib/interest/blockable/blocker.rb +69 -0
  19. data/lib/interest/blockable/blocking.rb +48 -0
  20. data/lib/interest/blockable/exceptions.rb +12 -0
  21. data/lib/interest/definition.rb +45 -0
  22. data/lib/interest/exception.rb +10 -0
  23. data/lib/interest/follow_requestable.rb +25 -0
  24. data/lib/interest/follow_requestable/exceptions.rb +12 -0
  25. data/lib/interest/follow_requestable/follow_request.rb +45 -0
  26. data/lib/interest/follow_requestable/follow_requestee.rb +45 -0
  27. data/lib/interest/follow_requestable/follow_requester.rb +92 -0
  28. data/lib/interest/followable.rb +25 -0
  29. data/lib/interest/followable/exceptions.rb +12 -0
  30. data/lib/interest/followable/followee.rb +41 -0
  31. data/lib/interest/followable/follower.rb +68 -0
  32. data/lib/interest/followable/following.rb +62 -0
  33. data/lib/interest/utils.rb +29 -0
  34. data/lib/interest/version.rb +3 -0
  35. data/spec/blockable_spec.rb +127 -0
  36. data/spec/database.yml.example +3 -0
  37. data/spec/follow_requestable_spec.rb +126 -0
  38. data/spec/followable_spec.rb +171 -0
  39. data/spec/models/blocking_spec.rb +42 -0
  40. data/spec/models/following_spec.rb +120 -0
  41. data/spec/spec_helper.rb +103 -0
  42. data/spec/support/database.rb +10 -0
  43. data/spec/support/models/blockable_user.rb +8 -0
  44. data/spec/support/models/blocking.rb +4 -0
  45. data/spec/support/models/collection.rb +6 -0
  46. data/spec/support/models/follow_requestable_and_blockable_user.rb +8 -0
  47. data/spec/support/models/follow_requestable_user.rb +9 -0
  48. data/spec/support/models/followable_and_blockable_user.rb +9 -0
  49. data/spec/support/models/followable_user.rb +8 -0
  50. data/spec/support/models/following.rb +4 -0
  51. data/spec/support/models/stuff.rb +6 -0
  52. data/spec/support/schema.rb +26 -0
  53. metadata +211 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fc82c4e1059269fa9b2883ec3e3b44a5abeb3b13
4
+ data.tar.gz: 3261ddd2763d276aeb65f99d2aed75385a0870a8
5
+ SHA512:
6
+ metadata.gz: d0d24030c45c3fa07c7cecf3936324f7b24215bb55485982582568856fa4253d9602fe454cfa8fdb05bc0935923e0069acf6a586d97c9800dbc773fce7825385
7
+ data.tar.gz: f0de0016b106f52a0baa34f6d78ae2e115d4f84d3cdb83c1de75427a90c84288e097e7f715a3ea2612f99582af6497db3c60fb0347debfa08d13d6a3047f19f9
data/.gitignore ADDED
@@ -0,0 +1,26 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+
24
+ vendor/bundle
25
+ spec/database.yml
26
+ spec/*.sqlite3
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in interest.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 tatat
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,329 @@
1
+ # Interest
2
+
3
+ a gem to follow, follow request and block between any ActiveRecord models.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'interest'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install interest
18
+
19
+ ### Post installation
20
+
21
+ #### Install migrations and models
22
+
23
+ ```
24
+ bin/rails generate interest
25
+ ```
26
+
27
+ #### Migrate
28
+
29
+ ```
30
+ bin/rake db:migrate
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ### Setup
36
+
37
+ Create User and Blog model as one example.
38
+
39
+ ```ruby
40
+ class User < ActiveRecord::Base
41
+ interest
42
+ end
43
+
44
+ class Blog < ActiveRecord::Base
45
+ interest
46
+ end
47
+
48
+ user = User.create!
49
+ blog = Blog.create!
50
+ ```
51
+
52
+ ### Follow
53
+
54
+ To follow,
55
+
56
+ ```ruby
57
+ following = user.follow!(blog)
58
+ ```
59
+
60
+ returns `Following` or raises `Interest::Followable::Rejected`.
61
+
62
+ Otherwise,
63
+
64
+ ```ruby
65
+ following = user.follow(blog)
66
+ ```
67
+
68
+ returns `Following` or `nil`.
69
+
70
+ Returned `Following` is the following.
71
+
72
+ ```ruby
73
+ following.follower == user # => true
74
+ following.followee == blog # => true
75
+ following.status # => "accepted"
76
+ ```
77
+
78
+ To unfollow,
79
+
80
+ ```ruby
81
+ user.unfollow(blog)
82
+ ```
83
+
84
+ To check whether the user is following the blog or not,
85
+
86
+ ```ruby
87
+ user.following?(blog)
88
+ ```
89
+
90
+ or
91
+
92
+ ```ruby
93
+ blog.followed_by?(user)
94
+ ```
95
+
96
+ #### Associations
97
+
98
+ ```ruby
99
+ user.following_relationships.of(Blog)
100
+ ```
101
+
102
+ and
103
+
104
+ ```ruby
105
+ blog.follower_relationships.of(User)
106
+ ```
107
+
108
+ returns `ActiveRecord::Associations::CollectionProxy` for `Following` belongs to `User` and `Blog`.
109
+
110
+ ```ruby
111
+ user.following_blogs
112
+ ```
113
+
114
+ returns `ActiveRecord::Associations::CollectionProxy` for `Blog`.
115
+
116
+ ```ruby
117
+ blog.follower_users
118
+ ```
119
+
120
+ returns `ActiveRecord::Associations::CollectionProxy` for `User`.
121
+
122
+ "blogs" and "users" part of the above are conditional on a class.
123
+
124
+ e.g.
125
+
126
+ ```ruby
127
+ other_user = OtherUser.create!
128
+ user.follow(other_user) # follows OtherUser
129
+ ```
130
+
131
+ then
132
+
133
+ ```ruby
134
+ user.following_other_users
135
+ ```
136
+
137
+ (It's just like `"ClassName".underscore.pluralize`)
138
+
139
+ ### Follow request
140
+
141
+ To request to follow,
142
+
143
+ ```ruby
144
+ following = user.request_to_follow!(blog)
145
+ ```
146
+
147
+ returns `Following` or raises `Interest::FollowRequestable::Rejected`.
148
+
149
+ Otherwise,
150
+
151
+ ```ruby
152
+ following = user.request_to_follow!(blog)
153
+ ```
154
+
155
+ returns `Following` or `nil`.
156
+
157
+ Returned `Following` is the following.
158
+
159
+ ```ruby
160
+ following.status # => "pending"
161
+ ```
162
+
163
+ To cancel request to follow,
164
+
165
+ ```ruby
166
+ user.cancel_request_to_follow(blog)
167
+ ```
168
+
169
+ To check whether the user has requested to follow the blog or not,
170
+
171
+ ```ruby
172
+ user.has_requested_to_follow?(blog)
173
+ ```
174
+
175
+ or
176
+
177
+ ```ruby
178
+ blog.has_been_requested_to_follow?(user)
179
+ ```
180
+
181
+ To accept request to follow, call `accept!` of `Following`
182
+
183
+ ```ruby
184
+ following = blog.incoming_follow_requests.of(User).find(id) # `Following.find(id)' is more simply.
185
+ following.accept!
186
+ ```
187
+
188
+ #### Associations
189
+
190
+ ```ruby
191
+ user.outgoing_follow_requests.of(Blog)
192
+ ```
193
+
194
+ and
195
+
196
+ ```ruby
197
+ blog.incoming_follow_requests.of(User)
198
+ ```
199
+
200
+ returns `ActiveRecord::Associations::CollectionProxy` for `Following` belongs to `User` and `Blog`
201
+
202
+ ```ruby
203
+ user.follow_requestee_blogs
204
+ ```
205
+
206
+ returns `ActiveRecord::Associations::CollectionProxy` for `Blog`
207
+
208
+ ```ruby
209
+ blog.follow_requester_users
210
+ ```
211
+
212
+ returns `ActiveRecord::Associations::CollectionProxy` for `User`
213
+
214
+ #### Note
215
+
216
+ `follow!` and `follow` methods don't check whether the user is required to request to follow the blog, so you should check it yourself.
217
+
218
+ In this case, you need to define (override) `requires_request_to_follow?` on `Blog` first.
219
+
220
+ ```ruby
221
+ class Blog < ActiveRecord::Base
222
+ # ...
223
+
224
+ def requires_request_to_follow?(follower)
225
+ true # or something
226
+ end
227
+ end
228
+ ```
229
+
230
+ Then, like the following
231
+
232
+ ```ruby
233
+ if user.required_request_to_follow?(blog)
234
+ user.request_to_follow(blog)
235
+ else
236
+ user.follow(blog)
237
+ end
238
+ ```
239
+
240
+ or
241
+
242
+ ```ruby
243
+ result = user.follow_or_request_to_follow!(blog)
244
+
245
+ if result.followed?
246
+ # when the user followed the blog
247
+ elsif result.requested_to_follow?
248
+ # when the user requested to follow the blog
249
+ end
250
+ ```
251
+
252
+ ### Block
253
+
254
+ To block,
255
+
256
+ ```ruby
257
+ blocking = blog.block!(user)
258
+ ```
259
+
260
+ returns `Blocking` or raises `Interest::Blockable::Rejected`.
261
+
262
+ Otherwise,
263
+
264
+ ```ruby
265
+ blocking = blog.block!(user)
266
+ ```
267
+
268
+ returns `Blocking` or `nil`
269
+
270
+ Returned `Blocking` is the following
271
+
272
+ ```ruby
273
+ blocking.blocker == blog # => true
274
+ blocking.blockee == user # => true
275
+ ```
276
+
277
+ Blocking destroys their folow and follow request relationships if they have.
278
+
279
+ To unblock,
280
+
281
+ ```ruby
282
+ blog.unblock(user)
283
+ ```
284
+
285
+ To check whether the blog is blocking the user or not,
286
+
287
+ ```ruby
288
+ blog.blocking?(user)
289
+ ```
290
+
291
+ or
292
+
293
+ ```ruby
294
+ user.blocked_by?(blog)
295
+ ```
296
+
297
+ #### Associations
298
+
299
+ ```ruby
300
+ blog.blocking_relationships.of(User)
301
+ ```
302
+
303
+ and
304
+
305
+ ```ruby
306
+ user.blocker_relationships.of(Blog)
307
+ ```
308
+
309
+ returns `ActiveRecord::Associations::CollectionProxy` for `Blocking` belongs to `Blog` and `User`
310
+
311
+ ```ruby
312
+ blog.blocking_users
313
+ ```
314
+
315
+ returns `ActiveRecord::Associations::CollectionProxy` for `User`
316
+
317
+ ```ruby
318
+ user.blocker_blogs
319
+ ```
320
+
321
+ returns `ActiveRecord::Associations::CollectionProxy` for `Blog`
322
+
323
+ ## Contributing
324
+
325
+ 1. Fork it ( https://github.com/conol/interest/fork )
326
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
327
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
328
+ 4. Push to the branch (`git push origin my-new-feature`)
329
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/interest.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'interest/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "interest"
8
+ spec.version = Interest::VERSION
9
+ spec.authors = ["tatat"]
10
+ spec.email = ["ioiioioloo@gmail.com"]
11
+ spec.summary = %q{Follow, follow request and block with ActiveRecord.}
12
+ spec.description = %q{A gem to follow, follow request and block between any ActiveRecord models.}
13
+ spec.homepage = "https://github.com/conol/interest"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport", "~> 4.0"
22
+ spec.add_dependency "activerecord", "~> 4.0"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake", "~> 10.3"
26
+ spec.add_development_dependency "sqlite3", "~> 1.3"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "rspec-collection_matchers", "~> 1"
29
+ end
@@ -0,0 +1,18 @@
1
+ require "rails/generators"
2
+ require "rails/generators/active_record"
3
+
4
+ class InterestGenerator < Rails::Generators::Base
5
+ include ActiveRecord::Generators::Migration
6
+
7
+ source_root File.expand_path("templates", File.dirname(__FILE__))
8
+
9
+ def create_migration_file
10
+ migration_template "migrations/followings.rb", "db/migrate/interest_followings_migration.rb"
11
+ migration_template "migrations/blockings.rb", "db/migrate/interest_blockings_migration.rb"
12
+ end
13
+
14
+ def create_model
15
+ copy_file "models/following.rb", "app/models/following.rb"
16
+ copy_file "models/blocking.rb", "app/models/blocking.rb"
17
+ end
18
+ end