rostra 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.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +30 -0
- data/Rakefile +27 -0
- data/app/assets/images/rostra/vote_arrows.png +0 -0
- data/app/assets/javascripts/rostra/application.js +28 -0
- data/app/assets/javascripts/rostra/jquery.jeditable.js +543 -0
- data/app/assets/stylesheets/rostra/application.css +177 -0
- data/app/assets/stylesheets/rostra/buttons.css +43 -0
- data/app/assets/stylesheets/rostra/flash_messages.css +13 -0
- data/app/assets/stylesheets/rostra/forms.css +40 -0
- data/app/assets/stylesheets/rostra/questions.css +4 -0
- data/app/assets/stylesheets/rostra/reset.css +13 -0
- data/app/assets/stylesheets/rostra/typography.css +7 -0
- data/app/controllers/rostra/answers_controller.rb +47 -0
- data/app/controllers/rostra/application_controller.rb +31 -0
- data/app/controllers/rostra/questions_controller.rb +57 -0
- data/app/helpers/rostra/application_helper.rb +4 -0
- data/app/helpers/rostra/questions_helper.rb +4 -0
- data/app/models/rostra/ability.rb +27 -0
- data/app/models/rostra/answer.rb +10 -0
- data/app/models/rostra/question.rb +15 -0
- data/app/models/rostra/vote.rb +19 -0
- data/app/models/vote.rb +17 -0
- data/app/views/layouts/rostra/application.html.erb +23 -0
- data/app/views/rostra/answers/_form.html.erb +8 -0
- data/app/views/rostra/answers/edit.html.erb +7 -0
- data/app/views/rostra/answers/vote.js.erb +1 -0
- data/app/views/rostra/questions/_form.html.erb +7 -0
- data/app/views/rostra/questions/edit.html.erb +7 -0
- data/app/views/rostra/questions/index.html.erb +45 -0
- data/app/views/rostra/questions/new.html.erb +7 -0
- data/app/views/rostra/questions/show.html.erb +47 -0
- data/app/views/rostra/questions/vote.js.erb +1 -0
- data/app/views/rostra/shared/_answers_votes.html.erb +27 -0
- data/app/views/rostra/shared/_sidebar.html.erb +8 -0
- data/app/views/rostra/shared/_votes.html.erb +27 -0
- data/config/cucumber.yml +8 -0
- data/config/initializers/client_side_validations.rb +14 -0
- data/config/initializers/simple_form.rb +93 -0
- data/config/locales/simple_form.en.yml +24 -0
- data/config/routes.rb +10 -0
- data/db/migrate/20110918170142_create_rostra_questions.rb +10 -0
- data/db/migrate/20111003233228_acts_as_taggable_on_migration.rb +28 -0
- data/db/migrate/20111005012613_add_user_id_to_questions.rb +5 -0
- data/db/migrate/20111007205730_create_rostra_answers.rb +11 -0
- data/db/migrate/20111008224511_thumbs_up_migration.rb +25 -0
- data/lib/rostra/engine.rb +13 -0
- data/lib/rostra/version.rb +3 -0
- data/lib/rostra.rb +11 -0
- data/lib/tasks/cucumber.rake +65 -0
- data/lib/tasks/rake_routes.rake +40 -0
- data/lib/tasks/rostra_tasks.rake +4 -0
- data/lib/templates/erb/scaffold/_form.html.erb +13 -0
- metadata +273 -0
@@ -0,0 +1,177 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll automatically include all the stylesheets available in this directory
|
3
|
+
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
|
4
|
+
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
5
|
+
*= require_self
|
6
|
+
*= require_tree .
|
7
|
+
*/
|
8
|
+
.hidden {
|
9
|
+
display: none;
|
10
|
+
}
|
11
|
+
|
12
|
+
#page_wrap {
|
13
|
+
width: 970px; margin: auto;
|
14
|
+
}
|
15
|
+
.text {
|
16
|
+
line-height: 18px;
|
17
|
+
}
|
18
|
+
nav {
|
19
|
+
float: right;
|
20
|
+
}
|
21
|
+
#page_content {
|
22
|
+
width: 550px;
|
23
|
+
border-right: 1px solid #ccc;
|
24
|
+
padding-right: 100px;
|
25
|
+
}
|
26
|
+
#sidebar {
|
27
|
+
float: right;
|
28
|
+
width: 300px;
|
29
|
+
text-align: center;
|
30
|
+
}
|
31
|
+
div#questions {
|
32
|
+
min-height: 250px;
|
33
|
+
}
|
34
|
+
.question {
|
35
|
+
margin-bottom: 10px;
|
36
|
+
border-bottom: dashed 1px #E0E0E0;
|
37
|
+
padding-bottom: 15px;
|
38
|
+
}
|
39
|
+
.question h3 {
|
40
|
+
margin-bottom: 5px;
|
41
|
+
width: 500px;
|
42
|
+
}
|
43
|
+
.question h3 a {
|
44
|
+
color: #333;
|
45
|
+
text-decoration: none;
|
46
|
+
}
|
47
|
+
.question h3 a:hover {
|
48
|
+
color: green;
|
49
|
+
background: transparent;
|
50
|
+
}
|
51
|
+
.question cite {
|
52
|
+
display: block;
|
53
|
+
margin-bottom: 20px;
|
54
|
+
color: #aaa;
|
55
|
+
}
|
56
|
+
.question cite a {
|
57
|
+
font-style: normal;
|
58
|
+
margin-left: 5px;
|
59
|
+
}
|
60
|
+
.question .text {
|
61
|
+
margin-bottom: 25px;
|
62
|
+
}
|
63
|
+
.question a.view_more {
|
64
|
+
margin-left: 10px;
|
65
|
+
}
|
66
|
+
.question .tags {
|
67
|
+
color: #aaa;
|
68
|
+
}
|
69
|
+
.question .tags a {
|
70
|
+
margin: 0 3px;
|
71
|
+
}
|
72
|
+
.timestamp {
|
73
|
+
color: #aaa;
|
74
|
+
float: right;
|
75
|
+
}
|
76
|
+
|
77
|
+
.vote h4 p.already_voted {
|
78
|
+
color: #e6e6e6;
|
79
|
+
}
|
80
|
+
|
81
|
+
/* styles for question on question show page */
|
82
|
+
body#questions.show .question {
|
83
|
+
border-bottom: none;
|
84
|
+
margin-bottom: 50px;
|
85
|
+
}
|
86
|
+
body#questions.show #page_content {
|
87
|
+
margin-left: 50px;
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
/* answers section */
|
92
|
+
#answer_count{
|
93
|
+
border: 1px dashed #ccc;
|
94
|
+
border-left: none;
|
95
|
+
border-right: none;
|
96
|
+
padding: 4px 0;
|
97
|
+
margin-bottom: 20px;
|
98
|
+
}
|
99
|
+
#answers .answer {
|
100
|
+
padding: 15px 0;
|
101
|
+
border-top: 1px dashed #ccc;
|
102
|
+
}
|
103
|
+
#answers .answer:first-child {
|
104
|
+
border-top: none;
|
105
|
+
}
|
106
|
+
#answers .answer cite {
|
107
|
+
color: #aaa;
|
108
|
+
}
|
109
|
+
#answers .answer cite a {
|
110
|
+
font-style: normal;
|
111
|
+
margin-left: 5px;
|
112
|
+
}
|
113
|
+
#answers .answer .text {
|
114
|
+
margin-top: 10px;
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
/* answer question form */
|
119
|
+
form#new_rostra_answer {
|
120
|
+
padding-top: 30px;
|
121
|
+
border-top: 2px solid #ccc;
|
122
|
+
margin-top: 50px;
|
123
|
+
}
|
124
|
+
form#new_rostra_answer .field label {
|
125
|
+
font-size: 16px;
|
126
|
+
}
|
127
|
+
form#new_rostra_answer .field label abbr {
|
128
|
+
display: none;
|
129
|
+
}
|
130
|
+
form#new_rostra_answer .field textarea {
|
131
|
+
height: 150px;
|
132
|
+
width: 100%;
|
133
|
+
margin: 10px 0;
|
134
|
+
}
|
135
|
+
|
136
|
+
/*voting styles*/
|
137
|
+
.vote_wrapper, .answers_vote_wrapper {
|
138
|
+
text-align: center;
|
139
|
+
width: 43px;
|
140
|
+
font-size: 22px;
|
141
|
+
font-weight: bold;
|
142
|
+
line-height: 12px;
|
143
|
+
float: left;
|
144
|
+
margin: -5px 0 0 -55px;
|
145
|
+
}
|
146
|
+
.vote {
|
147
|
+
background-image: url("vote_arrows.png");
|
148
|
+
background-repeat: no-repeat;
|
149
|
+
width: 43px;
|
150
|
+
height: 43px;
|
151
|
+
display: block;
|
152
|
+
text-indent: -999px;
|
153
|
+
background-color: transparent;
|
154
|
+
}
|
155
|
+
|
156
|
+
.vote:hover{
|
157
|
+
background-color: transparent;
|
158
|
+
}
|
159
|
+
|
160
|
+
.vote.up{
|
161
|
+
background-position: 0 0;
|
162
|
+
}
|
163
|
+
|
164
|
+
.vote.up:hover, .vote.up.selected{
|
165
|
+
background-position: 0 -43px;
|
166
|
+
}
|
167
|
+
|
168
|
+
.vote.down{
|
169
|
+
background-position: 0 -129px;
|
170
|
+
}
|
171
|
+
|
172
|
+
.vote.down:hover, .vote.down.selected{
|
173
|
+
background-position: 0 -86px;
|
174
|
+
}
|
175
|
+
|
176
|
+
|
177
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
.button,
|
2
|
+
input[type="submit"] {
|
3
|
+
margin: 10px 0;
|
4
|
+
display: inline-block;
|
5
|
+
background: #eee;
|
6
|
+
background: -moz-linear-gradient(top, #eee 0%, #ccc 100%);
|
7
|
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#eee), to(#ccc));
|
8
|
+
border: 1px solid #ccc;
|
9
|
+
border-bottom: 1px solid #bbb;
|
10
|
+
-moz-border-radius: 3px;
|
11
|
+
-webkit-border-radius: 3px;
|
12
|
+
border-radius: 3px;
|
13
|
+
color: #333 !important;
|
14
|
+
font-family: "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
|
15
|
+
font-size: 11px;
|
16
|
+
font-weight: bold;
|
17
|
+
line-height: 1;
|
18
|
+
padding: 8px;
|
19
|
+
text-align: center;
|
20
|
+
text-shadow: 0 1px 0 #eee;
|
21
|
+
text-decoration: none !important;
|
22
|
+
width: auto;
|
23
|
+
}
|
24
|
+
|
25
|
+
.button:hover,
|
26
|
+
input[type="submit"]:hover {
|
27
|
+
background: #ddd;
|
28
|
+
background: -moz-linear-gradient(top, #ddd 0%, #bbb 100%);
|
29
|
+
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ddd), to(#bbb));
|
30
|
+
border: 1px solid #bbb;
|
31
|
+
border-bottom: 1px solid #999;
|
32
|
+
cursor: pointer;
|
33
|
+
text-shadow: 0 1px 0 #ddd;
|
34
|
+
}
|
35
|
+
|
36
|
+
.button:active,
|
37
|
+
input[type="submit"]:active {
|
38
|
+
border: 1px solid #aaa;
|
39
|
+
border-bottom: 1px solid #888;
|
40
|
+
-moz-box-shadow: inset 0 0 5px 2px #aaa, 0 1px 0 0 #eee;
|
41
|
+
-webkit-box-shadow: inset 0 0 5px 2px #aaa, 0 1px 0 0 #eee;
|
42
|
+
box-shadow: inset 0 0 5px 2px #aaa, 0 1px 0 0 #eee;
|
43
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
form .hint {
|
2
|
+
display: block;
|
3
|
+
margin-top: -10px;
|
4
|
+
color: #aaa;
|
5
|
+
}
|
6
|
+
form label abbr {
|
7
|
+
color: green;
|
8
|
+
font-size: 18px;
|
9
|
+
font-weight: normal;
|
10
|
+
}
|
11
|
+
form .field {
|
12
|
+
position: relative;
|
13
|
+
width: 550px;
|
14
|
+
}
|
15
|
+
form label {
|
16
|
+
font-weight: bold;
|
17
|
+
display: block;
|
18
|
+
margin-bottom: 3px;
|
19
|
+
}
|
20
|
+
form input,
|
21
|
+
form textarea {
|
22
|
+
margin-bottom: 15px;
|
23
|
+
padding: 3px;
|
24
|
+
width: 100%;
|
25
|
+
}
|
26
|
+
textarea {
|
27
|
+
line-height: 18px;
|
28
|
+
height: 300px;
|
29
|
+
}
|
30
|
+
span.error {
|
31
|
+
color: red;
|
32
|
+
position: absolute;
|
33
|
+
top: 5px;
|
34
|
+
right: -5px;
|
35
|
+
}
|
36
|
+
.field_with_errors input,
|
37
|
+
.field_with_errors textarea {
|
38
|
+
background: #fde6e4;
|
39
|
+
border: 1px solid red;
|
40
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
* { margin: 0; padding: 0; }
|
2
|
+
body { font-size: 12px; font-family: Helvetica, Verdana, Arial, sans-serif; color: #333; }
|
3
|
+
ul { list-style: disc inside; padding-left: 10px; }
|
4
|
+
ol { list-style: decimal inside; padding-left: 10px; }
|
5
|
+
li { list-style-position: outside;}
|
6
|
+
a { outline: none; color: green;}
|
7
|
+
a:hover { background-color: green; color: white; text-decoration: none;}
|
8
|
+
a img { border: none; background: none; }
|
9
|
+
img { vertical-align: middle; }
|
10
|
+
table { border-collapse: collapse; }
|
11
|
+
p { margin-top: 10px; }
|
12
|
+
textarea { resize: none; }
|
13
|
+
input:focus, textarea:focus { outline: none; }
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Rostra
|
2
|
+
class AnswersController < ApplicationController
|
3
|
+
load_and_authorize_resource
|
4
|
+
before_filter :fetch_question
|
5
|
+
|
6
|
+
def vote
|
7
|
+
if current_user.voted_for?(@answer) && params[:vote_type] == 'up'
|
8
|
+
current_user.clear_votes(@answer)
|
9
|
+
elsif current_user.voted_against?(@answer) && params[:vote_type] == 'down'
|
10
|
+
current_user.clear_votes(@answer)
|
11
|
+
else
|
12
|
+
current_user.vote_exclusively_for(@answer) if params[:vote_type] == 'up'
|
13
|
+
current_user.vote_exclusively_against(@answer) if params[:vote_type] == 'down'
|
14
|
+
end
|
15
|
+
|
16
|
+
respond_to do |format|
|
17
|
+
format.html { redirect_to question_path(@question, anchor: "rostra_answer_#{@answer.id}") }
|
18
|
+
format.js
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def create
|
23
|
+
if @answer.save
|
24
|
+
redirect_to question_path(@question, anchor: "rostra_answer_#{@answer.id}")
|
25
|
+
else
|
26
|
+
redirect_to question_path(@question, anchor: 'new_rostra_answer')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def edit
|
31
|
+
end
|
32
|
+
|
33
|
+
def update
|
34
|
+
if @answer.update_attributes(params[:answer])
|
35
|
+
redirect_to question_path(@question, anchor: "rostra_answer_#{@answer.id}")
|
36
|
+
else
|
37
|
+
render :edit
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def fetch_question
|
44
|
+
@question = Question.find(params[:question_id])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Rostra
|
2
|
+
class ApplicationController < ActionController::Base
|
3
|
+
|
4
|
+
helper_method :user_logged_in?
|
5
|
+
|
6
|
+
rescue_from CanCan::AccessDenied do |exception|
|
7
|
+
after_access_denied
|
8
|
+
end
|
9
|
+
|
10
|
+
# Check if a user is logged in
|
11
|
+
#
|
12
|
+
def user_signed_in?
|
13
|
+
current_user
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Override <tt>cancan</tt>'s default class of <tt>Ability</tt> to user <tt>Rostra::Ability</tt>.
|
19
|
+
#
|
20
|
+
def current_ability
|
21
|
+
@current_ability ||= Rostra::Ability.new(current_user)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Override this method to if finer control over what happens when <tt>cancan</tt> denies access.
|
25
|
+
#
|
26
|
+
def after_access_denied
|
27
|
+
redirect_to root_url, alert: "You don't have access to view this page"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Rostra
|
2
|
+
class QuestionsController < ApplicationController
|
3
|
+
load_and_authorize_resource
|
4
|
+
|
5
|
+
def vote
|
6
|
+
if current_user.voted_for?(@question) && params[:vote_type] == 'up'
|
7
|
+
current_user.clear_votes(@question)
|
8
|
+
elsif current_user.voted_against?(@question) && params[:vote_type] == 'down'
|
9
|
+
current_user.clear_votes(@question)
|
10
|
+
else
|
11
|
+
current_user.vote_exclusively_for(@question) if params[:vote_type] == 'up'
|
12
|
+
current_user.vote_exclusively_against(@question) if params[:vote_type] == 'down'
|
13
|
+
end
|
14
|
+
|
15
|
+
respond_to do |format|
|
16
|
+
format.html { redirect_to @question }
|
17
|
+
format.js
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def index
|
22
|
+
@questions = Question.order('created_at desc')
|
23
|
+
@user = current_user
|
24
|
+
end
|
25
|
+
|
26
|
+
def show
|
27
|
+
@answers = @question.answers
|
28
|
+
end
|
29
|
+
|
30
|
+
def new
|
31
|
+
end
|
32
|
+
|
33
|
+
def edit
|
34
|
+
end
|
35
|
+
|
36
|
+
def create
|
37
|
+
if @question.save
|
38
|
+
redirect_to questions_path, notice: 'Your question has been posted.'
|
39
|
+
else
|
40
|
+
render :new
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def update
|
45
|
+
if @question.update_attributes(params[:question])
|
46
|
+
redirect_to @question, notice: 'Question was successfully updated.'
|
47
|
+
else
|
48
|
+
render :edit
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def destroy
|
53
|
+
@question.destroy
|
54
|
+
redirect_to questions_url
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rostra
|
2
|
+
class Ability
|
3
|
+
include CanCan::Ability
|
4
|
+
|
5
|
+
attr_reader :user
|
6
|
+
|
7
|
+
def initialize(user)
|
8
|
+
@user = user || User.new
|
9
|
+
|
10
|
+
if logged_in?
|
11
|
+
can :manage, Question, :user => user
|
12
|
+
can :manage, Answer, :user => user
|
13
|
+
can [:vote_up, :vote_down], Question
|
14
|
+
can [:vote_up, :vote_down], Answer
|
15
|
+
end
|
16
|
+
|
17
|
+
can :read, :all
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def logged_in?
|
23
|
+
! user.new_record?
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Rostra
|
2
|
+
class Question < ActiveRecord::Base
|
3
|
+
|
4
|
+
belongs_to :user
|
5
|
+
has_many :answers
|
6
|
+
|
7
|
+
acts_as_taggable
|
8
|
+
acts_as_voteable
|
9
|
+
|
10
|
+
validates :title, :presence => true, :uniqueness => true, :length => { :minimum => 15 }
|
11
|
+
validates :user, :presence => true
|
12
|
+
validates :tag_list, :presence => true
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Rostra
|
2
|
+
class Vote < ActiveRecord::Base
|
3
|
+
|
4
|
+
scope :for_voter, lambda { |*args| where(["voter_id = ? AND voter_type = ?", args.first.id, args.first.class.name]) }
|
5
|
+
scope :for_voteable, lambda { |*args| where(["voteable_id = ? AND voteable_type = ?", args.first.id, args.first.class.name]) }
|
6
|
+
scope :recent, lambda { |*args| where(["created_at > ?", (args.first || 2.weeks.ago)]) }
|
7
|
+
scope :descending, order("created_at DESC")
|
8
|
+
|
9
|
+
belongs_to :voteable, :polymorphic => true
|
10
|
+
belongs_to :voter, :polymorphic => true
|
11
|
+
|
12
|
+
attr_accessible :vote, :voter, :voteable
|
13
|
+
|
14
|
+
|
15
|
+
# Comment out the line below to allow multiple votes per user.
|
16
|
+
validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id]
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/app/models/vote.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
class Vote < ActiveRecord::Base
|
2
|
+
|
3
|
+
scope :for_voter, lambda { |*args| where(["voter_id = ? AND voter_type = ?", args.first.id, args.first.class.name]) }
|
4
|
+
scope :for_voteable, lambda { |*args| where(["voteable_id = ? AND voteable_type = ?", args.first.id, args.first.class.name]) }
|
5
|
+
scope :recent, lambda { |*args| where(["created_at > ?", (args.first || 2.weeks.ago)]) }
|
6
|
+
scope :descending, order("created_at DESC")
|
7
|
+
|
8
|
+
belongs_to :voteable, :polymorphic => true
|
9
|
+
belongs_to :voter, :polymorphic => true
|
10
|
+
|
11
|
+
attr_accessible :vote, :voter, :voteable
|
12
|
+
|
13
|
+
|
14
|
+
# Comment out the line below to allow multiple votes per user.
|
15
|
+
validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id]
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Rostra</title>
|
5
|
+
<%= stylesheet_link_tag "rostra/application" %>
|
6
|
+
<%= javascript_include_tag "rostra/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body id="<%= controller_name %>" class="<%= action_name %>">
|
10
|
+
<div id="page_wrap">
|
11
|
+
<nav>
|
12
|
+
<%= link_to 'Recent questions', questions_path %>
|
13
|
+
<%= link_to 'Logout', main_app.destroy_user_session_path, :method => :post %>
|
14
|
+
|
15
|
+
</nav>
|
16
|
+
<% flash.each do |name, msg| %>
|
17
|
+
<%= content_tag :div, msg, id: "flash_#{name}", class: 'flash' %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<%= yield %>
|
21
|
+
</div>
|
22
|
+
</body>
|
23
|
+
</html>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<% @answer ||= @question.answers.build %>
|
2
|
+
|
3
|
+
<%= simple_form_for [@question, @answer], validate: true do |f| %>
|
4
|
+
<%= f.hidden_field :user_id, value: current_user.id %>
|
5
|
+
<%= f.hidden_field :question_id, value: @question.id %>
|
6
|
+
<%= f.input :text, label: 'Answer this question' %>
|
7
|
+
<%= f.submit @answer.new_record? ? 'Answer' : 'Update' %>
|
8
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
$('.answers_vote_wrapper').replaceWith('<%= escape_javascript(render(:partial => 'rostra/shared/answers_votes', locals: {answer: @answer})) %>');
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<%= simple_form_for @question, validate: true do |f| %>
|
2
|
+
<%= f.hidden_field :user_id, value: current_user.id %>
|
3
|
+
<%= f.input :title %>
|
4
|
+
<%= f.input :details %>
|
5
|
+
<%= f.input :tag_list, label: 'Tags', hint: 'Separate tags with commas' %>
|
6
|
+
<%= f.submit "Post your question" %>
|
7
|
+
<% end %>
|
@@ -0,0 +1,45 @@
|
|
1
|
+
<h1>Recent Questions</h1>
|
2
|
+
|
3
|
+
<%= render 'rostra/shared/sidebar' %>
|
4
|
+
|
5
|
+
<div id="page_content">
|
6
|
+
<div id="questions">
|
7
|
+
<% if @questions.empty? %>
|
8
|
+
<h3>No questions have been asked.</h3>
|
9
|
+
|
10
|
+
<% else %>
|
11
|
+
|
12
|
+
<% @questions.each do |question| %>
|
13
|
+
<div class="question">
|
14
|
+
<h3 class="title"><%= link_to question.title, question %></h3>
|
15
|
+
<cite>
|
16
|
+
Asked by <%= question.user.name %>
|
17
|
+
<%= link_to 'edit', edit_question_path(question) if can? :manage, question %>
|
18
|
+
</cite>
|
19
|
+
<div class="text">
|
20
|
+
<% if question.details.length > 250 %>
|
21
|
+
<%= simple_format(
|
22
|
+
truncate(question.details, length: 250) +
|
23
|
+
link_to("view more", question, class: "view_more")
|
24
|
+
) %>
|
25
|
+
|
26
|
+
<% else %>
|
27
|
+
<%= simple_format(question.details) %>
|
28
|
+
<% end %>
|
29
|
+
</div>
|
30
|
+
<div class="timestamp"><%= time_ago_in_words(question.updated_at) %> ago</div>
|
31
|
+
<div class="tags">
|
32
|
+
Tags:
|
33
|
+
<% question.tags.each do |tag| %>
|
34
|
+
<%= link_to tag, "" %>
|
35
|
+
<% end %>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
<% end %>
|
39
|
+
|
40
|
+
<% end %>
|
41
|
+
</div><!-- questions -->
|
42
|
+
|
43
|
+
|
44
|
+
</div><!--page_content-->
|
45
|
+
|