Grayscale profile picture

Patrique Ouimet

Developer

Ruby on Rails Exploration Part 2

Dec 4, 2018

Introduction

Part 2! This is an overview of things I've learnt while working on my side project Anon Forum in Ruby on Rails.

Today's topics:

  • Custom Validation
  • Pagination

Custom Validation

There's a few ways to setup custom validation most of which is documented here Performing Custom Validations. The documentation is complete but a little difficult for me to digest so here's how I did it:

app/validators/bad_word_validator.rb

class BadWordValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 90.minutes)
    bad_words = cache.fetch('bad_words') do
      File.readlines('repos/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words/en').map { |a| a.strip }
    end

    value_array = ActionController::Base.helpers.strip_tags(value.to_s).gsub(/[^0-9a-z ]/i, '').split

    if value_array.length > 0
      for word in value_array
        if bad_words.include? word.downcase
          record.errors[attribute] << (options[:message] || "The #{attribute} must not contain bad words.")
          break
        end
      end
    end
  end
end

After the validation class is setup you just need to add bad_word: true as a validation requirement on the model attribute

app/models/post.rb

class Post < ApplicationRecord
  validates :title, presence: true, bad_word: true
  validates :body, presence: true, bad_word: true
  *
  *
  *
end

Pagination

Adding pagination is actually quite simple, first add the following gem to your Gemfile:

gem 'will_paginate', '~> 3.1.0'

Run bundle install, then add the following to any queries (this is a sample from my projects post controller index method)

def index
  page = params[:page].present? ? params[:page] : 1
  @posts = params[:q].present? ?
    Post.where('title LIKE ?', "%#{params[:q]}%").paginate(:page => page) :
    Post.paginate(:page => page)
end

Now in the view add this:

<%= will_paginate @posts %>

That's it! It'll display the pagination if needed, it'll show up as links labeled: Previous, 1...n, Next

Conclusion

That's it for this post! Figuring out the custom validation took me longer than it should have (likely due to how new I am to ruby/rails) but once I figured it out it all made sense. The pagination was incredibly easy to implement but I'm a little surprised it required a gem be added. If you'd like to see the progress and commits take a look here: Anon Forum.

Feel free to share! Thanks!

Gist

Comments