Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ gem 'rubocop-rails', require: false
gem 'bootsnap', '>= 1.4.4', require: false
gem 'devise'
gem 'slim-rails'


group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
Expand Down
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ GEM
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.6.3)
language_server-protocol (3.17.0.3)
launchy (2.5.2)
Expand Down Expand Up @@ -312,6 +316,7 @@ DEPENDENCIES
devise
factory_bot_rails (~> 4.8.2)
jbuilder (~> 2.7)
jquery-rails
launchy
listen (~> 3.3)
pg (~> 1.4)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ Think-over-flow project

* ...

Init 6 Integrational Testing
Init 7 Ajax in Rails
1 change: 1 addition & 0 deletions app/assets/stylesheets/common.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.hidden { display: none }
24 changes: 13 additions & 11 deletions app/controllers/answers_controller.rb
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
class AnswersController < ApplicationController
before_action :authenticate_user!, only: %i[create]
before_action :authenticate_user!, only: %i[create edit]

def new; end

def create
@answer = question.answers.build(answer_params)
if @answer.save
redirect_to question_path(question), notice: 'Your answer successfully added!'
else
render '/questions/show', locals: {question: question}
end
@answer = question.answers.create(answer_params)
end

def update
answer.update(answer_params)
@question = answer.question
@other_answers = @question.other_answers
end

def destroy
# binding.pry
question = answer.question
if current_user.author_of?(answer)
answer.destroy
redirect_to question_path(question)
# redirect_to question_path(question)
else
redirect_to question_path(question), notice: 'Answer can be deleted only by author.'
# redirect_to question_path(question), notice: 'Answer can be deleted only by author.'
end
end

private

def question
@question ||= Question.find(params[:answer][:question_id])
@question ||= Question.find(params[:question_id])
end

def answer
@answer ||= Answer.find(params[:id])
end

def answer_params
params.require(:answer).permit(:question_id, :body).merge(author_id: current_user.id)
params.require(:answer).permit(:body).merge(author_id: current_user.id)
end
end
9 changes: 5 additions & 4 deletions app/controllers/questions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ def index
end

def show
@answers = question.answers
@best_answer = question.best_answer
@other_answers = question.other_answers
@answer = Answer.new
end

def new; end
Expand All @@ -15,7 +17,6 @@ def edit; end

def create
@question = Question.new(question_params)
@question.save
if @question.save
redirect_to question, notice: 'Your question successfully created.'
else
Expand All @@ -34,9 +35,9 @@ def update
def destroy
if current_user.author_of?(question)
question.destroy
redirect_to questions_path
# redirect_to questions_path
else
redirect_to question_path(question), notice: 'Question can be deleted only by author.'
# redirect_to question_path(question), notice: 'Question can be deleted only by author.'
end
end

Expand Down
2 changes: 2 additions & 0 deletions app/javascript/packs/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
require("jquery")
require("utilities/answers")

Rails.start()
Turbolinks.start()
Expand Down
9 changes: 9 additions & 0 deletions app/javascript/utilities/answers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
$(document).on('turbolinks:load', function(){
console.log('Hello! I am a message from answers.js!')
$('.answers').on('click', '.edit-answer-link', function(event){
event.preventDefault();
$(this).hide();
var answerId = $(this).data('answerId');
$('form#edit-answer-' + answerId).removeClass('hidden');
})
});
5 changes: 5 additions & 0 deletions app/models/question.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
class Question < ApplicationRecord
has_many :answers, dependent: :destroy
belongs_to :best_answer, class_name: 'Answer', optional: true
belongs_to :author, class_name: 'User'

validates :title, :body, presence: true

def other_answers
answers.where.not(id: best_answer&.id)
end
end
18 changes: 12 additions & 6 deletions app/views/answers/_answer.html.slim
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
tr
td
= answer.body
td
- if current_user&.author_of?(answer)
= button_to 'Удалить ответ', answer_path(answer), method: :delete, data: { confirm: 'Вы действительно хотите удалить ответ?'}
. id="answer-block-#{answer.id}"
p= "[ Ответ ]: #{answer.body} (id = #{answer.id})"
- if current_user&.author_of?(answer)
p=link_to 'Edit', '#', class: 'edit-answer-link', data: {answer_id: answer.id }
= form_with model: answer, class: 'hidden', local: false, html: { id: "edit-answer-#{answer.id}"} do |f|
= f.label :body, 'Your answer'
= f.text_area :body
= f.submit 'Save'
p = button_to 'Удалить ответ', answer_path(answer), method: :delete, remote: true, data: { confirm: 'Вы действительно хотите удалить ответ?'}
- if current_user&.author_of?(answer.question)
span = button_to 'Выбрать ответ лучшим', answer_path(answer), method: :delete, remote: true, data: { confirm: 'Вы действительно хотите удалить ответ?'}
hr
8 changes: 8 additions & 0 deletions app/views/answers/_answers_list.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.best_answer
- if best_answer.present?
= render 'answers/best_answer', resource: best_answer

.other_answers
- if other_answers.present?
= render 'answers/other_answers', collection: other_answers

2 changes: 2 additions & 0 deletions app/views/answers/_best_answer.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
p Лучший ответ: '#{resource.body}'
hr
4 changes: 4 additions & 0 deletions app/views/answers/_other_answers.html.slim
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- if collection.present?
h3 Остальные ответы
- collection.each do |answer|
= render answer
6 changes: 6 additions & 0 deletions app/views/answers/create.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
$('.answer-errors').html('<%= render 'shared/errors', resource: @answer %>');
<% if @answer.persisted? %>
$('.answers .other_answers').append('<%= j render @answer %>');
$('.new-answer #answer_body').val('');
<% end %>

