markable 0.0.4

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 (67) hide show
  1. data/README.md +199 -0
  2. data/Rakefile +38 -0
  3. data/lib/generators/markable/migration/migration_generator.rb +39 -0
  4. data/lib/generators/markable/migration/templates/active_record/migration.rb +17 -0
  5. data/lib/markable.rb +95 -0
  6. data/lib/markable/acts_as_markable.rb +155 -0
  7. data/lib/markable/acts_as_marker.rb +62 -0
  8. data/lib/markable/exceptions.rb +7 -0
  9. data/lib/markable/version.rb +3 -0
  10. data/lib/models/mark.rb +6 -0
  11. data/test/acts_as_markable_test.rb +219 -0
  12. data/test/acts_as_marker_test.rb +165 -0
  13. data/test/dummy/README.rdoc +261 -0
  14. data/test/dummy/Rakefile +7 -0
  15. data/test/dummy/app/assets/javascripts/application.js +15 -0
  16. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  17. data/test/dummy/app/controllers/application_controller.rb +3 -0
  18. data/test/dummy/app/helpers/application_helper.rb +2 -0
  19. data/test/dummy/app/models/admin.rb +4 -0
  20. data/test/dummy/app/models/drink.rb +3 -0
  21. data/test/dummy/app/models/food.rb +4 -0
  22. data/test/dummy/app/models/user.rb +4 -0
  23. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  24. data/test/dummy/config.ru +4 -0
  25. data/test/dummy/config/application.rb +56 -0
  26. data/test/dummy/config/boot.rb +10 -0
  27. data/test/dummy/config/database.yml +25 -0
  28. data/test/dummy/config/environment.rb +5 -0
  29. data/test/dummy/config/environments/development.rb +37 -0
  30. data/test/dummy/config/environments/production.rb +67 -0
  31. data/test/dummy/config/environments/test.rb +37 -0
  32. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  33. data/test/dummy/config/initializers/inflections.rb +15 -0
  34. data/test/dummy/config/initializers/mime_types.rb +5 -0
  35. data/test/dummy/config/initializers/secret_token.rb +7 -0
  36. data/test/dummy/config/initializers/session_store.rb +8 -0
  37. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  38. data/test/dummy/config/locales/en.yml +5 -0
  39. data/test/dummy/config/routes.rb +58 -0
  40. data/test/dummy/db/development.sqlite3 +0 -0
  41. data/test/dummy/db/migrate/20120214103734_create_users.rb +9 -0
  42. data/test/dummy/db/migrate/20120214103741_create_admins.rb +9 -0
  43. data/test/dummy/db/migrate/20120214105411_create_foods.rb +9 -0
  44. data/test/dummy/db/migrate/20120214105421_create_drinks.rb +9 -0
  45. data/test/dummy/db/migrate/20120214114957_markable_migration.rb +17 -0
  46. data/test/dummy/db/production.sqlite3 +0 -0
  47. data/test/dummy/db/schema.rb +52 -0
  48. data/test/dummy/db/test.sqlite3 +0 -0
  49. data/test/dummy/log/development.log +134 -0
  50. data/test/dummy/log/production.log +0 -0
  51. data/test/dummy/log/test.log +93646 -0
  52. data/test/dummy/public/404.html +26 -0
  53. data/test/dummy/public/422.html +26 -0
  54. data/test/dummy/public/500.html +25 -0
  55. data/test/dummy/public/favicon.ico +0 -0
  56. data/test/dummy/script/rails +6 -0
  57. data/test/dummy/test/fixtures/admins.yml +7 -0
  58. data/test/dummy/test/fixtures/drinks.yml +7 -0
  59. data/test/dummy/test/fixtures/foods.yml +7 -0
  60. data/test/dummy/test/fixtures/users.yml +7 -0
  61. data/test/dummy/test/unit/admin_test.rb +7 -0
  62. data/test/dummy/test/unit/drink_test.rb +7 -0
  63. data/test/dummy/test/unit/food_test.rb +7 -0
  64. data/test/dummy/test/unit/user_test.rb +7 -0
  65. data/test/support/get.rb +8 -0
  66. data/test/test_helper.rb +10 -0
  67. metadata +196 -0
