diff --git a/app/controllers/admin/articles_controller.rb b/app/controllers/admin/articles_controller.rb index d6c41eb..15a0a36 100644 --- a/app/controllers/admin/articles_controller.rb +++ b/app/controllers/admin/articles_controller.rb @@ -47,7 +47,7 @@ def destroy private def find_article - @article = Article.find(params[:id]) + @article = Article[params[:id]] end end end diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb index 5a22a75..8840891 100644 --- a/app/controllers/articles_controller.rb +++ b/app/controllers/articles_controller.rb @@ -1,5 +1,6 @@ class ArticlesController < ApplicationController before_filter :find_article, :only => [:show, :edit, :update, :share] + before_filter :redirect_to_slug, :only => [:show] before_filter :create_visit, :only => [:show] skip_before_filter :authenticate, :only => [:shared, :samples] @@ -80,11 +81,7 @@ def random private def find_article - if params[:volume] && params[:issue] - @article = Article.find_by_issue_number("#{params[:volume]}.#{params[:issue]}") - else - @article = Article.find_by_id(params[:id]) - end + @article = Article[params[:id]] render_http_error(404) unless @article end @@ -108,4 +105,9 @@ def create_visit end end + def redirect_to_slug + return unless @article.slug.present? + + redirect_to article_path(@article.slug) unless params[:id] == @article.slug + end end diff --git a/app/models/article.rb b/app/models/article.rb index d432c43..7120269 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -3,7 +3,8 @@ class Article < ActiveRecord::Base belongs_to :volume belongs_to :collection - validates_presence_of :issue_number + validates_presence_of :issue_number + validates_uniqueness_of :slug, :allow_blank => true def self.in_volume(number) includes(:volume) @@ -18,6 +19,18 @@ def self.drafts where(:status => "draft") end + def self.[](key) + find_by_slug(key) || find_by_id(key) + end + + def to_param + if slug.present? + slug + else + id.to_s + end + end + def full_subject "Issue #{issue_number}: #{subject}" end diff --git a/app/views/admin/articles/_form.html.haml b/app/views/admin/articles/_form.html.haml index 9c58bb4..d47e94a 100644 --- a/app/views/admin/articles/_form.html.haml +++ b/app/views/admin/articles/_form.html.haml @@ -4,6 +4,10 @@ = f.label :subject %br = f.text_field :subject +%p + = f.label :slug + %br + = f.text_field :slug %p = f.label :published_time = f.date_select :published_time diff --git a/db/migrate/20130816174433_add_slug_to_articles.rb b/db/migrate/20130816174433_add_slug_to_articles.rb new file mode 100644 index 0000000..4a563b3 --- /dev/null +++ b/db/migrate/20130816174433_add_slug_to_articles.rb @@ -0,0 +1,5 @@ +class AddSlugToArticles < ActiveRecord::Migration + def change + add_column :articles, :slug, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index c0c32eb..358f54b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20130215174537) do +ActiveRecord::Schema.define(:version => 20130816174433) do create_table "announcements", :force => true do |t| t.text "title" @@ -43,6 +43,7 @@ t.text "issue_number" t.integer "volume_id" t.integer "collection_id" + t.string "slug" end create_table "authorization_links", :force => true do |t| diff --git a/test/integration/article_routing_test.rb b/test/integration/article_routing_test.rb new file mode 100644 index 0000000..c493211 --- /dev/null +++ b/test/integration/article_routing_test.rb @@ -0,0 +1,35 @@ +require_relative "../test_helper" + +class ArticleRoutingTest < ActionDispatch::IntegrationTest + setup do + @article = FactoryGirl.create(:article, :slug => "awesome-article") + simulated_user { register Support::SimulatedUser.default } + end + + test "by slug" do + visit "/articles/awesome-article" + + assert_content @article.subject + end + + test "by id" do + id = @article.id + visit "/articles/#{id}" + + assert_content @article.subject + + assert_current_path "/articles/awesome-article" + end + + test "with invalid slug" do + visit "/articles/i-do-no-exist" + + assert_equal 404, page.status_code + end + + test "with invalid id" do + visit "/articles/99999" + + assert_equal 404, page.status_code + end +end diff --git a/test/integration/edit_article_test.rb b/test/integration/edit_article_test.rb new file mode 100644 index 0000000..0f9b26f --- /dev/null +++ b/test/integration/edit_article_test.rb @@ -0,0 +1,27 @@ +require_relative '../test_helper' + +class EditArticleTest < ActionDispatch::IntegrationTest + setup do + simulated_user { register Support::SimulatedUser.default } + @article = FactoryGirl.create(:article, :slug => "awesome-article") + User.first.update_attribute(:admin, true) + end + + test "can edit articles with slugs" do + visit edit_admin_article_path(@article.slug) + + click_button "Update Article" + + assert_current_path article_path(@article) + end + + test "can edit articles without slugs" do + @article.update_attribute(:slug, nil) + + visit edit_admin_article_path(@article.id) + + click_button "Update Article" + + assert_current_path article_path(@article) + end +end