user2045764
user2045764

Reputation: 175

My user.rb model is too cluttered and I am not sure how to simplify it

I am a little new to the Ruby language and Rails framework but I really want to add some features to a registration page. Although this code works, I need to make it simpler and less cluttered but I am not sure where to begin here.

class User < ActiveRecord::Base
  has_many :posts
  has_many :comments
  has_many :votes

  has_secure_password validations: false

  validates :username, presence: true, on: :create, length: {minimum: 5}, uniqueness: true
  validates :username, presence: true, on: :update, length: {minimum: 5}, uniqueness: true

  validates :password, presence: true, on: :create, length: {minimum: 5}
  validates :password, presence: true, on: :update, length: {minimum: 5}

  validates_format_of :username, on: :create, with: /\A[A-Za-z\d_]+\z/, message: "can only include letters and numbers"
  validates_format_of :username, on: :update, with: /\A[A-Za-z\d_]+\z/, message: "can only include letters and numbers"
end

I want my users to be able to only include letters and numbers with no spaces for both their username and password. Also, they both need to be a minimum of 5 characters. Right now, only characters and numbers with no spaces works with my create action but it does not work for my update action. Any help would be greatly appreciated.

Upvotes: 0

Views: 241

Answers (2)

user229044
user229044

Reputation: 239311

This is a very small model.

That said, there is lots of room for improvement, as you've introduced a ton of clutter.

  • There is no reason to specify on: :create and on: :update for two duplicate validations. If you just omit the on:, then it will automatically apply to both create and update:

    # Validate on both create AND update
    validates :username, presence: true, length: { minimum: 5 }, uniquess: true 
    
  • You can merge your format validation into the first validates line, and simplify the regex dramatically down to just \A\w*\z, since \w matches A-Za-z0-9_:

    validates :username, presence: true, length: { minimum: 5 }, uniquess: true,
                         format: { with: /\A\w*\z/ }
    
  • You should move the validation message into config/locals/en.yml instead of having it directly in the model. User-facing strings have absolutely no place hard-coded in your source code, they should always reside in a localization file. See the i18n docs.

    # config/locals/en.yml
    activerecord:
      errors:
        models:
          user:
            attributes:
              username:
                too_short: "Your username is too short"
                too_long: "Your username is too long"
    

All told, your model should look like this (note you should be specifying a maximum length validation as well as a minimum):

class User < ActiveRecord::Base
  has_many :posts
  has_many :comments
  has_many :votes

  has_secure_password validations: false

  validates :username, presence: true,
                       length: { within: 5..20 },
                       uniqueness: true,
                       format: { with: /\A\w*\z/ }

  validates :password, presence: true,
                       length: { within: 5..20 }
end

Upvotes: 1

MZaragoza
MZaragoza

Reputation: 10111

class User < ActiveRecord::Base
  has_many :posts
  has_many :comments
  has_many :votes

  has_secure_password validations: false

  validates :username, presence: true, length: {minimum: 5}, uniqueness: true

  validates :password, presence: true, length: {minimum: 5}

  validates_format_of :username, with: /\A[A-Za-z\d_]+\z/, message: "can only include letters and numbers"
end

if you do something like this

Upvotes: 0

Related Questions