1
0
mirror of https://github.com/projekteuler/projekteuler.git synced 2025-12-10 08:46:41 +01:00

Show author names in problem and translation views

This commit is contained in:
Philipp Fischbeck 2019-02-05 12:00:06 +01:00
parent ddb1cfac33
commit 89a8fbba99
14 changed files with 69 additions and 7 deletions

View File

@ -13,6 +13,9 @@ class TranslationsController < ApplicationController
# POST /translations # POST /translations
def create def create
@translation = @problem.translations.new(translation_params) @translation = @problem.translations.new(translation_params)
if user_signed_in?
@translation.author = current_user
end
if @translation.save if @translation.save
redirect_to @problem, notice: t('translations.notice.successfully_created') redirect_to @problem, notice: t('translations.notice.successfully_created')
else else

View File

@ -4,6 +4,7 @@ class Problem < ApplicationRecord
delegate :title, :content, to: :translation delegate :title, :content, to: :translation
has_many :translations, inverse_of: :problem has_many :translations, inverse_of: :problem
has_many :authors, -> { where(translations: { status: [:in_use, :outdated] }).distinct }, through: :translations
self.per_page = 50 self.per_page = 50
@ -19,6 +20,10 @@ class Problem < ApplicationRecord
self.translation.in_use! self.translation.in_use!
end end
def has_anonymous_author?
translations.where(status: [:in_use, :outdated], author: nil).any?
end
def original_url def original_url
"https://projecteuler.net/problem=#{self.id}" "https://projecteuler.net/problem=#{self.id}"
end end

View File

@ -1,5 +1,6 @@
class Translation < ApplicationRecord class Translation < ApplicationRecord
belongs_to :problem, inverse_of: :translations belongs_to :problem, inverse_of: :translations
belongs_to :author, class_name: 'User', inverse_of: :translations, optional: true
enum status: [:pending, :in_use, :outdated, :declined] enum status: [:pending, :in_use, :outdated, :declined]
validates :title, :content, :problem_id, presence: true validates :title, :content, :problem_id, presence: true
@ -7,6 +8,10 @@ class Translation < ApplicationRecord
self.per_page = 50 self.per_page = 50
def has_author?
!!self.author
end
def title_is_unique_among_other_problems def title_is_unique_among_other_problems
Problem.includes(:translation).where.not(id: problem_id).each do |problem| Problem.includes(:translation).where.not(id: problem_id).each do |problem|
if problem.is_translated? and problem.title == title if problem.is_translated? and problem.title == title

View File

@ -2,6 +2,7 @@ class User < ApplicationRecord
devise :omniauthable, :rememberable devise :omniauthable, :rememberable
enum role: [:user, :admin] enum role: [:user, :admin]
has_many :translations, inverse_of: :author, dependent: :nullify
def self.from_omniauth(auth) def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user| where(provider: auth.provider, uid: auth.uid).first_or_create do |user|

View File

@ -7,6 +7,7 @@
<thead> <thead>
<tr> <tr>
<th><%= Translation.human_attribute_name(:created_at) %></th> <th><%= Translation.human_attribute_name(:created_at) %></th>
<th><%= Translation.human_attribute_name(:author) %></th>
<th><%= Translation.human_attribute_name(:problem_id) %></th> <th><%= Translation.human_attribute_name(:problem_id) %></th>
<th><%= Translation.human_attribute_name(:title) %></th> <th><%= Translation.human_attribute_name(:title) %></th>
</tr> </tr>
@ -16,6 +17,13 @@
<% @translations.each do |translation| %> <% @translations.each do |translation| %>
<tr> <tr>
<td><div data-toggle="tooltip" data-placement="left" title="<%= l translation.created_at %>"><%= time_ago_in_words(translation.created_at) %></div></td> <td><div data-toggle="tooltip" data-placement="left" title="<%= l translation.created_at %>"><%= time_ago_in_words(translation.created_at) %></div></td>
<td>
<% if translation.has_author? %>
<%= translation.author.name %>
<% else %>
<i><%= t('.anonymous') %></i>
<% end %>
</td>
<td><%= translation.problem_id %></td> <td><%= translation.problem_id %></td>
<td><%= link_to translation.title, [:admin, translation] %></td> <td><%= link_to translation.title, [:admin, translation] %></td>
</tr> </tr>

View File

@ -1,6 +1,9 @@
<% provide(:title, t('problems.show.problem_subtitle', id: @translation.problem_id)) %> <% provide(:title, t('problems.show.problem_subtitle', id: @translation.problem_id)) %>
<div class="page-header"> <div class="page-header">
<p class="text-muted">
<%= render 'shared/authors', authors: Array(@translation.author) %>
</p>
<h1><%= @translation.title %> <small><%= t 'problems.show.problem_subtitle', id: @translation.problem_id %></small></h1> <h1><%= @translation.title %> <small><%= t 'problems.show.problem_subtitle', id: @translation.problem_id %></small></h1>
</div> </div>

View File