1 change: 1 addition & 0 deletions app/views/answers/destroy.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$('<%= "#answer-block-#{@answer.id}" %>').remove()
5 changes: 5 additions & 0 deletions app/views/answers/update.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$('.answer-errors').html('<%= render 'shared/errors', resource: @answer %>');
<% if !@answer.errors.present? %>
$('.answers .other_answers').html('<%= j render 'answers/other_answers', collection: @other_answers %>');
<% end %>

4 changes: 2 additions & 2 deletions app/views/questions/_question.html.slim
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
tr
tr id="question-row-#{question.id}"
td
= question.title
td
= question.body
td
= link_to 'смотреть ответы', question_path(question)
- if current_user&.author_of?(question)
p= button_to 'Удалить вопрос', question_path(question), method: :delete, data: { confirm: 'Вы действительно хотите удалить вопрос?'}
p= button_to 'Удалить вопрос', question_path(question), method: :delete, remote: true, data: { confirm: 'Вы действительно хотите удалить вопрос?'}
1 change: 1 addition & 0 deletions app/views/questions/destroy.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$('<%= ".questions-list tr#question-row-#{@question.id}" %>').remove()
6 changes: 3 additions & 3 deletions app/views/questions/index.html.slim
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
p= link_to 'Ask question', new_question_path

- if @questions.present?
table
table class='questions-list'
tr
th Заголовок вопроса
th Текст вопроса
th Опции
= render @questions
- else
p Вопросы еще не созданы.

p= link_to 'Ask question', new_question_path
2 changes: 1 addition & 1 deletion app/views/questions/new.html.slim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= render 'shared/errors', resource: @question

= form_with model: @question, url: questions_path do |f|
= form_with model: @question, url: questions_path, local: false do |f|
= f.label :title
= f.text_field :title, name: "question[title]"
= f.label :body
Expand Down
49 changes: 24 additions & 25 deletions app/views/questions/show.html.slim
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
= render 'shared/errors', resource: @answer
h1= question.title
p= question.body

hr
- if @answers.present?
h2 Ответы
table
tr
th Ответ
th Опции
= render @answers
- else
p Ответов еще не создано

h1= "Заголовок: #{question.title}"
p= "Тело вопроса: #{question.body}"

h2 Полученные ответы
hr
.answers
= render 'answers/answers_list', best_answer: @best_answer, other_answers: @other_answers
br
.answer-errors
= render 'shared/errors', resource: @answer
- console

h2 Знаете ответ? помогите пользователю!
p
- if user_signed_in?
p Форма ответа на вопрос
= form_with model: [question, @answer], class: 'new-answer', local: false do |f|
= f.label :body
= f.text_area :body, name: "answer[body]"
= f.submit 'Add answer'
- else
p
= link_to "Авторизуйтесь", new_user_session_path
| , чтобы иметь возможность дать ответ на вопрос

- if user_signed_in?
= form_with model: @answer, url: answers_path do |f|
= f.label :body
= f.text_area :body, name: "answer[body]"
= f.hidden_field :question_id, value: question.id, name: "answer[question_id]"
= f.submit 'Add answer'
- else
p
= link_to "Авторизуйтесь", new_user_session_path
| , чтобы иметь возможность дать ответ на вопрос
p
hr
= link_to "Назад к списку вопросов", questions_path
18 changes: 9 additions & 9 deletions bin/webpack
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#!/usr/bin/env ruby

ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development'
ENV['NODE_ENV'] ||= 'development'
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
ENV["NODE_ENV"] ||= "development"

require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
Pathname.new(__FILE__).realpath)
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)

require 'bundler/setup'
require "bundler/setup"

require 'webpacker'
require 'webpacker/webpack_runner'
require "webpacker"
require "webpacker/webpack_runner"

APP_ROOT = File.expand_path('..', __dir__)
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::WebpackRunner.run(ARGV)
end
18 changes: 9 additions & 9 deletions bin/webpack-dev-server
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#!/usr/bin/env ruby

ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development'
ENV['NODE_ENV'] ||= 'development'
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
ENV["NODE_ENV"] ||= "development"

require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
Pathname.new(__FILE__).realpath)
require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)

require 'bundler/setup'
require "bundler/setup"

require 'webpacker'
require 'webpacker/dev_server_runner'
require "webpacker"
require "webpacker/dev_server_runner"

APP_ROOT = File.expand_path('..', __dir__)
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::DevServerRunner.run(ARGV)
end
2 changes: 1 addition & 1 deletion config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Application < Rails::Application

# set time zone of application
config.time_zone = 'Moscow'

# Configuration for the application, engines, and railties goes here.
#
# These settings can be overridden in specific environments using the files
Expand Down
8 changes: 6 additions & 2 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
Rails.application.routes.draw do
devise_for :users

devise_scope :user do
get '/users/sign_out' => 'devise/sessions#destroy'
end
resources :questions
resources :answers

resources :questions do
resources :answers, shallow: true
end

root to: 'questions#index'
end
8 changes: 8 additions & 0 deletions config/webpack/environment.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
const { environment } = require('@rails/webpacker')

const webpack = require('webpack')
environment.plugins.prepend('Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery'
})
)

module.exports = environment
5 changes: 5 additions & 0 deletions db/migrate/20241022205417_add_best_answer_id_to_questions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddBestAnswerIdToQuestions < ActiveRecord::Migration[6.1]
def change
add_column :questions, :best_answer_id, :integer
end
end
Loading