diff --git a/Gemfile b/Gemfile index 05d558a..708250c 100644 --- a/Gemfile +++ b/Gemfile @@ -20,6 +20,8 @@ gem 'slim-rails' gem 'bootstrap-sass' gem 'simple_form' +gem 'friendly_id', '~> 5.1.0' + gem 'bcrypt' gem 'sdoc', '~> 0.4.0', group: :doc diff --git a/Gemfile.lock b/Gemfile.lock index 016bbb5..b076b4f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -125,6 +125,8 @@ GEM ruby_parser (~> 3.1, > 3.1.0) sexp_processor (~> 4.4) formatador (0.2.5) + friendly_id (5.1.0) + activerecord (>= 4.0.0) globalid (0.3.5) activesupport (>= 4.1.0) guard (2.12.8) @@ -375,6 +377,7 @@ DEPENDENCIES dotenv-rails factory_girl_rails faker + friendly_id (~> 5.1.0) guard-rspec jbuilder (~> 2.0) jquery-rails diff --git a/app/controllers/subcreddits_controller.rb b/app/controllers/subcreddits_controller.rb index 256a6f1..7174794 100644 --- a/app/controllers/subcreddits_controller.rb +++ b/app/controllers/subcreddits_controller.rb @@ -45,6 +45,6 @@ class SubcredditsController < ApplicationController end def set_subcreddit - @subcreddit = Subcreddit.find_by_slug(params[:id]) + @subcreddit = Subcreddit.friendly.find(params[:id]) end end diff --git a/app/models/subcreddit.rb b/app/models/subcreddit.rb index b9a3c63..f057639 100644 --- a/app/models/subcreddit.rb +++ b/app/models/subcreddit.rb @@ -1,28 +1,25 @@ -RESERVED_SLUGS = %w(new edit) - class Subcreddit < ActiveRecord::Base + extend FriendlyId + belongs_to :owner, class_name: 'User' has_many :posts + friendly_id :name, use: :slugged + attr_accessor :closed - before_save :set_slug before_save :set_closed_at validates :name, presence: true, format: /\A(?! )[a-z0-9 ]*(?_changed? + # end + # } + # + # FriendlyId uses Rails's `parameterize` method to generate slugs, but for + # languages that don't use the Roman alphabet, that's not usually sufficient. + # Here we use the Babosa library to transliterate Russian Cyrillic slugs to + # ASCII. If you use this, don't forget to add "babosa" to your Gemfile. + # + # config.use Module.new { + # def normalize_friendly_id(text) + # text.to_slug.normalize! :transliterations => [:russian, :latin] + # end + # } +end diff --git a/db/migrate/20150716045747_create_friendly_id_slugs.rb b/db/migrate/20150716045747_create_friendly_id_slugs.rb new file mode 100644 index 0000000..770f626 --- /dev/null +++ b/db/migrate/20150716045747_create_friendly_id_slugs.rb @@ -0,0 +1,15 @@ +class CreateFriendlyIdSlugs < ActiveRecord::Migration + def change + create_table :friendly_id_slugs do |t| + t.string :slug, :null => false + t.integer :sluggable_id, :null => false + t.string :sluggable_type, :limit => 50 + t.string :scope + t.datetime :created_at + end + add_index :friendly_id_slugs, :sluggable_id + add_index :friendly_id_slugs, [:slug, :sluggable_type] + add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], :unique => true + add_index :friendly_id_slugs, :sluggable_type + end +end diff --git a/db/migrate/20150716050055_add_index_to_subcreddit_slug.rb b/db/migrate/20150716050055_add_index_to_subcreddit_slug.rb new file mode 100644 index 0000000..6776bb4 --- /dev/null +++ b/db/migrate/20150716050055_add_index_to_subcreddit_slug.rb @@ -0,0 +1,5 @@ +class AddIndexToSubcredditSlug < ActiveRecord::Migration + def change + add_index :subcreddits, :slug, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index f582bac..7aa24e6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,20 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150714200610) do +ActiveRecord::Schema.define(version: 20150716050055) do + + create_table "friendly_id_slugs", force: :cascade do |t| + t.string "slug", null: false + t.integer "sluggable_id", null: false + t.string "sluggable_type", limit: 50 + t.string "scope" + t.datetime "created_at" + end + + add_index "friendly_id_slugs", ["slug", "sluggable_type", "scope"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type_and_scope", unique: true + add_index "friendly_id_slugs", ["slug", "sluggable_type"], name: "index_friendly_id_slugs_on_slug_and_sluggable_type" + add_index "friendly_id_slugs", ["sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_id" + add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type" create_table "posts", force: :cascade do |t| t.integer "user_id" @@ -36,6 +49,7 @@ ActiveRecord::Schema.define(version: 20150714200610) do end add_index "subcreddits", ["owner_id"], name: "index_subcreddits_on_owner_id" + add_index "subcreddits", ["slug"], name: "index_subcreddits_on_slug", unique: true create_table "user_sessions", force: :cascade do |t| t.integer "user_id" diff --git a/spec/models/subcreddit_spec.rb b/spec/models/subcreddit_spec.rb index 987c34d..064d221 100644 --- a/spec/models/subcreddit_spec.rb +++ b/spec/models/subcreddit_spec.rb @@ -1,5 +1,7 @@ require 'rails_helper' +require 'securerandom' + describe Subcreddit, type: :model do let(:subcreddit) { build(:subcreddit) } @@ -15,12 +17,6 @@ describe Subcreddit, type: :model do expect(subcreddit).to be_valid end - it 'should sluggify the name' do - subcreddit.name = 'Testing Spaces 1' - subcreddit.save - expect(subcreddit.slug).to eq('testing_spaces_1') - end - it 'should set closed_at if closed is true and closed_at is nil' do Timecop.freeze do subcreddit.closed = '1' @@ -92,15 +88,8 @@ describe Subcreddit, type: :model do expect(duplicate).to be_invalid end - it 'should not allow duplicate names (case insensitive)' do - original = create(:subcreddit) - duplicate = build(:subcreddit, name: original.name.upcase) - - expect(duplicate).to be_invalid - end - - it 'should not use a reserved keyword' do - subcreddit.name = 'New' + it 'should not allow a slug with a UUID' do + subcreddit.slug = "test-#{SecureRandom.uuid}" expect(subcreddit).to be_invalid end