@ -1,6 +1,9 @@
<% provide(:title, t('problems.show.problem_subtitle', id: @problem.id)) %> <% provide(:title, t('problems.show.problem_subtitle', id: @problem.id)) %>
<div class="page-header"> <div class="page-header">
<p class="text-muted">
<%= render 'shared/authors', authors: @problem.authors, has_anonymous_author: @problem.has_anonymous_author? %>
</p>
<h1><%= @problem.title %> <small><%= t '.problem_subtitle', id: @problem.id %></small></h1> <h1><%= @problem.title %> <small><%= t '.problem_subtitle', id: @problem.id %></small></h1>
</div> </div>
<%= link_to new_problem_translation_path(@problem), class: 'btn btn-default btn-sm pull-right' do %> <%= link_to new_problem_translation_path(@problem), class: 'btn btn-default btn-sm pull-right' do %>

View File

@ -0,0 +1,11 @@
<% if authors.empty? %>
Diese Übersetung wurde anonym erstellt.
<% else %>
Diese Übersetzung wurde von
<% if local_assigns[:has_anonymous_author] %>
<%= (authors.map(&:name)+Array("anonymen Nutzern")).to_sentence %>
<% else %>
<%= authors.map(&:name).to_sentence %>
<% end %>
erstellt.
<% end %>

View File

@ -12,3 +12,4 @@ de:
problem_id: Problem-ID problem_id: Problem-ID
title: Titel title: Titel
content: Inhalt content: Inhalt
author: Autor

View File

@ -11,6 +11,8 @@ de:
failure_message: "Problem-Anzahl konnte nicht aktualisiert werden! Grund: %{error}" failure_message: "Problem-Anzahl konnte nicht aktualisiert werden! Grund: %{error}"
no_problem_count: "Keine Problem-Anzahl gegeben!" no_problem_count: "Keine Problem-Anzahl gegeben!"
translations: translations:
index:
anonymous: "Anonym"
must_be_pending: "Übersetzung muss ausstehend sein, um akzeptiert oder abgelehnt zu werden!" must_be_pending: "Übersetzung muss ausstehend sein, um akzeptiert oder abgelehnt zu werden!"
show: show:
accept_translation: "Akzeptieren" accept_translation: "Akzeptieren"

View File

@ -0,0 +1,5 @@
class AddAuthorToTranslations < ActiveRecord::Migration[5.2]
def change
add_reference :translations, :author, index: true, null: true, foreign_key: {to_table: :users}
end
end

View File

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_02_03_164629) do ActiveRecord::Schema.define(version: 2019_02_04_164033) do
create_table "problems", force: :cascade do |t| create_table "problems", force: :cascade do |t|
t.datetime "created_at" t.datetime "created_at"
@ -26,6 +26,8 @@ ActiveRecord::Schema.define(version: 2019_02_03_164629) do
t.datetime "updated_at" t.datetime "updated_at"
t.integer "problem_id" t.integer "problem_id"
t.integer "status", default: 0 t.integer "status", default: 0
t.integer "author_id"
t.index ["author_id"], name: "index_translations_on_author_id"
t.index ["problem_id"], name: "index_translations_on_problem_id" t.index ["problem_id"], name: "index_translations_on_problem_id"
end end

View File

@ -22,7 +22,7 @@ class TranslationsControllerTest < ActionDispatch::IntegrationTest
assert_response :success assert_response :success
end end
test "should create translation" do test "should create translation anonymously" do
assert_difference('Translation.count') do assert_difference('Translation.count') do
post problem_translations_url(problem_id: 1, translation: @update) post problem_translations_url(problem_id: 1, translation: @update)
end end
@ -30,6 +30,16 @@ class TranslationsControllerTest < ActionDispatch::IntegrationTest
assert_redirected_to problem_path(id: 1) assert_redirected_to problem_path(id: 1)
end end
test "should create translation with user" do
login_translator
assert_difference('Translation.count') do
post problem_translations_url(problem_id: 1, translation: @update)
end
assert_redirected_to problem_path(id: 1)
assert_equal users(:translator), Translation.last.author
end
test "should not create incorrect translation" do test "should not create incorrect translation" do
assert_no_difference('Translation.count') do assert_no_difference('Translation.count') do
post problem_translations_url(problem_id: 1, translation: @incorrect) post problem_translations_url(problem_id: 1, translation: @incorrect)

View File

@ -10,6 +10,12 @@ class ActiveSupport::TestCase
fixtures :all fixtures :all
# Add more helper methods to be used by all tests here... # Add more helper methods to be used by all tests here...
end
class ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
def login_admin def login_admin
admin = users(:admin) admin = users(:admin)
sign_in admin sign_in admin
@ -19,10 +25,7 @@ class ActiveSupport::TestCase
translator = users(:translator) translator = users(:translator)
sign_in translator sign_in translator
end end
end
class ActionDispatch::IntegrationTest
OmniAuth.config.test_mode = true OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new({ OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new({
provider: :github, provider: :github,