rostra 0.0.14 → 0.0.15
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.
- data/README.rdoc +4 -1
- data/app/controllers/rostra/answers_controller.rb +2 -37
- data/app/controllers/rostra/application_controller.rb +3 -3
- data/app/controllers/rostra/base/answers_controller.rb +42 -0
- data/app/controllers/rostra/base/comments_controller.rb +31 -0
- data/app/controllers/rostra/base/questions_controller.rb +15 -7
- data/app/controllers/rostra/comments_controller.rb +2 -28
- data/app/helpers/rostra/application_helper.rb +1 -1
- data/app/helpers/rostra/base/application_helper.rb +89 -0
- data/app/models/rostra/ability.rb +1 -3
- data/app/models/rostra/question.rb +4 -1
- data/app/views/layouts/rostra/application.html.erb +1 -3
- data/app/views/rostra/questions/_form.html.erb +1 -1
- data/app/views/rostra/questions/index.html.erb +2 -0
- data/app/views/rostra/questions/show.html.erb +3 -3
- data/app/views/rostra/questions/toggle_following.js.erb +7 -0
- data/app/views/rostra/shared/_sidebar.html.erb +5 -1
- data/app/views/rostra/shared/_toggle_following_question_button.html.erb +3 -0
- data/app/views/rostra/shared/_votes.html.erb +1 -1
- data/config/routes.rb +6 -5
- data/lib/generators/rostra/templates/app/helpers/rostra/application_helper.rb +1 -1
- data/lib/generators/rostra/templates/config/initializers/rostra.rb +4 -0
- data/lib/rostra.rb +6 -0
- data/lib/rostra/config.rb +6 -0
- data/lib/rostra/engine.rb +1 -0
- data/lib/rostra/version.rb +1 -1
- metadata +32 -17
- data/app/helpers/rostra/base_helper.rb +0 -87
data/README.rdoc
CHANGED
@@ -41,7 +41,7 @@ Also, be sure to read through <tt>config/initializers/rostra.rb</tt> and overrid
|
|
41
41
|
|
42
42
|
Finally, have a look at <tt>app/helpers/rostra/application_helper.rb</tt>, you may need to add/override helper methods.
|
43
43
|
|
44
|
-
==
|
44
|
+
== Overriding models
|
45
45
|
Rostra provides a DSL for adding application specific logic to <tt>Rostra::Question</tt> and <tt>Rostra:Answer</tt>:
|
46
46
|
|
47
47
|
class User < ActiveRecord::Base
|
@@ -69,6 +69,9 @@ Rostra provides a DSL for adding application specific logic to <tt>Rostra::Quest
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
== Overriding Controllers
|
73
|
+
Added instructions for overriding controllers here (including generators!)
|
74
|
+
|
72
75
|
== Setting permissions
|
73
76
|
Under the hood, Rostra uses <tt>CanCan</tt> to set permissions. By default anyone can read rostra content - even if they are not logged in. A user can contribute content (i.e. ask questions, give answers, and leave comments) as long as they've logged in.
|
74
77
|
|
@@ -1,40 +1,5 @@
|
|
1
1
|
module Rostra
|
2
|
-
class AnswersController <
|
3
|
-
|
4
|
-
before_filter :fetch_question
|
5
|
-
|
6
|
-
def vote
|
7
|
-
rostra_user.vote_on(@answer, params[:vote_direction])
|
8
|
-
|
9
|
-
respond_to do |format|
|
10
|
-
format.html { redirect_to question_path(@question, anchor: "rostra_answer_#{@answer.id}") }
|
11
|
-
format.js
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def create
|
16
|
-
if @answer.save
|
17
|
-
redirect_to question_path(@question, anchor: "rostra_answer_#{@answer.id}")
|
18
|
-
else
|
19
|
-
redirect_to question_path(@question, anchor: 'new_rostra_answer')
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def edit
|
24
|
-
end
|
25
|
-
|
26
|
-
def update
|
27
|
-
if @answer.update_attributes(params[:answer])
|
28
|
-
redirect_to question_path(@question, anchor: "rostra_answer_#{@answer.id}")
|
29
|
-
else
|
30
|
-
render :edit
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def fetch_question
|
37
|
-
@question = Question.find(params[:question_id])
|
38
|
-
end
|
2
|
+
class AnswersController < Rostra::Base::AnswersController
|
3
|
+
# Override existing actions here
|
39
4
|
end
|
40
5
|
end
|
@@ -3,7 +3,7 @@ module Rostra
|
|
3
3
|
|
4
4
|
include Rostra::Config
|
5
5
|
|
6
|
-
helper_method :
|
6
|
+
helper_method :can_participate_in_rostra?, :main_app_login_path, :main_app_signup_path, :rostra_user
|
7
7
|
|
8
8
|
rescue_from CanCan::AccessDenied do |exception|
|
9
9
|
after_access_denied
|
@@ -25,8 +25,8 @@ module Rostra
|
|
25
25
|
|
26
26
|
# Check if a user is logged in
|
27
27
|
#
|
28
|
-
def
|
29
|
-
rostra_user
|
28
|
+
def can_participate_in_rostra?
|
29
|
+
rostra_user && rostra_user.can_participate_in_rostra?
|
30
30
|
end
|
31
31
|
|
32
32
|
private
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rostra
|
2
|
+
module Base
|
3
|
+
class AnswersController < ApplicationController
|
4
|
+
load_and_authorize_resource
|
5
|
+
before_filter :fetch_question
|
6
|
+
|
7
|
+
def vote
|
8
|
+
rostra_user.vote_on(@answer, params[:vote_direction])
|
9
|
+
|
10
|
+
respond_to do |format|
|
11
|
+
format.html { redirect_to question_path(@question, anchor: "rostra_answer_#{@answer.id}") }
|
12
|
+
format.js
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def create
|
17
|
+
if @answer.save
|
18
|
+
redirect_to question_path(@question, anchor: "rostra_answer_#{@answer.id}")
|
19
|
+
else
|
20
|
+
redirect_to question_path(@question, anchor: 'new_rostra_answer')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def edit
|
25
|
+
end
|
26
|
+
|
27
|
+
def update
|
28
|
+
if @answer.update_attributes(params[:answer])
|
29
|
+
redirect_to question_path(@question, anchor: "rostra_answer_#{@answer.id}")
|
30
|
+
else
|
31
|
+
render :edit
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def fetch_question
|
38
|
+
@question = Question.find(params[:question_id])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Rostra
|
2
|
+
module Base
|
3
|
+
class CommentsController < ApplicationController
|
4
|
+
load_and_authorize_resource
|
5
|
+
|
6
|
+
before_filter :fetch_question
|
7
|
+
|
8
|
+
def create
|
9
|
+
if @comment.save
|
10
|
+
redirect_to @question
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
@comment.update_attributes(:comment => params[:value])
|
16
|
+
render :text => @comment.comment
|
17
|
+
end
|
18
|
+
|
19
|
+
def destroy
|
20
|
+
@comment.destroy
|
21
|
+
redirect_to @question
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def fetch_question
|
27
|
+
@question = Question.find(params[:question_id])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -12,11 +12,24 @@ module Rostra
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
def toggle_following
|
16
|
+
if rostra_user.following?(@question)
|
17
|
+
rostra_user.followed_questions.delete(@question)
|
18
|
+
else
|
19
|
+
rostra_user.followed_questions << @question
|
20
|
+
end
|
21
|
+
|
22
|
+
respond_to do |format|
|
23
|
+
format.html { redirect_to @question }
|
24
|
+
format.js
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
15
28
|
def index
|
16
29
|
if params[:tag_search].present?
|
17
|
-
@questions = Question.tagged_with(params[:tag_search]).order('created_at desc')
|
30
|
+
@questions = Question.tagged_with(params[:tag_search]).order('created_at desc').page(params[:page])
|
18
31
|
else
|
19
|
-
@questions = Question.order('created_at desc')
|
32
|
+
@questions = Question.order('created_at desc').page(params[:page])
|
20
33
|
end
|
21
34
|
end
|
22
35
|
|
@@ -47,11 +60,6 @@ module Rostra
|
|
47
60
|
end
|
48
61
|
end
|
49
62
|
|
50
|
-
def destroy
|
51
|
-
@question.destroy
|
52
|
-
redirect_to questions_url
|
53
|
-
end
|
54
|
-
|
55
63
|
end
|
56
64
|
end
|
57
65
|
end
|
@@ -1,31 +1,5 @@
|
|
1
1
|
module Rostra
|
2
|
-
class CommentsController <
|
3
|
-
|
4
|
-
|
5
|
-
before_filter :fetch_question
|
6
|
-
|
7
|
-
def create
|
8
|
-
|
9
|
-
if @comment.save
|
10
|
-
redirect_to @question
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def update
|
15
|
-
@comment.update_attributes(:comment => params[:value])
|
16
|
-
render :text => @comment.comment
|
17
|
-
end
|
18
|
-
|
19
|
-
def destroy
|
20
|
-
@comment.destroy
|
21
|
-
redirect_to @question
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def fetch_question
|
27
|
-
@question = Question.find(params[:question_id])
|
28
|
-
end
|
29
|
-
|
2
|
+
class CommentsController < Rostra::Base::CommentsController
|
3
|
+
# Override existing actions here
|
30
4
|
end
|
31
5
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Rostra
|
2
|
+
module Base
|
3
|
+
module ApplicationHelper
|
4
|
+
|
5
|
+
# Method used to render to user names (e.g. where it says: "John Does says:"). You can,
|
6
|
+
# for example, use this method to turn "John Doe" into a link to his profile page.
|
7
|
+
#
|
8
|
+
def link_to_profile(user)
|
9
|
+
link_to user.rostra_user_name, main_app.user_path(user)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Used to populate both the <tt>title</tt> and <tt>h1</tt> elements for each page.
|
13
|
+
#
|
14
|
+
def page_title_helper
|
15
|
+
case "#{controller_name}##{action_name}"
|
16
|
+
when "questions#show" then @question.title
|
17
|
+
when "questions#index" then
|
18
|
+
if params[:tag_search].present?
|
19
|
+
"Recent Questions for tag #{params[:tag_search]}"
|
20
|
+
else
|
21
|
+
"Recent Questions"
|
22
|
+
end
|
23
|
+
when "questions#new" then "Post a new question"
|
24
|
+
when "questions#edit" then "Editing question"
|
25
|
+
when "answers#edit" then "Editing answer"
|
26
|
+
else "Recent Questions"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Creates a list of tags linking to the index showing only questions with that tag
|
31
|
+
#
|
32
|
+
def tag_list(question)
|
33
|
+
tags = question.tags.map { |tag| link_to tag, questions_path(:tag_search => "#{tag}")}.join
|
34
|
+
content_tag :div, "Tags: #{tags}".html_safe, class: 'tags'
|
35
|
+
end
|
36
|
+
|
37
|
+
# Finds the url to the user's avatar following this logic:
|
38
|
+
#
|
39
|
+
# 1. Calls <tt>avatar</tt> on the user object
|
40
|
+
# 2. Uses the users email address to look for a gravatar
|
41
|
+
# 3. Renders <tt>app/assets/images/rostra/anonymous_avatar.png</tt>
|
42
|
+
#
|
43
|
+
def rostra_user_avatar(user)
|
44
|
+
if user.respond_to?(:avatar)
|
45
|
+
url = user.avatar
|
46
|
+
else
|
47
|
+
default_url = "#{main_app.root_url}assets/rostra/anonymous_avatar.png"
|
48
|
+
gravatar_id = Digest::MD5.hexdigest(user.rostra_user_email.downcase)
|
49
|
+
url = "http://gravatar.com/avatar/#{gravatar_id}.png?s=48&d=#{CGI.escape(default_url)}"
|
50
|
+
end
|
51
|
+
image_tag(url, class: 'avatar')
|
52
|
+
end
|
53
|
+
|
54
|
+
# Method to build links for ajax-y voting arrows.
|
55
|
+
#
|
56
|
+
def link_to_vote(direction, resource)
|
57
|
+
if can_participate_in_rostra? && ( (direction == :up && rostra_user.voted_for?(resource)) || (direction == :down && rostra_user.voted_against?(resource)) )
|
58
|
+
selected = 'selected'
|
59
|
+
else
|
60
|
+
selected = ''
|
61
|
+
end
|
62
|
+
|
63
|
+
link_to "Vote #{direction.capitalize}", vote_path(resource, direction), method: :put, remote: true, class: "vote #{direction} #{selected}"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns a rostra object's base class name. For example, <tt>@question</tt> is an instance of
|
67
|
+
# Rostra::Question and so:
|
68
|
+
#
|
69
|
+
# class_name(@question) # => 'question'
|
70
|
+
#
|
71
|
+
def class_name(resource)
|
72
|
+
resource.class.name.split('::').last.downcase
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def vote_path(resource, direction)
|
78
|
+
return '#' if !can_participate_in_rostra? || can?(:manage, resource)
|
79
|
+
|
80
|
+
if resource.is_a?(Rostra::Question)
|
81
|
+
vote_question_path(resource, vote_direction: direction)
|
82
|
+
else
|
83
|
+
vote_question_answer_path(resource.question, resource, vote_direction: direction)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -2,8 +2,6 @@ module Rostra
|
|
2
2
|
class Ability
|
3
3
|
include CanCan::Ability
|
4
4
|
|
5
|
-
attr_reader :user
|
6
|
-
|
7
5
|
def initialize(user)
|
8
6
|
@user = user || User.new
|
9
7
|
|
@@ -12,7 +10,7 @@ module Rostra
|
|
12
10
|
can :manage, Answer, :user => user
|
13
11
|
can :manage, Comment, :user => user
|
14
12
|
|
15
|
-
can :vote, Question
|
13
|
+
can [:vote, :toggle_following], Question
|
16
14
|
cannot :vote, Question, :user => user
|
17
15
|
|
18
16
|
can :vote, Answer
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Rostra
|
2
2
|
class Question < ActiveRecord::Base
|
3
|
-
|
4
3
|
belongs_to :user
|
5
4
|
has_many :answers
|
6
5
|
has_many :question_followings
|
@@ -17,6 +16,10 @@ module Rostra
|
|
17
16
|
before_save :create_question_following
|
18
17
|
attr_accessor :follow_by_email
|
19
18
|
|
19
|
+
# Set number of questions per page for will paginate
|
20
|
+
#
|
21
|
+
per_page = Rostra::Config.number_of_question_per_page
|
22
|
+
|
20
23
|
# Finds questions asked within the last 15 days ordered by non-unique page views.
|
21
24
|
#
|
22
25
|
def self.trending(limit = 5)
|
@@ -8,9 +8,7 @@
|
|
8
8
|
</head>
|
9
9
|
<body id="<%= controller_name %>" class="<%= action_name %>">
|
10
10
|
<div id="page_wrap">
|
11
|
-
|
12
|
-
<%= link_to 'Recent questions', questions_path %>
|
13
|
-
</nav>
|
11
|
+
|
14
12
|
<% flash.each do |name, msg| %>
|
15
13
|
<%= content_tag :div, msg, id: "flash_#{name}", class: 'flash' %>
|
16
14
|
<% end %>
|
@@ -4,5 +4,5 @@
|
|
4
4
|
<%= f.input :details, input_html: {class: 'wysiwyg'} %>
|
5
5
|
<%= f.input :tag_list, label: 'Tags', hint: 'Separate tags with commas' %>
|
6
6
|
<%= f.input :follow_by_email, as: :boolean, input_html: { checked: true }, label: "I want to follow answers and comments on this question" %>
|
7
|
-
<%= f.submit
|
7
|
+
<%= f.submit @question.new_record? ? 'Post your question' : 'Update' %>
|
8
8
|
<% end %>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
Asked by <%= link_to_profile(@question.user) %>
|
10
10
|
<%= link_to 'edit', edit_question_path(@question) if can? :manage, @question %>
|
11
11
|
</cite>
|
12
|
-
<div class="text"><%=
|
12
|
+
<div class="text"><%= @question.details.html_safe %></div>
|
13
13
|
<div class="details">
|
14
14
|
<div class="timestamp"><%= time_ago_in_words(@question.updated_at) %> ago</div>
|
15
15
|
<%= tag_list(@question) %>
|
@@ -27,7 +27,7 @@
|
|
27
27
|
<%= link_to_profile(answer.user) %> says:
|
28
28
|
<%= link_to('edit', edit_question_answer_path(@question, answer)) if can? :manage, answer %>
|
29
29
|
</cite>
|
30
|
-
<div class="text"><%=
|
30
|
+
<div class="text"><%= answer.text.html_safe %></div>
|
31
31
|
<div class="timestamp"><%= time_ago_in_words(answer.updated_at) %> ago</div>
|
32
32
|
|
33
33
|
<% if answer.comments.any? %>
|
@@ -71,7 +71,7 @@
|
|
71
71
|
</div>
|
72
72
|
<% end %>
|
73
73
|
|
74
|
-
<% if
|
74
|
+
<% if can_participate_in_rostra? %>
|
75
75
|
<%= render 'rostra/answers/form' %>
|
76
76
|
<% else %>
|
77
77
|
<%= link_to "Login to answer this question", main_app_login_path, class: 'button' %>
|
@@ -1,10 +1,14 @@
|
|
1
1
|
<div id="sidebar">
|
2
|
-
<% if
|
2
|
+
<% if can_participate_in_rostra? %>
|
3
3
|
<%= link_to 'Ask a question', new_question_path, class: "button" %>
|
4
4
|
<% else %>
|
5
5
|
<%= link_to 'Login to ask a question', main_app_login_path, class: "button" %>
|
6
6
|
<% end %>
|
7
7
|
|
8
|
+
<% if can_participate_in_rostra? && controller_name == 'questions' && action_name == 'show' %>
|
9
|
+
<%= render partial: 'rostra/shared/toggle_following_question_button', locals: { question: @question } %>
|
10
|
+
<% end %>
|
11
|
+
|
8
12
|
<h4>Trending questions</h4>
|
9
13
|
<ul id="trending_questions">
|
10
14
|
<% Rostra::Question.trending.each do |question| %>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<%= link_to_vote(:down, resource) %>
|
5
5
|
</div>
|
6
6
|
|
7
|
-
<% unless
|
7
|
+
<% unless can_participate_in_rostra? %>
|
8
8
|
<div class="hidden flash" id="flash_notice">
|
9
9
|
You must <%= link_to 'login', main_app_login_path %> or <%= link_to 'signup', main_app_signup_path %> in order to vote
|
10
10
|
<%= link_to 'X', '#', class: 'closeable' %>
|
data/config/routes.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
Rostra::Engine.routes.draw do
|
2
|
-
resources :questions do
|
3
|
-
put :vote, :
|
4
|
-
|
5
|
-
|
2
|
+
resources :questions, except: [:destroy] do
|
3
|
+
put :vote, on: :member
|
4
|
+
put :toggle_following, on: :member
|
5
|
+
resources :answers, only: [:create, :edit, :update] do
|
6
|
+
put :vote, on: :member
|
6
7
|
end
|
7
|
-
resources :comments, :
|
8
|
+
resources :comments, only: [:create, :update, :destroy]
|
8
9
|
end
|
9
10
|
|
10
11
|
root :to => "questions#index"
|
@@ -6,7 +6,7 @@ module Rostra
|
|
6
6
|
# this line but you can add/override rostra methods in this file. The helpers which you may
|
7
7
|
# need to override are listed below. Just un-comment them and make changes.
|
8
8
|
#
|
9
|
-
include Rostra::
|
9
|
+
include Rostra::Base::ApplicationHelper
|
10
10
|
|
11
11
|
# If you want to user helper methods defined elsewhere in your app, you can include them here
|
12
12
|
# as well. For example:
|
@@ -3,6 +3,10 @@ Rostra::Config.setup do |config|
|
|
3
3
|
# Helper method used to access current user in the view
|
4
4
|
# config.deliver_emails_from = 'change_me@example.com'
|
5
5
|
|
6
|
+
# Set the number of questions that will appear on each page. Applies to both the
|
7
|
+
# questions index page (i.e. "recent questions" and "questions tagged with")
|
8
|
+
# config.number_of_question_per_page = 10
|
9
|
+
|
6
10
|
# Helper method used to access current user in the view
|
7
11
|
# config.rostra_user = :current_user
|
8
12
|
|
data/lib/rostra.rb
CHANGED
@@ -63,6 +63,12 @@ module Rostra
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
# Check if the user is following a given question
|
67
|
+
#
|
68
|
+
def following?(question)
|
69
|
+
followed_questions.include?(question)
|
70
|
+
end
|
71
|
+
|
66
72
|
# By default anyone can read rostra content - even if they are not logged in. This method
|
67
73
|
# determines if users can contribute content (i.e. ask questions, give answers, and leave
|
68
74
|
# comments). If <tt>can_participate_in_rostra?</tt> returns true, the user can contribute
|
data/lib/rostra/config.rb
CHANGED
@@ -6,6 +6,12 @@ module Rostra
|
|
6
6
|
mattr_accessor :deliver_emails_from
|
7
7
|
@@deliver_emails_from = 'change_me@example.com'
|
8
8
|
|
9
|
+
# Set the number of questions that will appear on each page. Applies to both the
|
10
|
+
# questions index page (i.e. "recent questions" and "questions tagged with")
|
11
|
+
#
|
12
|
+
mattr_accessor :number_of_question_per_page
|
13
|
+
@@number_of_question_per_page = 10
|
14
|
+
|
9
15
|
# Helper method used to access current user in the view
|
10
16
|
#
|
11
17
|
mattr_accessor :rostra_user
|
data/lib/rostra/engine.rb
CHANGED
data/lib/rostra/version.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: rostra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.15
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Cory Schires
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-10-
|
13
|
+
date: 2011-10-24 00:00:00 -05:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -113,7 +113,7 @@ dependencies:
|
|
113
113
|
type: :runtime
|
114
114
|
version_requirements: *id009
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
|
-
name:
|
116
|
+
name: will_paginate
|
117
117
|
prerelease: false
|
118
118
|
requirement: &id010 !ruby/object:Gem::Requirement
|
119
119
|
none: false
|
@@ -121,10 +121,10 @@ dependencies:
|
|
121
121
|
- - ">="
|
122
122
|
- !ruby/object:Gem::Version
|
123
123
|
version: "0"
|
124
|
-
type: :
|
124
|
+
type: :runtime
|
125
125
|
version_requirements: *id010
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
127
|
+
name: sqlite3
|
128
128
|
prerelease: false
|
129
129
|
requirement: &id011 !ruby/object:Gem::Requirement
|
130
130
|
none: false
|
@@ -135,7 +135,7 @@ dependencies:
|
|
135
135
|
type: :development
|
136
136
|
version_requirements: *id011
|
137
137
|
- !ruby/object:Gem::Dependency
|
138
|
-
name:
|
138
|
+
name: cucumber-rails
|
139
139
|
prerelease: false
|
140
140
|
requirement: &id012 !ruby/object:Gem::Requirement
|
141
141
|
none: false
|
@@ -146,7 +146,7 @@ dependencies:
|
|
146
146
|
type: :development
|
147
147
|
version_requirements: *id012
|
148
148
|
- !ruby/object:Gem::Dependency
|
149
|
-
name:
|
149
|
+
name: factory_girl_rails
|
150
150
|
prerelease: false
|
151
151
|
requirement: &id013 !ruby/object:Gem::Requirement
|
152
152
|
none: false
|
@@ -157,7 +157,7 @@ dependencies:
|
|
157
157
|
type: :development
|
158
158
|
version_requirements: *id013
|
159
159
|
- !ruby/object:Gem::Dependency
|
160
|
-
name:
|
160
|
+
name: launchy
|
161
161
|
prerelease: false
|
162
162
|
requirement: &id014 !ruby/object:Gem::Requirement
|
163
163
|
none: false
|
@@ -168,29 +168,29 @@ dependencies:
|
|
168
168
|
type: :development
|
169
169
|
version_requirements: *id014
|
170
170
|
- !ruby/object:Gem::Dependency
|
171
|
-
name:
|
171
|
+
name: database_cleaner
|
172
172
|
prerelease: false
|
173
173
|
requirement: &id015 !ruby/object:Gem::Requirement
|
174
174
|
none: false
|
175
175
|
requirements:
|
176
|
-
- -
|
176
|
+
- - ">="
|
177
177
|
- !ruby/object:Gem::Version
|
178
|
-
version: "
|
178
|
+
version: "0"
|
179
179
|
type: :development
|
180
180
|
version_requirements: *id015
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
182
|
+
name: rspec-rails
|
183
183
|
prerelease: false
|
184
184
|
requirement: &id016 !ruby/object:Gem::Requirement
|
185
185
|
none: false
|
186
186
|
requirements:
|
187
|
-
- -
|
187
|
+
- - ~>
|
188
188
|
- !ruby/object:Gem::Version
|
189
|
-
version: "
|
189
|
+
version: "2.5"
|
190
190
|
type: :development
|
191
191
|
version_requirements: *id016
|
192
192
|
- !ruby/object:Gem::Dependency
|
193
|
-
name:
|
193
|
+
name: devise
|
194
194
|
prerelease: false
|
195
195
|
requirement: &id017 !ruby/object:Gem::Requirement
|
196
196
|
none: false
|
@@ -201,7 +201,7 @@ dependencies:
|
|
201
201
|
type: :development
|
202
202
|
version_requirements: *id017
|
203
203
|
- !ruby/object:Gem::Dependency
|
204
|
-
name:
|
204
|
+
name: grb
|
205
205
|
prerelease: false
|
206
206
|
requirement: &id018 !ruby/object:Gem::Requirement
|
207
207
|
none: false
|
@@ -211,6 +211,17 @@ dependencies:
|
|
211
211
|
version: "0"
|
212
212
|
type: :development
|
213
213
|
version_requirements: *id018
|
214
|
+
- !ruby/object:Gem::Dependency
|
215
|
+
name: email_spec
|
216
|
+
prerelease: false
|
217
|
+
requirement: &id019 !ruby/object:Gem::Requirement
|
218
|
+
none: false
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: "0"
|
223
|
+
type: :development
|
224
|
+
version_requirements: *id019
|
214
225
|
description: Don't use. Not production ready
|
215
226
|
email:
|
216
227
|
- coryschires@gmail.com
|
@@ -487,11 +498,13 @@ files:
|
|
487
498
|
- app/assets/stylesheets/rostra/typography.css
|
488
499
|
- app/controllers/rostra/answers_controller.rb
|
489
500
|
- app/controllers/rostra/application_controller.rb
|
501
|
+
- app/controllers/rostra/base/answers_controller.rb
|
502
|
+
- app/controllers/rostra/base/comments_controller.rb
|
490
503
|
- app/controllers/rostra/base/questions_controller.rb
|
491
504
|
- app/controllers/rostra/comments_controller.rb
|
492
505
|
- app/controllers/rostra/questions_controller.rb
|
493
506
|
- app/helpers/rostra/application_helper.rb
|
494
|
-
- app/helpers/rostra/
|
507
|
+
- app/helpers/rostra/base/application_helper.rb
|
495
508
|
- app/mailers/rostra/application_mailer.rb
|
496
509
|
- app/models/comment.rb
|
497
510
|
- app/models/rostra/ability.rb
|
@@ -510,8 +523,10 @@ files:
|
|
510
523
|
- app/views/rostra/questions/index.html.erb
|
511
524
|
- app/views/rostra/questions/new.html.erb
|
512
525
|
- app/views/rostra/questions/show.html.erb
|
526
|
+
- app/views/rostra/questions/toggle_following.js.erb
|
513
527
|
- app/views/rostra/questions/vote.js.erb
|
514
528
|
- app/views/rostra/shared/_sidebar.html.erb
|
529
|
+
- app/views/rostra/shared/_toggle_following_question_button.html.erb
|
515
530
|
- app/views/rostra/shared/_votes.html.erb
|
516
531
|
- config/cucumber.yml
|
517
532
|
- config/initializers/client_side_validations.rb
|
@@ -1,87 +0,0 @@
|
|
1
|
-
module Rostra
|
2
|
-
module BaseHelper
|
3
|
-
|
4
|
-
# Method used to render to user names (e.g. where it says: "John Does says:"). You can,
|
5
|
-
# for example, use this method to turn "John Doe" into a link to his profile page.
|
6
|
-
#
|
7
|
-
def link_to_profile(user)
|
8
|
-
link_to user.rostra_user_name, main_app.user_path(user)
|
9
|
-
end
|
10
|
-
|
11
|
-
# Used to populate both the <tt>title</tt> and <tt>h1</tt> elements for each page.
|
12
|
-
#
|
13
|
-
def page_title_helper
|
14
|
-
case "#{controller_name}##{action_name}"
|
15
|
-
when "questions#show" then @question.title
|
16
|
-
when "questions#index" then
|
17
|
-
if params[:tag_search].present?
|
18
|
-
"Recent Questions for tag #{params[:tag_search]}"
|
19
|
-
else
|
20
|
-
"Recent Questions"
|
21
|
-
end
|
22
|
-
when "questions#new" then "Post a new question"
|
23
|
-
when "questions#edit" then "Editing question"
|
24
|
-
when "answers#edit" then "Editing answer"
|
25
|
-
else "Recent Questions"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# Creates a list of tags linking to the index showing only questions with that tag
|
30
|
-
#
|
31
|
-
def tag_list(question)
|
32
|
-
tags = question.tags.map { |tag| link_to tag, questions_path(:tag_search => "#{tag}")}.join
|
33
|
-
content_tag :div, "Tags: #{tags}".html_safe, class: 'tags'
|
34
|
-
end
|
35
|
-
|
36
|
-
# Finds the url to the user's avatar following this logic:
|
37
|
-
#
|
38
|
-
# 1. Calls <tt>avatar</tt> on the user object
|
39
|
-
# 2. Uses the users email address to look for a gravatar
|
40
|
-
# 3. Renders <tt>app/assets/images/rostra/anonymous_avatar.png</tt>
|
41
|
-
#
|
42
|
-
def rostra_user_avatar(user)
|
43
|
-
if user.respond_to?(:avatar)
|
44
|
-
url = user.avatar
|
45
|
-
else
|
46
|
-
default_url = "#{main_app.root_url}assets/rostra/anonymous_avatar.png"
|
47
|
-
gravatar_id = Digest::MD5.hexdigest(user.rostra_user_email.downcase)
|
48
|
-
url = "http://gravatar.com/avatar/#{gravatar_id}.png?s=48&d=#{CGI.escape(default_url)}"
|
49
|
-
end
|
50
|
-
image_tag(url, class: 'avatar')
|
51
|
-
end
|
52
|
-
|
53
|
-
# Method to build links for ajax-y voting arrows.
|
54
|
-
#
|
55
|
-
def link_to_vote(direction, resource)
|
56
|
-
if user_signed_in? && ( (direction == :up && rostra_user.voted_for?(resource)) || (direction == :down && rostra_user.voted_against?(resource)) )
|
57
|
-
selected = 'selected'
|
58
|
-
else
|
59
|
-
selected = ''
|
60
|
-
end
|
61
|
-
|
62
|
-
link_to "Vote #{direction.capitalize}", vote_path(resource, direction), method: :put, remote: true, class: "vote #{direction} #{selected}"
|
63
|
-
end
|
64
|
-
|
65
|
-
# Returns a rostra object's base class name. For example, <tt>@question</tt> is an instance of
|
66
|
-
# Rostra::Question and so:
|
67
|
-
#
|
68
|
-
# class_name(@question) # => 'question'
|
69
|
-
#
|
70
|
-
def class_name(resource)
|
71
|
-
resource.class.name.split('::').last.downcase
|
72
|
-
end
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
def vote_path(resource, direction)
|
77
|
-
return '#' if !user_signed_in? || can?(:manage, resource)
|
78
|
-
|
79
|
-
if resource.is_a?(Rostra::Question)
|
80
|
-
vote_question_path(resource, vote_direction: direction)
|
81
|
-
else
|
82
|
-
vote_question_answer_path(resource.question, resource, vote_direction: direction)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
end
|
87
|
-
end
|