@@ -0,0 +1,62 @@
1
+ module Markable
2
+ module ActsAsMarker
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ end
7
+
8
+ module ClassMethods
9
+ def acts_as_marker(options = {})
10
+ Markable.set_models ActiveRecord::Base.connection.tables.collect{|t| t.classify rescue nil }.compact
11
+
12
+ cattr_accessor :marker_name
13
+ self.marker_name = self.name.downcase.to_sym
14
+
15
+ class_eval do
16
+ has_many :marker_marks, :class_name => 'Markable::Mark', :as => :marker
17
+ end
18
+ class_eval do
19
+ include Markable::ActsAsMarker::MarkerInstanceMethods
20
+ end
21
+ Markable.add_marker self
22
+ end
23
+ end
24
+
25
+ module MarkerInstanceMethods
26
+ def method_missing( method_sym, *args )
27
+ Markable.models.each { |model_name|
28
+ if method_sym.to_s =~ Regexp.new("^[\\w_]+_#{model_name.downcase.pluralize}$") ||
29
+ method_sym.to_s =~ Regexp.new("^#{model_name.downcase.pluralize}_marked_as(_[\\w_]+)?$")
30
+ model_name.constantize # ping model
31
+ if self.methods.include? method_sym # method has appear
32
+ return self.method(method_sym).call(args) if args.count > 0 # call this method
33
+ return self.method(method_sym).call
34
+ end
35
+ end
36
+ }
37
+ super
38
+ rescue
39
+ super
40
+ end
41
+
42
+ def set_mark mark, markables
43
+ markables = [ markables ] unless markables.kind_of? Array
44
+ markables.each do |markable|
45
+ Markable.can_mark_or_raise? self, markable, mark
46
+ markable.mark_as mark, self
47
+ end
48
+ end
49
+
50
+ def remove_mark mark, markables
51
+ markables = [ markables ] unless markables.kind_of? Array
52
+ Markable.can_mark_or_raise? self, markables, mark
53
+ markables.each do |markable|
54
+ markable.unmark mark, :by => self
55
+ end
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ ActiveRecord::Base.send :include, Markable::ActsAsMarker
@@ -0,0 +1,7 @@
1
+ module Markable
2
+ class WrongMarkableType < Exception
3
+ def initialize()
4
+ super 'Wrong markable type'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Markable
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,6 @@
1
+ module Markable
2
+ class Mark < ActiveRecord::Base
3
+ belongs_to :markable, :polymorphic => true
4
+ belongs_to :marker, :polymorphic => true
5
+ end
6
+ end
@@ -0,0 +1,219 @@
1
+ require 'test_helper'
2
+
3
+ class ActsAsMarkableTest < ActiveSupport::TestCase
4
+
5
+ # Config tests
6
+
7
+ test "a drink's markable_marks[:favorite] should not be nil" do
8
+ assert_not_nil Drink.markable_marks[:favorite]
9
+ end
10
+
11
+ test "a food's markable_marks[:favorite] should not be nil" do
12
+ assert_not_nil Food.markable_marks[:favorite]
13
+ assert_not_nil Food.markable_marks[:hated]
14
+ end
15
+
16
+ test "a food's markable_marks[:favorite][:allowed_markers] should be :all" do
17
+ assert_equal :all, Food.markable_marks[:favorite][:allowed_markers]
18
+ end
19
+
20
+ test "a drink's markable_marks[:favorite][:allowed_markers] should be [:admin]" do
21
+ assert_equal [:admin], Drink.markable_marks[:favorite][:allowed_markers]
22
+ end
23
+
24
+ test "a user favorite 2 types of food and 1 drink, favorite_foods should contain both foods, favorite_drinks should contain 1 drink" do
25
+ admin1 = Admin.create :name => 'Admin1'
26
+ food1 = Food.create :name => 'Food1'
27
+ food2 = Food.create :name => 'Food2'
28
+ drink1 = Drink.create :name => 'Drink1'
29
+
30
+ admin1.favorite_foods << [food1, food2]
31
+ admin1.favorite_drinks << drink1
32
+
33
+ assert_equal [food1, food2], admin1.favorite_foods
34
+ assert_equal [drink1], admin1.favorite_drinks
35
+ end
36
+
37
+ # Methods
38
+
39
+ test "food.mark_as" do
40
+ u1, u2 = get(User, 2)
41
+ f1, f2 = get(Food, 2)
42
+ assert_equal [], f1.users_have_marked_as(:favorite)
43
+ f1.mark_as :favorite, u1
44
+ assert_equal [ u1 ], f1.users_have_marked_as(:favorite)
45
+ assert_equal [ f1 ], u1.favorite_foods
46
+ f2.mark_as :favorite, [u1, u2]
47
+ assert_equal [ u1, u2 ], f2.users_have_marked_as(:favorite)
48
+ assert_equal [ f1, f2 ], u1.favorite_foods
49
+ assert_equal [ f2 ], u2.favorite_foods
50
+ end
51
+
52
+ test "food.users_have_marked_as_favorite" do
53
+ u1, u2 = get(User, 2)
54
+ f1, f2 = get(Food, 2)
55
+ assert_equal [], f1.users_have_marked_as_favorite
56
+ f1.users_have_marked_as_favorite << u1
57
+ assert_equal [ u1 ], f1.users_have_marked_as_favorite
58
+ assert_equal [ f1 ], u1.favorite_foods
59
+ f2.users_have_marked_as_favorite << [u1, u2]
60
+ assert_equal [ u1, u2 ], f2.users_have_marked_as_favorite
61
+ assert_equal [ f1, f2 ], u1.favorite_foods
62
+ assert_equal [ f2 ], u2.favorite_foods
63
+ end
64
+
65
+ test "food.users_have_marked_as" do
66
+ u1, u2 = get(User, 2)
67
+ f1, f2 = get(Food, 2)
68
+ assert_equal [], f1.users_have_marked_as(:favorite)
69
+ f1.users_have_marked_as(:favorite) << u1
70
+ assert_equal [ u1 ], f1.users_have_marked_as(:favorite)
71
+ assert_equal [ f1 ], u1.favorite_foods
72
+ f2.users_have_marked_as(:favorite) << [u1, u2]
73
+ assert_equal [ u1, u2 ], f2.users_have_marked_as(:favorite)
74
+ assert_equal [ f1, f2 ], u1.favorite_foods
75
+ assert_equal [ f2 ], u2.favorite_foods
76
+ end
77
+
78
+ test "Food.marked_as" do
79
+ u1, u2 = get(User, 2)
80
+ f1, f2, f3 = get(Food, 3)
81
+ assert_equal [], Food.marked_as(:favorite)
82
+ u1.favorite_foods << [ f1, f3 ]
83
+ u2.favorite_foods << f2
84
+ assert_equal [ f1, f2, f3 ], Food.marked_as(:favorite)
85
+ assert_equal [ f1, f3 ], Food.marked_as(:favorite, :by => u1)
86
+ assert_equal [ f2 ], Food.marked_as(:favorite, :by => u2)
87
+ end
88
+
89
+ test "Food.marked_as_favorite" do
90
+ u1, u2 = get(User, 2)
91
+ f1, f2, f3 = get(Food, 3)
92
+ assert_equal [], Food.marked_as_favorite
93
+ u1.favorite_foods << [ f1, f3 ]
94
+ u2.favorite_foods << f2
95
+ assert_equal [ f1, f2, f3 ], Food.marked_as_favorite
96
+ assert_equal [ f1, f3 ], Food.marked_as_favorite(:by => u1)
97
+ assert_equal [ f2 ], Food.marked_as_favorite(:by => u2)
98
+ end
99
+
100
+ test "food.marked_as?" do
101
+ u1, u2 = get(User, 2)
102
+ f1, f2 = get(Food, 2)
103
+
104
+ assert !f1.marked_as_favorite?
105
+
106
+ u1.favorite_foods << [f1]
107
+ u2.favorite_foods << [f2]
108
+
109
+ assert f1.marked_as?(:favorite)
110
+ assert f1.marked_as_favorite?
111
+ assert f1.marked_as_favorite?(:by => u1)
112
+ assert !f1.marked_as_favorite?(:by => u2)
113
+ end
114
+
115
+ test "admin should have proper methods" do
116
+ admin = Admin.create :name => 'Admin'
117
+ assert_nothing_raised(NoMethodError) {
118
+ admin.favorite_foods
119
+ }
120
+ assert_nothing_raised(NoMethodError) {
121
+ admin.favorite_drinks
122
+ }
123
+ end
124
+
125
+ test "a drink marked as favorite with << by user, should be in favorite_drinks list of this user" do
126
+ admin1 = Admin.create :name => 'Admin1'
127
+ drink1 = Drink.create :name => 'Drink1'
128
+ admin1.favorite_drinks << drink1
129
+ assert_equal [drink1], admin1.favorite_drinks
130
+ end
131
+
132
+ test "a drink marked as favorite with mark_as by user, should be in favorite_drinks list of this user" do
133
+ admin1 = Admin.create :name => 'Admin1'
134
+ drink1 = Drink.create :name => 'Drink1'
135
+ admin1.set_mark :favorite, drink1
136
+ assert_equal [drink1], admin1.favorite_drinks
137
+ end
138
+
139
+ test "user.mark_as_favorite should mark food as favorite" do
140
+ user1 = User.create :name => 'User1'
141
+ food1 = Food.create :name => 'Food1'
142
+ food2 = Food.create :name => 'Food2'
143
+ user1.mark_as_favorite [food1, food2]
144
+
145
+ assert_equal [food1, food2], user1.favorite_foods
146
+ end
147
+
148
+ test "user.mark_as_favorite should not mark drink as favorite" do
149
+ user1 = User.create :name => 'User1'
150
+ drink1 = Drink.create :name => 'Drink1'
151
+
152
+ assert_raise(Markable::WrongMarkableType) {
153
+ user1.mark_as_favorite drink1
154
+ }
155
+ end
156
+
157
+ test "admin.mark_as_favorite" do
158
+ admin1 = Admin.create :name => 'Admin1'
159
+ food1 = Food.create :name => 'Food1'
160
+ drink1 = Drink.create :name => 'Drink1'
161
+ admin1.mark_as_favorite [food1, drink1]
162
+ end
163
+
164
+ test "food.remove_mark" do
165
+ u1, u2 = get(User, 2)
166
+ f1, f2 = get(Food, 2)
167
+ u1.favorite_foods << [f1, f2]
168
+ u2.favorite_foods << [f1, f2]
169
+ assert_equal [f1, f2], u1.favorite_foods
170
+ assert_equal [f1, f2], u2.favorite_foods
171
+ f1.unmark :favorite, :by => u1
172
+ assert_equal [u2], f1.users_have_marked_as_favorite
173
+ assert_equal [u1, u2], f2.users_have_marked_as_favorite
174
+ f2.unmark :favorite
175
+ assert_equal [u2], f1.users_have_marked_as_favorite
176
+ assert_equal [], f2.users_have_marked_as_favorite
177
+ end
178
+ test "food.users_have_marked_as_favorite.delete" do
179
+ u1, u2 = get(User, 2)
180
+ f1, f2 = get(Food, 2)
181
+ u1.favorite_foods << [f1, f2]
182
+ u2.favorite_foods << [f1, f2]
183
+ assert_equal [f1, f2], u1.favorite_foods
184
+ assert_equal [f1, f2], u2.favorite_foods
185
+ f1.users_have_marked_as_favorite.delete(u1)
186
+ f2.users_have_marked_as_favorite.delete(u2)
187
+ assert_equal [u2], f1.users_have_marked_as_favorite
188
+ assert_equal [u1], f2.users_have_marked_as_favorite
189
+ end
190
+
191
+ # Errors
192
+
193
+ test "markables can't be marked by not allowed markers" do
194
+ marker = User.create :name => 'marker'
195
+ markable = Drink.create :name => 'markable'
196
+
197
+ assert_raise(NoMethodError) {
198
+ marker.favorite_drinks
199
+ }
200
+ assert_raise(NoMethodError) {
201
+ markable.users_have_marked_as_favorite
202
+ }
203
+ assert_raise(Markable::WrongMarkableType) {
204
+ markable.admins_have_marked_as_favorite << marker
205
+ }
206
+ assert_raise(Markable::WrongMarkableType) {
207
+ markable.mark_as :favorite, marker
208
+ }
209
+ end
210
+
211
+ test "markables can be marked by allowed markers" do
212
+ marker = User.create :name => 'marker'
213
+ markable = Food.create :name => 'markable'
214
+
215
+ markable.users_have_marked_as_favorite << marker
216
+ assert_equal [ markable ], marker.favorite_foods
217
+ assert_equal [ marker ], markable.users_have_marked_as_favorite
218
+ end
219
+ end
@@ -0,0 +1,165 @@
1
+ require 'test_helper'
2
+
3
+ class ActsAsMarkerTest < ActiveSupport::TestCase
4
+
5
+ # Config
6
+
7
+ test "a_users_marker_name_should_be_user" do
8
+ assert_equal :user, User.marker_name
9
+ end
10
+
11
+ # Methods
12
+
13
+ test "user.favorite_foods" do
14
+ u1, u2 = get(User, 2)
15
+ f1, f2 = get(Food, 2)
16
+ assert_equal [], u1.favorite_foods
17
+ u1.favorite_foods << f1
18
+ assert_equal [ f1 ], u1.favorite_foods
19
+ u2.favorite_foods << [f1, f2]
20
+ assert_equal [ f1, f2 ], u2.favorite_foods
21
+ end
22
+
23
+ test "user.foods_marked_as" do
24
+ u1, u2 = get(User, 2)
25
+ f1, f2 = get(Food, 2)
26
+ assert_equal [], u1.foods_marked_as(:favorite)
27
+ u1.foods_marked_as(:favorite) << f1
28
+ assert_equal [ f1 ], u1.foods_marked_as(:favorite)
29
+ u2.foods_marked_as(:favorite) << [f1, f2]
30
+ assert_equal [ f1, f2 ], u2.foods_marked_as(:favorite)
31
+ end
32
+
33
+ test "user.foods_marked_as_favorite" do
34
+ u1, u2 = get(User, 2)
35
+ f1, f2 = get(Food, 2)
36
+ assert_equal [], u1.foods_marked_as_favorite
37
+ u1.foods_marked_as_favorite << f1
38
+ assert_equal [ f1 ], u1.foods_marked_as_favorite
39
+ u2.foods_marked_as_favorite << [f1, f2]
40
+ assert_equal [ f1, f2 ], u2.foods_marked_as_favorite
41
+ end
42
+
43
+ test "user.set_mark_to" do
44
+ u1, u2 = get(User, 2)
45
+ f1, f2 = get(Food, 2)
46
+ assert_equal [], u1.favorite_foods
47
+ u1.set_mark :favorite, f1
48
+ assert_equal [ f1 ], u1.favorite_foods
49
+ u2.set_mark :favorite, [f1, f2]
50
+ assert_equal [ f1, f2 ], u2.favorite_foods
51
+ end
52
+
53
+ test "user.remove_mark_from" do
54
+ u1 = get(User)
55
+ f1, f2 = get(Food, 2)
56
+ u1.favorite_foods << [f1, f2]
57
+ assert_equal [f1, f2], u1.favorite_foods
58
+ u1.remove_mark :favorite, f1
59
+ assert_equal [f2], u1.favorite_foods
60
+ end
61
+ test "user.favorite_foods.delete" do
62
+ u1 = get(User)
63
+ f1, f2 = get(Food, 2)
64
+ u1.favorite_foods << [f1, f2]
65
+ assert_equal [f1, f2], u1.favorite_foods
66
+ u1.favorite_foods.delete f1
67
+ assert_equal [f2], u1.favorite_foods
68
+ end
69
+
70
+ test "user.hated_food" do
71
+ u1 = get(User)
72
+ f1, f2 = get(Food, 2)
73
+
74
+ u1.hated_foods << f1
75
+ u1.favorite_foods << f2
76
+ assert_equal [ f1 ], u1.hated_foods
77
+ assert_equal [ f2 ], u1.favorite_foods
78
+ end
79
+
80
+ # Errors
81
+
82
+ test "markers can mark allowed markables" do
83
+ marker = User.create :name => 'marker'
84
+ markable = Food.create :name => 'markable'
85
+
86
+ marker.favorite_foods << markable
87
+ assert_equal [ markable ], marker.favorite_foods
88
+ assert_equal [ marker ], markable.users_have_marked_as_favorite
89
+ end
90
+
91
+ test "markers can't mark not allowed markables" do
92
+ marker = User.create :name => 'marker'
93
+ markable = Drink.create :name => 'markable'
94
+
95
+ assert_raise(NoMethodError) {
96
+ marker.favorite_drinks
97
+ }
98
+ assert_raise(NoMethodError) {
99
+ markable.users_have_marked_as_favorite
100
+ }
101
+ assert_raise(Markable::WrongMarkableType) {
102
+ marker.favorite_foods << markable
103
+ }
104
+ assert_raise(Markable::WrongMarkableType) {
105
+ marker.set_mark :favorite, markable
106
+ }
107
+ end
108
+
109
+ test "marker can't mark not markable" do
110
+ marker1 = User.create :name => 'marker'
111
+ marker2 = User.create :name => 'marker'
112
+
113
+ assert_raise(Markable::WrongMarkableType) {
114
+ marker1.set_mark :favorite, marker2
115
+ }
116
+ assert_raise(Markable::WrongMarkableType) {
117
+ marker1.set_mark :favorite, 'STRING'
118
+ }
119
+ assert_raise(Markable::WrongMarkableType) {
120
+ marker1.favorite_foods << marker2
121
+ }
122
+ assert_raise(Markable::WrongMarkableType) {
123
+ marker1.favorite_foods << 'STRING'
124
+ }
125
+ end
126
+
127
+ test "errors in mark removal" do
128
+ u1, u2 = get(User, 2)
129
+ f1, f2 = get(Food, 2)
130
+ u1.favorite_foods << [f1, f2]
131
+ u2.favorite_foods << [f1, f2]
132
+ assert_equal [f1, f2], u1.favorite_foods
133
+ assert_equal [f1, f2], u2.favorite_foods
134
+
135
+ assert_raise(Markable::WrongMarkableType) {
136
+ f1.users_have_marked_as_favorite.delete(f2)
137
+ }
138
+ assert_raise(Markable::WrongMarkableType) {
139
+ f1.users_have_marked_as_favorite.delete('STRING')
140
+ }
141
+ assert_raise(NoMethodError) {
142
+ u1.users_have_marked_as_favorite.delete(u2)
143
+ }
144
+
145
+ assert_raise(Markable::WrongMarkableType) {
146
+ f1.unmark :favorite, :by => f2
147
+ }
148
+ assert_raise(Markable::WrongMarkableType) {
149
+ f1.unmark :favorite, :by => 'STRING'
150
+ }
151
+ assert_raise(Markable::WrongMarkableType, NoMethodError) {
152
+ u1.remove_mark :favorite, :by => f1
153
+ }
154
+
155
+ assert_raise(Markable::WrongMarkableType) {
156
+ u1.favorite_foods.delete u2
157
+ }
158
+ assert_raise(Markable::WrongMarkableType) {
159
+ u1.favorite_foods.delete 'STRING'
160
+ }
161
+ assert_raise(NoMethodError) {
162
+ f1.favorite_foods.delete f2
163
+ }
164
+ end
165
+ end