Chat with Thomas | Profile

Welcome to the Modern Web Design.

Lecture 4–Devise and Tagging Gems

Hi there, welcome back to the Ruby on Rails course.

In this lecture we use 2 gems to enhance the Link Redirection.

Gems are plugins in Ruby. Rails itself is a gem. Different modules of Rails are also gems, like ActiveRecord, ActiveSupport, ActiveCable, Turbolinks. They are individual plugins. For example, the Turbolinks can be used without Rails. ActiveSupport could also be loaded without Rails dependency.

We will use the Devise gem for user authentication and act_as_taggable_on gem for tagging.

Sometimes, we don’t know what gem to use, there are some indicators:

  1. Is it still actively maintained and developed?
  2. Are there many people using this gem?
  3. Who is the creator behind the gem?
  4. How is it compare to other gems with similar functionality?

For gem comparison, we can use Ruby Toolbox. The ruby toolbox site groups different gems and compare their activities and popularity.

Here is the video that add the Devise gem for user authentication in the Link Redirection example.

 

Here are some recaps on the code we used in the video:

Installation:

In Gemfile:

gem 'devise'

In shell:

$ bundle
$ rails generate devise:install
$ rails generate devise User
$ rake db:migrate

In LinksController:

before_action :authenticate_user!, except: :redirect

Change all Link. to current_user.links.. (Except the redirect action)

User class:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
        
  has_many :links
end

Link class:

class Link < ActiveRecord::Base
  belongs_to :user  
    
  validates :short_url, uniqueness: true  
    
  # ... existing code
    
end

Here is the video that add the act_as_taggable_on gem to add tagging functionalities to links.

 

Here are some recaps on the code we used in the video:

Installation:

In Gemfile:

gem 'acts-as-taggable-on', '~> 3.4'

In shell:

$ bundle
$ rake acts_as_taggable_on_engine:install:migrations
$ rake db:migrate

Link model class.

class Link < ActiveRecord::Base

  acts_as_taggable    
    
  # ... existing code
    
end

app/views/links/_form.html.erb file:

<div class="field">
  <%= f.label :tag_list %><br>
  <%= f.text_field :tag_list %>
</div>

For displaying the URL for the short URL:

@host = request.host

Customize tag parser in lib/my_parser.rb:

class MyParser < ActsAsTaggableOn::GenericParser
  def parse
    ActsAsTaggableOn::TagList.new.tap do |tag_list|
      tag_list.add @tag_list.split /,|\s/
    end
  end
end

Configure gem to use my_parser:

# /config/initializers/act_as_taggable_on.rb

# if want auto load, use this:
# config.autoload_paths << Rails.root.join('lib')

require Rails.root.join 'lib', 'my_parser.rb'

ActsAsTaggableOn.default_parser = MyParser

For tags searching in controller:

if params[:tag].nil?
  @links = current_user.links.all
else 
  @links = current_user.links.tagged_with(params[:tag])
end

For printing the tag list with a link.

module LinksHelper
  
  def tag_list_with_link(tag_list)
    html = ""
    
    tag_list.each do |tag| 
      html += link_to(tag, tag_path(tag)) + " "
    end 
    return html.html_safe
  end
  
end

Updated links/index.html.erb file:

<% if params[:tag].nil? %>
  <h1>Links</h1>
<% else %>
  <h1>Links with #<%= params[:tag] %></h1>
<% end %>

<%= link_to 'New Link', new_link_path, class:'button' %>

<ul class='link-list'>
  <% @links.each do |link| %>
    <li>
      <p><%= link_to link.original_url, link %></p>
      <p><input readonly value="http://<%= @host %>/<%= link.short_url %>"></p>
      <p><small>Visited <%= link.visited_count %> times.</small></p>
      
      <p><%= tag_list_with_link(link.tag_list) %></p>
    </li>
  <% end %>
</ul>

Some extra CSS styles:

.button {
  display: inline-block;  
  padding: 0.5em 1em;
  background: #efefef;
}

ul.link-list {
  padding: 0;
  margin: 0;
  list-style: none;
}


.link-list li {
  border-bottom: 1px dashed #ccc;
  
  padding: 2em 0;
}
.link-list li:first-child {
  border-top: 1px dashed #ccc;
}

.link-list input {
  width: 100%;
}