voluntary_ranking 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +29 -0
- data/app/assets/javascripts/voluntary_ranking/app.js +11 -0
- data/app/assets/javascripts/voluntary_ranking/application.js +4 -0
- data/app/assets/javascripts/voluntary_ranking/base.js.coffee +3 -0
- data/app/assets/javascripts/voluntary_ranking/components/modal_dialog_component.js.coffee +6 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/arguments/index_controller.js.coffee +5 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/arguments/new_controller.js.coffee +16 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/compare_things/arguments_controller.js.coffee +5 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/compare_things_controller.js.coffee +8 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/controller.js.coffee +1 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/index_controller.js.coffee +5 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/profile/rankings_controller.js.coffee +3 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/ranking_item_controller.js.coffee +7 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/rankings/index_controller.js.coffee +5 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/rankings/show_controller.js.coffee +6 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/thing_controller.js.coffee +10 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/user/rankings/show_controller.js.coffee +92 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/user_controller.js.coffee +5 -0
- data/app/assets/javascripts/voluntary_ranking/controllers/user_ranking_controller.js.coffee +2 -0
- data/app/assets/javascripts/voluntary_ranking/helpers/name_with_apostrophe_helper.js.coffee +5 -0
- data/app/assets/javascripts/voluntary_ranking/helpers/stars_html_helper.js.coffee +29 -0
- data/app/assets/javascripts/voluntary_ranking/mixins/has_current_user.js.coffee +4 -0
- data/app/assets/javascripts/voluntary_ranking/mixins/pagination_controller.js.coffee +51 -0
- data/app/assets/javascripts/voluntary_ranking/mixins/ranking_controller.js.coffee +31 -0
- data/app/assets/javascripts/voluntary_ranking/mixins/singleton.js.coffee +17 -0
- data/app/assets/javascripts/voluntary_ranking/models/argument.js.coffee +7 -0
- data/app/assets/javascripts/voluntary_ranking/models/movie.js.coffee +5 -0
- data/app/assets/javascripts/voluntary_ranking/models/ranking.js.coffee +5 -0
- data/app/assets/javascripts/voluntary_ranking/models/ranking_item.js.coffee +26 -0
- data/app/assets/javascripts/voluntary_ranking/models/thing.js.coffee +2 -0
- data/app/assets/javascripts/voluntary_ranking/models/user.js.coffee +18 -0
- data/app/assets/javascripts/voluntary_ranking/models/user/ranking_item.js.coffee +33 -0
- data/app/assets/javascripts/voluntary_ranking/router.js.coffee +30 -0
- data/app/assets/javascripts/voluntary_ranking/routes/arguments/index_route.js.coffee +24 -0
- data/app/assets/javascripts/voluntary_ranking/routes/compare_things/arguments_route.js.coffee +16 -0
- data/app/assets/javascripts/voluntary_ranking/routes/compare_things/compare_things_route.js.coffee +9 -0
- data/app/assets/javascripts/voluntary_ranking/routes/profile/rankings_route.js.coffee +29 -0
- data/app/assets/javascripts/voluntary_ranking/routes/ranking_item_route.js.coffee +25 -0
- data/app/assets/javascripts/voluntary_ranking/routes/rankings/index_route.js.coffee +10 -0
- data/app/assets/javascripts/voluntary_ranking/routes/rankings/show_route.js.coffee +19 -0
- data/app/assets/javascripts/voluntary_ranking/routes/thing_route.js.coffee +7 -0
- data/app/assets/javascripts/voluntary_ranking/routes/user_ranking_route.js.coffee +27 -0
- data/app/assets/javascripts/voluntary_ranking/routes/user_route.js.coffee +20 -0
- data/app/assets/javascripts/voluntary_ranking/templates/application.handlebars.erb +16 -0
- data/app/assets/javascripts/voluntary_ranking/templates/arguments.js.handlebars +1 -0
- data/app/assets/javascripts/voluntary_ranking/templates/arguments/index.js.handlebars +27 -0
- data/app/assets/javascripts/voluntary_ranking/templates/arguments/new.js.handlebars +17 -0
- data/app/assets/javascripts/voluntary_ranking/templates/compare_things.js.handlebars +22 -0
- data/app/assets/javascripts/voluntary_ranking/templates/compare_things/arguments.js.handlebars +26 -0
- data/app/assets/javascripts/voluntary_ranking/templates/components/modal-dialog.js.handlebars +9 -0
- data/app/assets/javascripts/voluntary_ranking/templates/components/rankings-component.handlebars +17 -0
- data/app/assets/javascripts/voluntary_ranking/templates/index.js.handlebars +1 -0
- data/app/assets/javascripts/voluntary_ranking/templates/navigation.js.handlebars +28 -0
- data/app/assets/javascripts/voluntary_ranking/templates/ranking_item.js.handlebars +31 -0
- data/app/assets/javascripts/voluntary_ranking/templates/ranking_items/_collection.js.handlebars +84 -0
- data/app/assets/javascripts/voluntary_ranking/templates/ranking_items/_form.js.handlebars +30 -0
- data/app/assets/javascripts/voluntary_ranking/templates/rankings/_form.js.handlebars +38 -0
- data/app/assets/javascripts/voluntary_ranking/templates/rankings/index.js.handlebars +3 -0
- data/app/assets/javascripts/voluntary_ranking/templates/rankings/show.js.handlebars +3 -0
- data/app/assets/javascripts/voluntary_ranking/templates/shared/_pagination.js.handlebars +23 -0
- data/app/assets/javascripts/voluntary_ranking/templates/shared/_stars.js.handlebars +3 -0
- data/app/assets/javascripts/voluntary_ranking/templates/thing.js.handlebars +13 -0
- data/app/assets/javascripts/voluntary_ranking/templates/thing/index.js.handlebars +0 -0
- data/app/assets/javascripts/voluntary_ranking/templates/things/show.arguments.js.handlebars +1 -0
- data/app/assets/javascripts/voluntary_ranking/templates/things/show.js.handlebars +1 -0
- data/app/assets/javascripts/voluntary_ranking/templates/user.js.handlebars +5 -0
- data/app/assets/javascripts/voluntary_ranking/templates/user/rankings/details.js.handlebars +7 -0
- data/app/assets/javascripts/voluntary_ranking/views/application/index_view.js.coffee +1 -0
- data/app/assets/javascripts/voluntary_ranking/views/arguments/new_view.js.coffee +9 -0
- data/app/assets/javascripts/voluntary_ranking/views/index_view.js.coffee +1 -0
- data/app/assets/javascripts/voluntary_ranking/views/ranking_items/colllection_view.js.coffee +25 -0
- data/app/assets/javascripts/voluntary_ranking/views/shared/pagination.js +4 -0
- data/app/assets/stylesheets/voluntary_ranking/application.css +17 -0
- data/app/assets/stylesheets/voluntary_ranking/base.css.sass +6 -0
- data/app/assets/stylesheets/voluntary_ranking/bootstrap_and_overrides.css.sass +0 -0
- data/app/assets/stylesheets/voluntary_ranking/stars.css.sass +31 -0
- data/app/assets/stylesheets/voluntary_ranking/twitter-typeahead.css.sass +29 -0
- data/app/controllers/api/v1/argument_topics_controller.rb +12 -0
- data/app/controllers/api/v1/arguments_controller.rb +32 -0
- data/app/controllers/api/v1/ranking_items_controller.rb +43 -0
- data/app/controllers/api/v1/rankings_controller.rb +29 -0
- data/app/controllers/api/v1/things/arguments_controller.rb +40 -0
- data/app/controllers/api/v1/things_controller.rb +26 -0
- data/app/controllers/api/v1/user_ranking_items_controller.rb +94 -0
- data/app/controllers/api/v1/users_controller.rb +9 -0
- data/app/controllers/product/ranking_controller.rb +16 -0
- data/app/models/argument.rb +48 -0
- data/app/models/argument_topic.rb +7 -0
- data/app/models/product/ranking.rb +2 -0
- data/app/models/ranking.rb +97 -0
- data/app/models/ranking_item.rb +30 -0
- data/app/models/user_ranking_item.rb +136 -0
- data/app/serializers/argument_serializer.rb +11 -0
- data/app/serializers/base_ranking_item_serializer.rb +23 -0
- data/app/serializers/ranking_item_serializer.rb +2 -0
- data/app/serializers/user_ranking_item_serializer.rb +7 -0
- data/app/views/product/ranking/index.html.erb +0 -0
- data/config/locales/en.yml +10 -0
- data/config/locales/resources/ranking/en.yml +10 -0
- data/config/routes.rb +41 -0
- data/db/migrate/20130817115303_add_ranking_product.rb +50 -0
- data/db/migrate/20140926102943_create_arguments.rb +20 -0
- data/lib/concerns/controller/base_ranking_items_controller.rb +10 -0
- data/lib/concerns/model/base_ranking_item.rb +29 -0
- data/lib/concerns/model/user/ranking.rb +48 -0
- data/lib/tasks/voluntary_ranking_tasks.rake +4 -0
- data/lib/voluntary_ranking.rb +12 -0
- data/lib/voluntary_ranking/ability.rb +11 -0
- data/lib/voluntary_ranking/engine.rb +16 -0
- data/lib/voluntary_ranking/version.rb +3 -0
- metadata +436 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
.tt-dropdown-menu, .gist
|
2
|
+
text-align: left
|
3
|
+
|
4
|
+
.tt-query
|
5
|
+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset
|
6
|
+
|
7
|
+
.tt-hint
|
8
|
+
color: #999
|
9
|
+
|
10
|
+
.tt-dropdown-menu
|
11
|
+
background-color: #fff
|
12
|
+
border: 1px solid rgba(0, 0, 0, 0.2)
|
13
|
+
border-radius: 8px
|
14
|
+
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2)
|
15
|
+
margin-top: 12px
|
16
|
+
padding: 8px 0
|
17
|
+
width: 422px
|
18
|
+
|
19
|
+
.tt-suggestion
|
20
|
+
font-size: 18px
|
21
|
+
line-height: 24px
|
22
|
+
padding: 3px 20px
|
23
|
+
|
24
|
+
.tt-suggestion.tt-cursor
|
25
|
+
background-color: #0097cf
|
26
|
+
color: #fff
|
27
|
+
|
28
|
+
.tt-suggestion p
|
29
|
+
margin: 0
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Api::V1::ArgumentTopicsController < ActionController::Base
|
2
|
+
include Voluntary::V1::BaseController
|
3
|
+
|
4
|
+
respond_to :json
|
5
|
+
|
6
|
+
def autocomplete
|
7
|
+
render json: (
|
8
|
+
ArgumentTopic.order(:name).where("name LIKE ?", "%#{params[:term]}%").
|
9
|
+
map{|t| { id: t.id, value: t.name }}
|
10
|
+
), root: false
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Api::V1::ArgumentsController < ActionController::Base
|
2
|
+
include Voluntary::V1::BaseController
|
3
|
+
|
4
|
+
respond_to :json
|
5
|
+
|
6
|
+
def index
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
arguments = Argument
|
10
|
+
arguments = Argument.where(thing_id: params[:thing_id]) if params[:thing_id].present?
|
11
|
+
options[:json] = arguments.paginate(page: params[:page], per_page: 10)
|
12
|
+
|
13
|
+
options[:meta] = {
|
14
|
+
pagination: {
|
15
|
+
total_pages: options[:json].total_pages, current_page: options[:json].current_page,
|
16
|
+
previous_page: options[:json].previous_page, next_page: options[:json].next_page
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
respond_with do |format|
|
21
|
+
format.json { render options }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def create
|
26
|
+
raise CanCan::AccessDenied if current_user.blank?
|
27
|
+
|
28
|
+
respond_to do |format|
|
29
|
+
format.json { render json: Argument.create_with_topic(params[:argument]) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Api::V1::RankingItemsController < ActionController::Base
|
2
|
+
include Voluntary::V1::BaseController
|
3
|
+
include Concerns::Controller::BaseRankingItemsController
|
4
|
+
|
5
|
+
respond_to :json
|
6
|
+
|
7
|
+
def index
|
8
|
+
options = {}
|
9
|
+
|
10
|
+
if ranking.present?
|
11
|
+
options[:json] = ranking.items.order('position').includes(:thing).paginate(page: params[:page], per_page: 10)
|
12
|
+
|
13
|
+
options[:meta] = {
|
14
|
+
pagination: {
|
15
|
+
total_pages: options[:json].total_pages, current_page: options[:json].current_page,
|
16
|
+
previous_page: options[:json].previous_page, next_page: options[:json].next_page
|
17
|
+
}
|
18
|
+
}
|
19
|
+
else
|
20
|
+
options[:json] = []
|
21
|
+
options[:meta] = { pagination: { total_pages: 0, current_page: 0, previous_page: 0, next_page: 0 } }
|
22
|
+
end
|
23
|
+
|
24
|
+
respond_with do |format|
|
25
|
+
format.json { render options }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def show
|
30
|
+
ranking = Ranking.where(
|
31
|
+
'(LOWER(adjective) = :adjective OR LOWER(negative_adjective) = :adjective) AND LOWER(topic) = :topic AND LOWER(scope) = :scope',
|
32
|
+
adjective: params[:adjective].downcase, topic: params[:topic].downcase, scope: params[:scope].downcase
|
33
|
+
).first
|
34
|
+
thing = Thing.where('LOWER(name) = ?', params[:thing_name].downcase).first
|
35
|
+
ranking_item = RankingItem.where(ranking_id: ranking.try(:id), thing_id: thing.try(:id)).first
|
36
|
+
|
37
|
+
raise ActiveRecord::RecordNotFound if ranking_item.blank?
|
38
|
+
|
39
|
+
respond_with do |format|
|
40
|
+
format.json { render json: ranking_item }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Api::V1::RankingsController < ActionController::Base
|
2
|
+
include Voluntary::V1::BaseController
|
3
|
+
|
4
|
+
respond_to :json
|
5
|
+
|
6
|
+
def index
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
rankings = Ranking
|
10
|
+
rankings = Ranking.for_user(params[:user_name]) if params[:user_name].present?
|
11
|
+
rankings = Ranking.for_thing(params[:thing_id]) if params[:thing_id].present?
|
12
|
+
options[:json] = rankings.paginate page: params[:page], per_page: 1, count: { group: 'rankings.id' }
|
13
|
+
|
14
|
+
options[:meta] = {
|
15
|
+
pagination: {
|
16
|
+
total_pages: options[:json].total_pages, current_page: options[:json].current_page,
|
17
|
+
previous_page: options[:json].previous_page, next_page: options[:json].next_page
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
respond_with do |format|
|
22
|
+
format.json { render options }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def autocomplete_attribute
|
27
|
+
render json: Ranking.autocomplete_attribute(params[:attribute], params[:term]), root: false
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Api::V1::Things::ArgumentsController < ActionController::Base
|
2
|
+
include Voluntary::V1::BaseController
|
3
|
+
|
4
|
+
respond_to :json
|
5
|
+
|
6
|
+
def comparison
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
arguments = Argument.compare_two_things(params[:side], params[:left_thing_name], params[:right_thing_name]).
|
10
|
+
paginate(page: params[:page], per_page: 10)
|
11
|
+
|
12
|
+
options[:json] = arguments.map do |argument_comparison|
|
13
|
+
hash = {
|
14
|
+
left: { id: argument_comparison.id, value: argument_comparison.value },
|
15
|
+
right: { id: argument_comparison.right_id, value: argument_comparison.right_value },
|
16
|
+
topic: { id: argument_comparison.topic_id, name: argument_comparison.topic_name }
|
17
|
+
}
|
18
|
+
|
19
|
+
if params[:side] == 'right'
|
20
|
+
left = hash[:left].clone
|
21
|
+
right = hash[:right].clone
|
22
|
+
hash[:left] = right
|
23
|
+
hash[:right] = left
|
24
|
+
end
|
25
|
+
|
26
|
+
hash
|
27
|
+
end
|
28
|
+
|
29
|
+
options[:meta] = {
|
30
|
+
pagination: {
|
31
|
+
total_pages: arguments.total_pages, current_page: arguments.current_page,
|
32
|
+
previous_page: arguments.previous_page, next_page: arguments.next_page
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
respond_with do |format|
|
37
|
+
format.json { render options }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Api::V1::ThingsController < ActionController::Base
|
2
|
+
include Voluntary::V1::BaseController
|
3
|
+
|
4
|
+
respond_to :json
|
5
|
+
|
6
|
+
def show
|
7
|
+
@thing = Thing.where('LOWER(name) = ?', params[:id].downcase).first
|
8
|
+
|
9
|
+
raise ActiveRecord::RecordNotFound if @thing.blank?
|
10
|
+
|
11
|
+
respond_with do |format|
|
12
|
+
format.json { render json: @thing, root: true }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def autocomplete
|
17
|
+
render json: (
|
18
|
+
Thing.order(:name).where("name LIKE ?", "%#{params[:term]}%").
|
19
|
+
map{|t| { id: t.id, value: t.name }}
|
20
|
+
), root: false
|
21
|
+
end
|
22
|
+
|
23
|
+
def suggest
|
24
|
+
render json: Thing.suggest(params[:term]), root: false
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
class Api::V1::UserRankingItemsController < ActionController::Base
|
2
|
+
include Voluntary::V1::BaseController
|
3
|
+
include Concerns::Controller::BaseRankingItemsController
|
4
|
+
|
5
|
+
respond_to :json
|
6
|
+
|
7
|
+
def index
|
8
|
+
options = {}
|
9
|
+
|
10
|
+
if ranking.present?
|
11
|
+
options[:json] = if params[:user_id].present? || params[:user_name].present?
|
12
|
+
user.ranking_items
|
13
|
+
else
|
14
|
+
UserRankingItem
|
15
|
+
end
|
16
|
+
|
17
|
+
if params[:thing_name].present?
|
18
|
+
options[:json] = options[:json].where(
|
19
|
+
thing_id: Thing.where('LOWER(name) = ?', params[:thing_name].downcase).first.id
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
options[:json] = options[:json].order('position').where(ranking_id: ranking.id).includes(:thing)
|
24
|
+
options[:json] = options[:json].paginate(page: params[:page], per_page: 10)
|
25
|
+
|
26
|
+
options[:meta] = {
|
27
|
+
pagination: {
|
28
|
+
total_pages: options[:json].total_pages, current_page: options[:json].current_page,
|
29
|
+
previous_page: options[:json].previous_page, next_page: options[:json].next_page
|
30
|
+
}
|
31
|
+
}
|
32
|
+
else
|
33
|
+
options[:json] = []
|
34
|
+
options[:meta] = { pagination: { total_pages: 0, current_page: 0, previous_page: 0, next_page: 0 } }
|
35
|
+
end
|
36
|
+
|
37
|
+
respond_with do |format|
|
38
|
+
format.json { render options }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def create
|
43
|
+
raise CanCan::AccessDenied if current_user.blank?
|
44
|
+
|
45
|
+
respond_to do |format|
|
46
|
+
format.json { render json: current_user.add_ranking_item(params[:user_ranking_item]) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def update
|
51
|
+
user_ranking_item = current_user.ranking_items.find(params[:id])
|
52
|
+
user_ranking_item.update_stars params[:user_ranking_item][:stars]
|
53
|
+
respond_with user_ranking_item
|
54
|
+
end
|
55
|
+
|
56
|
+
def move
|
57
|
+
user_ranking_item = UserRankingItem.find(params[:id])
|
58
|
+
|
59
|
+
raise CanCan::AccessDenied unless can? :update, user_ranking_item
|
60
|
+
|
61
|
+
user_ranking_item.set_position(params[:position].to_i)
|
62
|
+
respond_with user_ranking_item
|
63
|
+
end
|
64
|
+
|
65
|
+
def move_to_page
|
66
|
+
user_ranking_item = UserRankingItem.find(params[:id])
|
67
|
+
|
68
|
+
raise CanCan::AccessDenied unless can? :update, user_ranking_item
|
69
|
+
|
70
|
+
user_ranking_item.move_to_top_of_page(params[:page])
|
71
|
+
|
72
|
+
respond_to do |format|
|
73
|
+
format.json { render json: user_ranking_item }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def destroy
|
78
|
+
current_user.ranking_items.find(params[:id]).destroy!
|
79
|
+
|
80
|
+
render nothing: true
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def user
|
86
|
+
if @user
|
87
|
+
@user
|
88
|
+
elsif params[:user_id].present?
|
89
|
+
@user = User.find(params[:user_id])
|
90
|
+
elsif params[:user_name].present?
|
91
|
+
@user = User.where('LOWER(name) = ?', params[:user_name].downcase).first
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Product::RankingController < Voluntary::EmberJs::ApplicationController
|
2
|
+
layout Proc.new { |controller| controller.request.xhr? || request.format.try('json?') ? false : 'voluntary/ember_js' }
|
3
|
+
|
4
|
+
def index
|
5
|
+
end
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
def voluntary_ember_js_stylesheets
|
10
|
+
['voluntary_ranking/application']
|
11
|
+
end
|
12
|
+
|
13
|
+
def voluntary_ember_js_javascripts
|
14
|
+
['voluntary_ranking/application']
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class Argument < ActiveRecord::Base
|
2
|
+
belongs_to :topic, class_name: 'ArgumentTopic'
|
3
|
+
belongs_to :thing
|
4
|
+
|
5
|
+
scope :compare_two_things, ->(side, left_thing_name, right_thing_name) do
|
6
|
+
left_thing_name, right_thing_name = right_thing_name, left_thing_name if side == 'right'
|
7
|
+
|
8
|
+
left_thing = Thing.where('LOWER(name) = ?', left_thing_name.downcase).first
|
9
|
+
right_thing = Thing.where('LOWER(name) = ?', right_thing_name.downcase).first
|
10
|
+
|
11
|
+
scope = joins(:topic).select('arguments.id, arguments.value, arguments.topic_id, argument_topics.name AS topic_name, arguments2.id AS right_id, arguments2.value AS right_value').
|
12
|
+
joins("#{side == 'both' ? 'INNER' : 'LEFT'} JOIN arguments arguments2 ON arguments2.thing_id = #{sanitize(right_thing.id)} AND arguments2.topic_id = arguments.topic_id")
|
13
|
+
scope = scope.where('arguments2.id IS NULL') unless side == 'both'
|
14
|
+
scope.where('arguments.thing_id = ?', left_thing.id)
|
15
|
+
end
|
16
|
+
|
17
|
+
validates :topic_id, presence: true
|
18
|
+
validates :thing_id, presence: true, uniqueness: { scope: :topic_id }
|
19
|
+
validates :value, presence: true
|
20
|
+
|
21
|
+
attr_accessible :topic_id, :thing_id, :value
|
22
|
+
|
23
|
+
def self.create_with_topic(attributes)
|
24
|
+
topic = ArgumentTopic.where('LOWER(name) = ?', attributes[:topic_name].to_s.strip.downcase).first
|
25
|
+
|
26
|
+
unless topic
|
27
|
+
topic = ArgumentTopic.create(name: attributes[:topic_name].to_s.strip)
|
28
|
+
end
|
29
|
+
|
30
|
+
if topic.valid?
|
31
|
+
thing_id = if attributes[:thing_name].present?
|
32
|
+
Thing.where('LOWER(name) = ?', attributes[:thing_name].downcase).first.id
|
33
|
+
else
|
34
|
+
Thing.where(id: attributes[:thing_id]).first.try(:id)
|
35
|
+
end
|
36
|
+
|
37
|
+
argument = Argument.create(topic_id: topic.id, thing_id: thing_id, value: attributes[:value])
|
38
|
+
|
39
|
+
if argument.valid?
|
40
|
+
argument
|
41
|
+
else
|
42
|
+
{ errors: argument.errors.to_hash }
|
43
|
+
end
|
44
|
+
else
|
45
|
+
{ errors: { topic: topic.errors.to_hash } }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
class Ranking < ActiveRecord::Base
|
2
|
+
attr_accessible :adjective, :topic, :scope, :negative_adjective
|
3
|
+
|
4
|
+
has_many :items, class_name: 'RankingItem', dependent: :destroy
|
5
|
+
has_many :user_items, class_name: 'UserRankingItem', dependent: :destroy
|
6
|
+
|
7
|
+
scope :for_user, ->(user_name) do
|
8
|
+
all.select('DISTINCT(rankings.id), rankings.*').joins(:user_items).
|
9
|
+
where('user_ranking_items.user_id = ?', User.where('LOWER(name) = ?', user_name.downcase).first.id)
|
10
|
+
end
|
11
|
+
|
12
|
+
scope :for_thing, ->(thing_id) do
|
13
|
+
all.select('DISTINCT(rankings.id), rankings.*').joins(:items).where('ranking_items.thing_id = ?', thing_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
validates :adjective, presence: true
|
17
|
+
validates :topic, presence: true, uniqueness: { scope: [:adjective, :scope], case_sensitive: false }
|
18
|
+
validates :scope, presence: true
|
19
|
+
validate :one_ranking_per_topic_scope_and_one_of_the_adjectives
|
20
|
+
|
21
|
+
#pusherable "#{Rails.env}_channel"
|
22
|
+
|
23
|
+
def self.find_by_params(params)
|
24
|
+
scope = if params[:negative_adjective].present?
|
25
|
+
where(
|
26
|
+
'LOWER(adjective) = ? AND LOWER(negative_adjective) = ?',
|
27
|
+
params[:adjective].downcase, params[:negative_adjective].downcase
|
28
|
+
)
|
29
|
+
else
|
30
|
+
where(
|
31
|
+
'(LOWER(adjective) = :adjective OR LOWER(negative_adjective) = :adjective)',
|
32
|
+
adjective: params[:adjective].downcase
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
scope.where(
|
37
|
+
'LOWER(topic) = ? AND LOWER(scope) = ?', params[:topic].downcase, params[:scope].downcase
|
38
|
+
).first
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.find_or_create_by_params(params)
|
42
|
+
attributes = (params[:user_ranking_item] || params[:ranking_item] || params).clone
|
43
|
+
attributes.symbolize_keys! unless params.is_a?(ActiveSupport::HashWithIndifferentAccess)
|
44
|
+
|
45
|
+
if attributes[:ranking_id].present? then Ranking.find(attributes[:ranking_id])
|
46
|
+
elsif attributes[:adjective].present?
|
47
|
+
rankings = Ranking
|
48
|
+
ranking = Ranking.new
|
49
|
+
|
50
|
+
attributes.each do |param, value|
|
51
|
+
if ranking.respond_to?(param) && value.present?
|
52
|
+
rankings = rankings.where("LOWER(#{param}) = ?", value.downcase)
|
53
|
+
else
|
54
|
+
attributes.delete(param)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
rankings.first || Ranking.create(attributes)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.autocomplete_attribute(attribute, term)
|
63
|
+
unless ['adjective', 'negative_adjective', 'topic', 'scope'].include? attribute
|
64
|
+
raise ActiveRecord::RecordNotFound
|
65
|
+
end
|
66
|
+
|
67
|
+
Ranking.select("DISTINCT(#{attribute})").order(attribute).limit(10).
|
68
|
+
where("#{attribute} LIKE ?", "%#{term.strip}%").map(&attribute.to_sym).map{|v| { value: v }}
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def one_ranking_per_topic_scope_and_one_of_the_adjectives
|
74
|
+
if Ranking.where(
|
75
|
+
'(' +
|
76
|
+
'LOWER(adjective) = :adjective OR LOWER(negative_adjective) = :adjective OR ' +
|
77
|
+
'LOWER(adjective) = :negative_adjective OR LOWER(negative_adjective) = :negative_adjective' +
|
78
|
+
') AND ' +
|
79
|
+
'LOWER(topic) = :topic AND LOWER(scope) = :scope',
|
80
|
+
adjective: adjective.downcase, negative_adjective: negative_adjective.downcase,
|
81
|
+
topic: topic.downcase, scope: scope.downcase
|
82
|
+
).any?
|
83
|
+
errors[:base] << I18n.t(
|
84
|
+
'activerecord.errors.models.ranking.attributes.base.' +
|
85
|
+
'one_ranking_per_topic_scope_and_one_of_the_adjectives'
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def special_characters_excluded
|
91
|
+
if adjective.match(/\//) || negative_adjective.match(/\//) || topic.match(/\//) || scope.match(/\//)
|
92
|
+
errors[:name] << I18n.t(
|
93
|
+
'activerecord.errors.models.ranking.attributes.name.unwanted_special_characters_included'
|
94
|
+
)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|