neutral 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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +194 -0
- data/MIT-LICENSE +20 -0
- data/README.md +143 -0
- data/Rakefile +21 -0
- data/app/assets/stylesheets/neutral/index.css +43 -0
- data/app/controllers/neutral/application_controller.rb +22 -0
- data/app/controllers/neutral/votes_controller.rb +48 -0
- data/app/helpers/neutral/votes_helper.rb +16 -0
- data/app/models/neutral/vote.rb +26 -0
- data/app/models/neutral/voting.rb +39 -0
- data/app/views/neutral/votes/create.js.erb +27 -0
- data/app/views/neutral/votes/destroy.js.erb +18 -0
- data/app/views/neutral/votes/errors/cannot_change.js.erb +9 -0
- data/app/views/neutral/votes/errors/duplicate.js.erb +9 -0
- data/app/views/neutral/votes/errors/require_login.js.erb +10 -0
- data/app/views/neutral/votes/update.js.erb +11 -0
- data/bin/rails +8 -0
- data/config/locales/impartial.yml +6 -0
- data/config/routes.rb +3 -0
- data/lib/generators/neutral/formats.rb +16 -0
- data/lib/generators/neutral/install/install_generator.rb +47 -0
- data/lib/generators/neutral/install/templates/initializer.rb +41 -0
- data/lib/generators/neutral/install/templates/locale.yml +5 -0
- data/lib/generators/neutral/install/templates/votes.rb +12 -0
- data/lib/generators/neutral/install/templates/votings.rb +12 -0
- data/lib/generators/neutral/uninstall/templates/drop_neutral_votes_table.rb +9 -0
- data/lib/generators/neutral/uninstall/templates/drop_neutral_votings_table.rb +9 -0
- data/lib/generators/neutral/uninstall/uninstall_generator.rb +55 -0
- data/lib/neutral/configuration.rb +27 -0
- data/lib/neutral/engine.rb +28 -0
- data/lib/neutral/errors.rb +11 -0
- data/lib/neutral/helpers/action_view_extension.rb +19 -0
- data/lib/neutral/helpers/routes.rb +9 -0
- data/lib/neutral/icons/collection.rb +55 -0
- data/lib/neutral/icons/set.rb +22 -0
- data/lib/neutral/model/active_record_extension.rb +31 -0
- data/lib/neutral/model/vote_cached.rb +32 -0
- data/lib/neutral/version.rb +3 -0
- data/lib/neutral/voting_builder/builder.rb +42 -0
- data/lib/neutral/voting_builder/elements/link.rb +46 -0
- data/lib/neutral/voting_builder/elements/span.rb +41 -0
- data/lib/neutral/voting_builder/elements.rb +23 -0
- data/lib/neutral/voting_builder/router.rb +45 -0
- data/lib/neutral/voting_builder/structure.rb +21 -0
- data/lib/neutral.rb +46 -0
- data/neutral.gemspec +34 -0
- data/spec/controllers/votes_controller_spec.rb +138 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +29 -0
- data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
- data/spec/dummy/app/controllers/application_controller.rb +11 -0
- data/spec/dummy/app/controllers/posts_controller.rb +33 -0
- data/spec/dummy/app/controllers/sessions_controller.rb +21 -0
- data/spec/dummy/app/controllers/users_controller.rb +24 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/post.rb +3 -0
- data/spec/dummy/app/models/user.rb +7 -0
- data/spec/dummy/app/views/layouts/application.html.erb +25 -0
- data/spec/dummy/app/views/posts/_form.html.erb +21 -0
- data/spec/dummy/app/views/posts/index.html.erb +26 -0
- data/spec/dummy/app/views/posts/new.html.erb +5 -0
- data/spec/dummy/app/views/sessions/new.html.erb +18 -0
- data/spec/dummy/app/views/users/_form.html.erb +25 -0
- data/spec/dummy/app/views/users/new.html.erb +3 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +29 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +29 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +36 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/neutral.rb +41 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/locales/neutral.yml +5 -0
- data/spec/dummy/config/routes.rb +13 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20140110214145_create_posts.rb +9 -0
- data/spec/dummy/db/migrate/20140111225442_create_users.rb +10 -0
- data/spec/dummy/db/migrate/20140118172808881589_create_neutral_votes.rb +12 -0
- data/spec/dummy/db/migrate/20140118172808882161_create_neutral_votings.rb +12 -0
- data/spec/dummy/db/schema.rb +47 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories.rb +18 -0
- data/spec/helpers/action_view_extension_spec.rb +45 -0
- data/spec/icons/collection_spec.rb +38 -0
- data/spec/icons/set_spec.rb +25 -0
- data/spec/models/active_record_extension_spec.rb +49 -0
- data/spec/models/vote_spec.rb +51 -0
- data/spec/models/voting_spec.rb +60 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/shared_examples/controller_examples.rb +45 -0
- data/spec/support/votes_controller_base_class.rb +28 -0
- data/spec/support/votes_controller_helpers.rb +24 -0
- data/spec/voting_builder/builder_spec.rb +66 -0
- data/spec/voting_builder/elements/link_spec.rb +31 -0
- data/spec/voting_builder/elements/span_spec.rb +44 -0
- data/spec/voting_builder/router_spec.rb +57 -0
- data/spec/voting_builder/structure_spec.rb +59 -0
- metadata +449 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 27678637183996203a37b3887be25f347be8a784
|
|
4
|
+
data.tar.gz: a76fd757d8c8e389a38fb89f94c912baf592deb3
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6dfdec73927a16494db5b9dc5ecf8097d301c5aa995b7282e7035d0851cc0c0882a521ab4ae56bda9e8fae9c3f08427546669edcf5db73a895db84d086091652
|
|
7
|
+
data.tar.gz: aabe39f28693e565acaace9c7c897c32f7a698c878f0a1063ca69225037e1354da49804005763f7b9bbb416a9a83be9296709461188a5f0c9bfd95ce1432197e
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
neutral (0.0.1)
|
|
5
|
+
font-awesome-rails (~> 4.0.3.1)
|
|
6
|
+
jquery-rails
|
|
7
|
+
rails (~> 4.0.0)
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: https://rubygems.org/
|
|
11
|
+
specs:
|
|
12
|
+
actionmailer (4.0.2)
|
|
13
|
+
actionpack (= 4.0.2)
|
|
14
|
+
mail (~> 2.5.4)
|
|
15
|
+
actionpack (4.0.2)
|
|
16
|
+
activesupport (= 4.0.2)
|
|
17
|
+
builder (~> 3.1.0)
|
|
18
|
+
erubis (~> 2.7.0)
|
|
19
|
+
rack (~> 1.5.2)
|
|
20
|
+
rack-test (~> 0.6.2)
|
|
21
|
+
activemodel (4.0.2)
|
|
22
|
+
activesupport (= 4.0.2)
|
|
23
|
+
builder (~> 3.1.0)
|
|
24
|
+
activerecord (4.0.2)
|
|
25
|
+
activemodel (= 4.0.2)
|
|
26
|
+
activerecord-deprecated_finders (~> 1.0.2)
|
|
27
|
+
activesupport (= 4.0.2)
|
|
28
|
+
arel (~> 4.0.0)
|
|
29
|
+
activerecord-deprecated_finders (1.0.3)
|
|
30
|
+
activesupport (4.0.2)
|
|
31
|
+
i18n (~> 0.6, >= 0.6.4)
|
|
32
|
+
minitest (~> 4.2)
|
|
33
|
+
multi_json (~> 1.3)
|
|
34
|
+
thread_safe (~> 0.1)
|
|
35
|
+
tzinfo (~> 0.3.37)
|
|
36
|
+
arel (4.0.1)
|
|
37
|
+
atomic (1.1.14)
|
|
38
|
+
bcrypt-ruby (3.0.1)
|
|
39
|
+
builder (3.1.4)
|
|
40
|
+
capybara (2.2.1)
|
|
41
|
+
mime-types (>= 1.16)
|
|
42
|
+
nokogiri (>= 1.3.3)
|
|
43
|
+
rack (>= 1.0.0)
|
|
44
|
+
rack-test (>= 0.5.4)
|
|
45
|
+
xpath (~> 2.0)
|
|
46
|
+
coderay (1.1.0)
|
|
47
|
+
columnize (0.3.6)
|
|
48
|
+
database_cleaner (1.2.0)
|
|
49
|
+
debugger (1.6.5)
|
|
50
|
+
columnize (>= 0.3.1)
|
|
51
|
+
debugger-linecache (~> 1.2.0)
|
|
52
|
+
debugger-ruby_core_source (~> 1.3.1)
|
|
53
|
+
debugger-linecache (1.2.0)
|
|
54
|
+
debugger-ruby_core_source (1.3.1)
|
|
55
|
+
diff-lcs (1.2.5)
|
|
56
|
+
docile (1.1.1)
|
|
57
|
+
erubis (2.7.0)
|
|
58
|
+
factory_girl (4.2.0)
|
|
59
|
+
activesupport (>= 3.0.0)
|
|
60
|
+
factory_girl_rails (4.2.1)
|
|
61
|
+
factory_girl (~> 4.2.0)
|
|
62
|
+
railties (>= 3.0.0)
|
|
63
|
+
faraday (0.8.7)
|
|
64
|
+
multipart-post (~> 1.1)
|
|
65
|
+
ffaker (1.22.1)
|
|
66
|
+
font-awesome-rails (4.0.3.1)
|
|
67
|
+
railties (>= 3.2, < 5.0)
|
|
68
|
+
hike (1.2.3)
|
|
69
|
+
httpauth (0.2.0)
|
|
70
|
+
i18n (0.6.9)
|
|
71
|
+
jquery-rails (3.0.4)
|
|
72
|
+
railties (>= 3.0, < 5.0)
|
|
73
|
+
thor (>= 0.14, < 2.0)
|
|
74
|
+
jwt (0.1.8)
|
|
75
|
+
multi_json (>= 1.5)
|
|
76
|
+
libv8 (3.16.14.3)
|
|
77
|
+
mail (2.5.4)
|
|
78
|
+
mime-types (~> 1.16)
|
|
79
|
+
treetop (~> 1.4.8)
|
|
80
|
+
method_source (0.8.2)
|
|
81
|
+
mime-types (1.25.1)
|
|
82
|
+
mini_portile (0.5.2)
|
|
83
|
+
minitest (4.7.5)
|
|
84
|
+
multi_json (1.8.2)
|
|
85
|
+
multipart-post (1.2.0)
|
|
86
|
+
nokogiri (1.6.1)
|
|
87
|
+
mini_portile (~> 0.5.0)
|
|
88
|
+
oauth (0.4.7)
|
|
89
|
+
oauth2 (0.8.1)
|
|
90
|
+
faraday (~> 0.8)
|
|
91
|
+
httpauth (~> 0.1)
|
|
92
|
+
jwt (~> 0.1.4)
|
|
93
|
+
multi_json (~> 1.0)
|
|
94
|
+
rack (~> 1.2)
|
|
95
|
+
polyglot (0.3.3)
|
|
96
|
+
pry (0.9.12.4)
|
|
97
|
+
coderay (~> 1.0)
|
|
98
|
+
method_source (~> 0.8)
|
|
99
|
+
slop (~> 3.4)
|
|
100
|
+
pry-rails (0.3.2)
|
|
101
|
+
pry (>= 0.9.10)
|
|
102
|
+
rack (1.5.2)
|
|
103
|
+
rack-test (0.6.2)
|
|
104
|
+
rack (>= 1.0)
|
|
105
|
+
rails (4.0.2)
|
|
106
|
+
actionmailer (= 4.0.2)
|
|
107
|
+
actionpack (= 4.0.2)
|
|
108
|
+
activerecord (= 4.0.2)
|
|
109
|
+
activesupport (= 4.0.2)
|
|
110
|
+
bundler (>= 1.3.0, < 2.0)
|
|
111
|
+
railties (= 4.0.2)
|
|
112
|
+
sprockets-rails (~> 2.0.0)
|
|
113
|
+
railties (4.0.2)
|
|
114
|
+
actionpack (= 4.0.2)
|
|
115
|
+
activesupport (= 4.0.2)
|
|
116
|
+
rake (>= 0.8.7)
|
|
117
|
+
thor (>= 0.18.1, < 2.0)
|
|
118
|
+
rake (10.1.1)
|
|
119
|
+
ref (1.0.5)
|
|
120
|
+
remarkable (3.1.13)
|
|
121
|
+
rspec (>= 1.2.0)
|
|
122
|
+
remarkable_activerecord (3.1.13)
|
|
123
|
+
remarkable (~> 3.1.13)
|
|
124
|
+
rspec (>= 1.2.0)
|
|
125
|
+
rspec (2.14.1)
|
|
126
|
+
rspec-core (~> 2.14.0)
|
|
127
|
+
rspec-expectations (~> 2.14.0)
|
|
128
|
+
rspec-mocks (~> 2.14.0)
|
|
129
|
+
rspec-core (2.14.7)
|
|
130
|
+
rspec-expectations (2.14.4)
|
|
131
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
|
132
|
+
rspec-mocks (2.14.4)
|
|
133
|
+
rspec-rails (2.14.1)
|
|
134
|
+
actionpack (>= 3.0)
|
|
135
|
+
activemodel (>= 3.0)
|
|
136
|
+
activesupport (>= 3.0)
|
|
137
|
+
railties (>= 3.0)
|
|
138
|
+
rspec-core (~> 2.14.0)
|
|
139
|
+
rspec-expectations (~> 2.14.0)
|
|
140
|
+
rspec-mocks (~> 2.14.0)
|
|
141
|
+
shoulda-matchers (2.4.0)
|
|
142
|
+
activesupport (>= 3.0.0)
|
|
143
|
+
simplecov (0.8.2)
|
|
144
|
+
docile (~> 1.1.0)
|
|
145
|
+
multi_json
|
|
146
|
+
simplecov-html (~> 0.8.0)
|
|
147
|
+
simplecov-html (0.8.0)
|
|
148
|
+
slop (3.4.7)
|
|
149
|
+
sorcery (0.8.2)
|
|
150
|
+
bcrypt-ruby (~> 3.0.0)
|
|
151
|
+
oauth (~> 0.4.4)
|
|
152
|
+
oauth2 (~> 0.8.0)
|
|
153
|
+
sprockets (2.10.1)
|
|
154
|
+
hike (~> 1.2)
|
|
155
|
+
multi_json (~> 1.0)
|
|
156
|
+
rack (~> 1.0)
|
|
157
|
+
tilt (~> 1.1, != 1.3.0)
|
|
158
|
+
sprockets-rails (2.0.1)
|
|
159
|
+
actionpack (>= 3.0)
|
|
160
|
+
activesupport (>= 3.0)
|
|
161
|
+
sprockets (~> 2.8)
|
|
162
|
+
sqlite3 (1.3.8)
|
|
163
|
+
therubyracer (0.12.0)
|
|
164
|
+
libv8 (~> 3.16.14.0)
|
|
165
|
+
ref
|
|
166
|
+
thor (0.18.1)
|
|
167
|
+
thread_safe (0.1.3)
|
|
168
|
+
atomic
|
|
169
|
+
tilt (1.4.1)
|
|
170
|
+
treetop (1.4.15)
|
|
171
|
+
polyglot
|
|
172
|
+
polyglot (>= 0.3.1)
|
|
173
|
+
tzinfo (0.3.38)
|
|
174
|
+
xpath (2.0.0)
|
|
175
|
+
nokogiri (~> 1.3)
|
|
176
|
+
|
|
177
|
+
PLATFORMS
|
|
178
|
+
ruby
|
|
179
|
+
|
|
180
|
+
DEPENDENCIES
|
|
181
|
+
capybara
|
|
182
|
+
database_cleaner
|
|
183
|
+
debugger
|
|
184
|
+
factory_girl_rails (~> 4.2.1)
|
|
185
|
+
ffaker
|
|
186
|
+
neutral!
|
|
187
|
+
pry-rails
|
|
188
|
+
remarkable_activerecord
|
|
189
|
+
rspec-rails
|
|
190
|
+
shoulda-matchers
|
|
191
|
+
simplecov
|
|
192
|
+
sorcery
|
|
193
|
+
sqlite3
|
|
194
|
+
therubyracer
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2014 YOURNAME
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Neutral
|
|
2
|
+
|
|
3
|
+
Neutral is a rails engine providing ajaxful positive/negative voting solution for your ActiveRecord objects along with couple of additional features.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add following into your Gemfile
|
|
10
|
+
|
|
11
|
+
gem 'neutral'
|
|
12
|
+
|
|
13
|
+
Run
|
|
14
|
+
|
|
15
|
+
$ bundle
|
|
16
|
+
|
|
17
|
+
Or install it yourself as
|
|
18
|
+
|
|
19
|
+
$ gem install neutral
|
|
20
|
+
|
|
21
|
+
### Generation
|
|
22
|
+
|
|
23
|
+
Generate required files using
|
|
24
|
+
|
|
25
|
+
$ rails g neutral:install
|
|
26
|
+
|
|
27
|
+
And proceed to migrate newly created migration files
|
|
28
|
+
|
|
29
|
+
$ rake db:migrate
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
Make your ActiveRecord model voteable
|
|
34
|
+
|
|
35
|
+
class Post < ActiveRecord::Base
|
|
36
|
+
neutral
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
And select your voter model
|
|
40
|
+
|
|
41
|
+
class User < ActiveRecord::Base
|
|
42
|
+
neutral_voter
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
*Note: If your voter model is not User configure this setting inside neutral.rb [intializer](https://github.com/petertoth/neutral#configuring-neutral)*
|
|
46
|
+
|
|
47
|
+
To display voting use `voting_for` helper in your view :
|
|
48
|
+
|
|
49
|
+
<%= voting_for post %>
|
|
50
|
+
|
|
51
|
+
## Customization
|
|
52
|
+
|
|
53
|
+
### View
|
|
54
|
+
|
|
55
|
+
You can also pass two additional options to `voting_for` helper
|
|
56
|
+
|
|
57
|
+
* **[icons](https://github.com/petertoth/neutral#font-awesome)** : Icons used for positive/negative/remove
|
|
58
|
+
* **difference** : Display difference count instead of positive/negative counts
|
|
59
|
+
<br>*If the difference is positive i.e positive votes - negative votes > 0 then the color of the span is green, red otherwise*
|
|
60
|
+
|
|
61
|
+
Example :
|
|
62
|
+
|
|
63
|
+
<%= voting_for article, icons: :myfabulousicons, difference: true %>
|
|
64
|
+
|
|
65
|
+
### Configuring Neutral
|
|
66
|
+
|
|
67
|
+
In *config/initializers/neutral.rb* you can configure these options :
|
|
68
|
+
|
|
69
|
+
* **can_change** : Determine wheter a voter can change(update,delete) his vote
|
|
70
|
+
* **current_voter_method** : This is most typically `current_user` but if not, change this to your own representation of a voter instance e.g `current_client` or `current_customer`. Also make sure it accessible from your ApplicationController.
|
|
71
|
+
* **require_login** : Voter is/is not required to be authenticated in order to vote. Setting to false is not recommended
|
|
72
|
+
* **vote_owner_class** : Configure an owner of a vote. Pass string of class name of the model you added `neutral_voter` into. For example `'User'`, `'Client'` or `'Customer'`
|
|
73
|
+
* **default_icon_set** : This icon set is used when no explicit icon set is passed to `voting_for` helper
|
|
74
|
+
|
|
75
|
+
### Font Awesome
|
|
76
|
+
|
|
77
|
+
This engine enables you to define your own icon sets using FontAwesome icons that provide representation of voting related actions such as like, dislike, remove, plus, minus, whatever ...
|
|
78
|
+
|
|
79
|
+
You can use any [FontAwesome icon class](http://fontawesome.io/icons/) available
|
|
80
|
+
|
|
81
|
+
Define an icon set in your *neutral.rb* initializer
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
#config/initializers/neutral.rb
|
|
85
|
+
|
|
86
|
+
Neutral.define do
|
|
87
|
+
set :myicons do
|
|
88
|
+
positive "fa-thumbs-up"
|
|
89
|
+
negative "fa-thumbs-down"
|
|
90
|
+
remove "fa-times"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
set :fabulous do
|
|
94
|
+
positive "fa-plus"
|
|
95
|
+
# If any of action is omitted, definition from your default icon set is used.
|
|
96
|
+
# In this case "fa-thumbs-down-o" would be used for negative and "fa-times"
|
|
97
|
+
# for remove action because because :thumbs(default set) contains these definitions.
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Finally use it as follows :
|
|
103
|
+
|
|
104
|
+
<%= voting_for voteable, icons: :myicons %>
|
|
105
|
+
|
|
106
|
+
If you ever need to access a definition of a given icon set proceed analogically as follows : `Neutral.icons.thumbs.positive`
|
|
107
|
+
|
|
108
|
+
## i18n
|
|
109
|
+
|
|
110
|
+
Define your custom error messages for each of your locale in *config/locales/neutral.yml*
|
|
111
|
+
|
|
112
|
+
en:
|
|
113
|
+
errors:
|
|
114
|
+
duplication: "You have already selected this option!"
|
|
115
|
+
cannot_change: "You are not permitted to change the vote!"
|
|
116
|
+
require_login : "You must be logged in to vote!"
|
|
117
|
+
|
|
118
|
+
## Uninstallation
|
|
119
|
+
|
|
120
|
+
Run :
|
|
121
|
+
|
|
122
|
+
$ rails g neutral:uninstall
|
|
123
|
+
|
|
124
|
+
It :
|
|
125
|
+
|
|
126
|
+
* comments `neutral` in your *routes.rb*
|
|
127
|
+
|
|
128
|
+
* removes `require neutral` from your stylesheet manifest
|
|
129
|
+
|
|
130
|
+
* removes *neutral.rb* initializer
|
|
131
|
+
* removes *neutral.yml* locale file
|
|
132
|
+
* removes database entities(engine's tables) and migration files - **optional**
|
|
133
|
+
|
|
134
|
+
## Contributing
|
|
135
|
+
|
|
136
|
+
1. Fork it
|
|
137
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
138
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
139
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
140
|
+
5. Create new Pull Request
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
MIT License. Copyright (c) 2014
|
data/Rakefile
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Neutral'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
|
18
|
+
load 'rails/tasks/engine.rake'
|
|
19
|
+
|
|
20
|
+
Bundler::GemHelper.install_tasks
|
|
21
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*= require font-awesome
|
|
3
|
+
*= require_self
|
|
4
|
+
*= require_tree .
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
div.neutral a {
|
|
8
|
+
display: inline;
|
|
9
|
+
margin: 0 4px;
|
|
10
|
+
color: inherit;
|
|
11
|
+
outline: none;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
div.neutral a:hover {
|
|
15
|
+
border: none;
|
|
16
|
+
opacity: .8;
|
|
17
|
+
text-decoration: none;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
div.neutral a.remove {
|
|
21
|
+
opacity: .4;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
div.neutral i {
|
|
25
|
+
font-size: 1.2em;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
div.neutral span {
|
|
29
|
+
display: inline;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
div.neutral span#positive, div.neutral span.positive {
|
|
33
|
+
color: green;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
div.neutral span#negative, div.neutral span.negative {
|
|
37
|
+
color: red;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
div.neutral span.error {
|
|
41
|
+
margin-left: 5px;
|
|
42
|
+
color: red;
|
|
43
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Neutral
|
|
2
|
+
class ApplicationController < ::ApplicationController
|
|
3
|
+
protect_from_forgery
|
|
4
|
+
|
|
5
|
+
rescue_from Errors::RequireLogin, with: :require_login
|
|
6
|
+
rescue_from Errors::CannotChange, with: :cannot_change
|
|
7
|
+
rescue_from Errors::DuplicateVote, with: :duplicate
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
def require_login
|
|
11
|
+
render 'neutral/votes/errors/require_login'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cannot_change
|
|
15
|
+
render 'neutral/votes/errors/cannot_change'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def duplicate
|
|
19
|
+
render 'neutral/votes/errors/duplicate'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require_dependency 'application_controller'
|
|
2
|
+
|
|
3
|
+
module Neutral
|
|
4
|
+
class VotesController < ApplicationController
|
|
5
|
+
layout false
|
|
6
|
+
|
|
7
|
+
before_filter :require_login?, only: :create
|
|
8
|
+
before_filter :can_change?, except: :create
|
|
9
|
+
|
|
10
|
+
def create
|
|
11
|
+
@vote = Vote.create(vote_params)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def update
|
|
15
|
+
vote.update_attributes(value: params[:value])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def destroy
|
|
19
|
+
vote.destroy
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
helper_method :vote, :voting
|
|
23
|
+
def vote
|
|
24
|
+
@vote ||= Vote.find_by(id: params[:id]) || Vote.new(vote_params)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def voting
|
|
28
|
+
@voting ||= vote.voting || Voting.new
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
def require_login?
|
|
33
|
+
raise Errors::RequireLogin if Neutral.config.require_login && !current_voter
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def can_change?
|
|
37
|
+
raise Errors::CannotChange unless Neutral.config.can_change && authorized?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def vote_params
|
|
41
|
+
params.require(:vote).permit(:voteable_type, :voteable_id, :value).merge voter_id: current_voter.try(:id)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def authorized?
|
|
45
|
+
current_voter == vote.voter
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Neutral
|
|
2
|
+
module VotesHelper
|
|
3
|
+
def by_url
|
|
4
|
+
return raw "a[href*='#{request.post? ? votes_path : vote_path}']"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def vote_path(value=[1,0].sample)
|
|
8
|
+
raw neutral.vote_path(vote, value: value)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def votes_path(value=[1,0].sample)
|
|
12
|
+
raw neutral.votes_path(vote: vote.main_attributes.update(value: value))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Neutral
|
|
2
|
+
class Vote < ActiveRecord::Base
|
|
3
|
+
before_update :avoid_duplication
|
|
4
|
+
|
|
5
|
+
validates_inclusion_of :value, in: [0,1]
|
|
6
|
+
validates_presence_of :voteable_type, :voteable_id, :value
|
|
7
|
+
|
|
8
|
+
belongs_to :voteable, polymorphic: true
|
|
9
|
+
belongs_to :voter, class_name: Neutral.config.vote_owner_class.classify
|
|
10
|
+
|
|
11
|
+
include Neutral::Model::VoteCached
|
|
12
|
+
|
|
13
|
+
def nature
|
|
14
|
+
value == 1 ? :positive : :negative
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def main_attributes
|
|
18
|
+
attributes.symbolize_keys.except(:id, :voter_id, :created_at, :updated_at)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
def avoid_duplication
|
|
23
|
+
raise Errors::DuplicateVote unless self.changed?
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Neutral
|
|
2
|
+
class Voting < ActiveRecord::Base
|
|
3
|
+
before_destroy :delete_votes
|
|
4
|
+
|
|
5
|
+
belongs_to :votingable, polymorphic: true
|
|
6
|
+
|
|
7
|
+
delegate :votes, to: :votingable
|
|
8
|
+
|
|
9
|
+
def difference
|
|
10
|
+
positive - negative
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.init(vote)
|
|
14
|
+
create(votingable_type: vote.voteable_type, votingable_id: vote.voteable_id) do |voting|
|
|
15
|
+
voting.increment(vote.nature)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def add_to_existing(nature)
|
|
20
|
+
increment!(nature)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def edit(nature)
|
|
24
|
+
increment(nature)
|
|
25
|
+
decrement(nature==:positive ? :negative : :positive)
|
|
26
|
+
save
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def remove(nature)
|
|
30
|
+
decrement!(nature)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def delete_votes
|
|
36
|
+
votes.delete_all
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
$(document).ready(function() {
|
|
2
|
+
|
|
3
|
+
neutral = $("div.neutral").find("<%= by_url %>").parent();
|
|
4
|
+
|
|
5
|
+
neutral.find("span#positive").html("<%= voting.positive.nonzero? %>");
|
|
6
|
+
neutral.find("span#negative").html("<%= voting.negative.nonzero? %>");
|
|
7
|
+
neutral.find("span#difference").html("<%= voting.difference.nonzero?.try(:abs) %>");
|
|
8
|
+
|
|
9
|
+
neutral.find("span#difference").attr("class", "<%= voting.difference > 0 ? 'positive' : 'negative' %>");
|
|
10
|
+
|
|
11
|
+
<% if vote.voter_id && Neutral.config.can_change %>
|
|
12
|
+
|
|
13
|
+
neutral.find("a[class!='remove']").data('method', 'patch');
|
|
14
|
+
neutral.find("a[class!='remove']").attr('data-method', 'patch');
|
|
15
|
+
neutral.find("a.positive").attr('href', '<%= vote_path(1) %>');
|
|
16
|
+
neutral.find("a.negative").attr('href', '<%= vote_path(0) %>');
|
|
17
|
+
|
|
18
|
+
neutral.append('<%= escape_javascript(
|
|
19
|
+
Neutral::VotingBuilder::Elements::Link::Remove.new(
|
|
20
|
+
Neutral::VotingBuilder::Router.new(vote)[:remove],
|
|
21
|
+
Neutral.icons.send(Neutral.config.default_icon_set).send(:remove)).to_s
|
|
22
|
+
)
|
|
23
|
+
%>');
|
|
24
|
+
|
|
25
|
+
<% end %>
|
|
26
|
+
|
|
27
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
$(document).ready(function() {
|
|
2
|
+
|
|
3
|
+
neutral = $("div.neutral").find("<%= by_url %>").parent();
|
|
4
|
+
|
|
5
|
+
neutral.find("a[class!='remove']").data('method', 'post');
|
|
6
|
+
neutral.find("a[class!='remove']").attr('data-method', 'post');
|
|
7
|
+
neutral.find("a.positive").attr('href', '<%= votes_path(1) %>');
|
|
8
|
+
neutral.find("a.negative").attr('href', '<%= votes_path(0) %>');
|
|
9
|
+
|
|
10
|
+
neutral.find("span#positive").html("<%= voting.positive.nonzero? %>");
|
|
11
|
+
neutral.find("span#negative").html("<%= voting.negative.nonzero? %>");
|
|
12
|
+
neutral.find("span#difference").html("<%= voting.difference.nonzero?.try(:abs) %>");
|
|
13
|
+
|
|
14
|
+
neutral.find("span#difference").attr("class", "<%= voting.difference > 0 ? 'positive' : 'negative' %>");
|
|
15
|
+
|
|
16
|
+
neutral.find("a.remove").remove();
|
|
17
|
+
|
|
18
|
+
});
|