{"action":"created","issue":{"url":"https://api.github.com/repos/thoughtbot/shoulda-matchers/issues/679","labels_url":"https://api.github.com/repos/thoughtbot/shoulda-matchers/issues/679/labels{/name}","comments_url":"https://api.github.com/repos/thoughtbot/shoulda-matchers/issues/679/comments","events_url":"https://api.github.com/repos/thoughtbot/shoulda-matchers/issues/679/events","html_url":"https://github.com/thoughtbot/shoulda-matchers/issues/679","id":60221119,"number":679,"title":"validate_uniqueness_of no longer works in 2.8.0","user":{"login":"doughsay","id":221693,"avatar_url":"https://avatars.githubusercontent.com/u/221693?v=3","gravatar_id":"","url":"https://api.github.com/users/doughsay","html_url":"https://github.com/doughsay","followers_url":"https://api.github.com/users/doughsay/followers","following_url":"https://api.github.com/users/doughsay/following{/other_user}","gists_url":"https://api.github.com/users/doughsay/gists{/gist_id}","starred_url":"https://api.github.com/users/doughsay/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/doughsay/subscriptions","organizations_url":"https://api.github.com/users/doughsay/orgs","repos_url":"https://api.github.com/users/doughsay/repos","events_url":"https://api.github.com/users/doughsay/events{/privacy}","received_events_url":"https://api.github.com/users/doughsay/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-03-07T19:40:36Z","updated_at":"2015-03-24T05:31:59Z","closed_at":null,"body":"A test for `validate_uniqueness_of` fails with `undefined method 'validate_uniqueness_of' for #<RSpec::ExampleGroups::User:0x007ff055b73db8>`.\r\n\r\nReverting back to 2.7.0 causes it to work.\r\n\r\nThe relevant parts of my spec are:\r\n\r\n```ruby\r\nrequire 'rails_helper'\r\n\r\nRSpec.describe User, :type => :model do\r\n  let(:user) { create(:user) }\r\n  subject { user }\r\n\r\n  describe '#save' do\r\n    it { is_expected.to validate_uniqueness_of(:email).case_insensitive }\r\n  end\r\nend\r\n```"},"comment":{"url":"https://api.github.com/repos/thoughtbot/shoulda-matchers/issues/comments/85347941","html_url":"https://github.com/thoughtbot/shoulda-matchers/issues/679#issuecomment-85347941","issue_url":"https://api.github.com/repos/thoughtbot/shoulda-matchers/issues/679","id":85347941,"user":{"login":"zxlai","id":1407908,"avatar_url":"https://avatars.githubusercontent.com/u/1407908?v=3","gravatar_id":"","url":"https://api.github.com/users/zxlai","html_url":"https://github.com/zxlai","followers_url":"https://api.github.com/users/zxlai/followers","following_url":"https://api.github.com/users/zxlai/following{/other_user}","gists_url":"https://api.github.com/users/zxlai/gists{/gist_id}","starred_url":"https://api.github.com/users/zxlai/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zxlai/subscriptions","organizations_url":"https://api.github.com/users/zxlai/orgs","repos_url":"https://api.github.com/users/zxlai/repos","events_url":"https://api.github.com/users/zxlai/events{/privacy}","received_events_url":"https://api.github.com/users/zxlai/received_events","type":"User","site_admin":false},"created_at":"2015-03-24T05:31:59Z","updated_at":"2015-03-24T05:31:59Z","body":"I also got this problem. Here is my code:\r\n\r\n``` ruby\r\n# spec/factories/user_spec.rb\r\nFactoryGirl.define do\r\n  factory :user do\r\n    sequence(:username) { |n|  \"user#{n}\" }\r\n    sequence(:email) { |n| \"person#{n}@example.com\" }\r\n    password \"123456\"\r\n  end\r\nend\r\n\r\n#spec/models/user_spec.rb\r\nRSpec.describe User, type: :model do\r\n  context \"validations\" do\r\n    subject { FactoryGirl.build(:user) }\r\n    it do\r\n      should validate_presence_of(:username)\r\n      should validate_uniqueness_of(:username).case_insensitive\r\n    end\r\n  end\r\nend\r\n\r\n#app/models/user.rb\r\n\r\nclass User < ActiveRecord::Base\r\n\r\n  extend FriendlyId\r\n  friendly_id :username, use: :slugged\r\n\r\n  # Include default devise modules. Others available are:\r\n  # :confirmable, :lockable, :timeoutable and :omniauthable\r\n  devise :database_authenticatable, :registerable,\r\n    :recoverable, :rememberable, :trackable, :validatable\r\n\r\n  attr_accessor :login\r\n\r\n  validates :username, :presence => true\r\n  validates_uniqueness_of :username, case_insensitive: true\r\n  validates_format_of :username, :with => /^[A-Za-z\\d_]+$/, :multiline => true, :message => \"can only be alphanumeric with no spaces\"\r\n\r\n  before_save { self.username = username.downcase! }\r\n\r\n  def should_generate_new_friendly_id?\r\n    if !slug? || username_changed?\r\n      true\r\n    else\r\n      false\r\n    end\r\n  end\r\n\r\n  def login=(login)\r\n    @login = login\r\n  end\r\n\r\n  def login\r\n    @login || self.username || self.email\r\n  end\r\n\r\n  def self.find_first_by_auth_conditions(warden_conditions)\r\n    conditions = warden_conditions.dup\r\n    if login = conditions.delete(:login)\r\n      where(conditions).where([\"lower(username) = :value OR lower(email) = :value\", { :value => login.downcase }]).first\r\n    else\r\n      where(conditions).first\r\n    end\r\n  end\r\nend\r\n\r\n```\r\nHere is my Guardfile\r\n``` ruby\r\nguard :rspec, cmd: \"spring rspec\" do\r\n  require \"guard/rspec/dsl\"\r\n  dsl = Guard::RSpec::Dsl.new(self)\r\n\r\n  # Feel free to open issues for suggestions and improvements\r\n\r\n  # RSpec files\r\n  rspec = dsl.rspec\r\n  watch(rspec.spec_helper) { rspec.spec_dir }\r\n  watch(rspec.spec_support) { rspec.spec_dir }\r\n  watch(rspec.spec_files)\r\n\r\n  # Ruby files\r\n  ruby = dsl.ruby\r\n  dsl.watch_spec_files_for(ruby.lib_files)\r\n\r\n  # Rails files\r\n  rails = dsl.rails(view_extensions: %w(erb haml slim))\r\n  dsl.watch_spec_files_for(rails.app_files)\r\n  dsl.watch_spec_files_for(rails.views)\r\n\r\n  watch(rails.controllers) do |m|\r\n    [\r\n      rspec.spec.(\"routing/#{m[1]}_routing\"),\r\n      rspec.spec.(\"controllers/#{m[1]}_controller\"),\r\n      rspec.spec.(\"acceptance/#{m[1]}\")\r\n    ]\r\n  end\r\n\r\n  # Rails config changes\r\n  watch(rails.spec_helper)     { rspec.spec_dir }\r\n  watch(rails.routes)          { \"#{rspec.spec_dir}/routing\" }\r\n  watch(rails.app_controller)  { \"#{rspec.spec_dir}/controllers\" }\r\n\r\n  # Capybara features specs\r\n  watch(rails.view_dirs)     { |m| rspec.spec.(\"features/#{m[1]}\") }\r\n\r\n  # Turnip features and steps\r\n  watch(%r{^spec/acceptance/(.+)\\.feature$})\r\n  watch(%r{^spec/acceptance/steps/(.+)_steps\\.rb$}) do |m|\r\n    Dir[File.join(\"**/#{m[1]}.feature\")][0] || \"spec/acceptance\"\r\n  end\r\nend\r\n```\r\n\r\nError message:\r\n```\r\n1) User validations should require unique value for username\r\n     Failure/Error: should validate_uniqueness_of(:username).case_insensitive\r\n     ActiveRecord::StatementInvalid:\r\n       PG::NotNullViolation: ERROR:  null value in column \"username\" violates not-null constraint\r\n       DETAIL:  Failing row contains (48, person1@example.com, $2a$04$N0x1xXN5ma3cIKfStEESquZ0eKo2QYS/vaOYcCFVpdI/TvYvd6tYG, null, 849af238-dac1-4d9a-96d8-f1d3de3b9e4f, null, null, null, 0, null, null, null, null, 2015-03-24 03:54:34.333744, 2015-03-24 03:54:34.333744).\r\n       : INSERT INTO \"users\" (\"username\", \"email\", \"encrypted_password\", \"slug\", \"created_at\", \"updated_at\") VALUES ($1, $2, $3, $4, $5, $6) RETURNING \"id\"\r\n     # ./spec/models/user_spec.rb:34:in `block (3 levels) in <top (required)>'\r\n     # -e:1:in `<main>'\r\n```"}}