Separating Tags in a Text Field

I’m using the awesome acts-as-taggable-on gem to implement tagging. One problem that I ran into is that when users come back to the edit page, and you use the standard coding for a field, such as this:

<%= f.text_field :tag_list %>

Then the values show, but they’re not comma separated. The big problem with that is that if the users save the form again and don’t add commas, the values will change.

For example, if the person originally had this in the tag list: “funny,exciting,premium”, then in the edit view, the field would read in as “funny exciting premium”, and if they saved, instead of three different tags, they would now have one tag: “funny exciting premium” which isn’t what anyone wants.

I found a great solution on SO by DaniG2k (assuming that the list for your tags is called “tagged list”:

<% @article.tag_types.each do |tag| %>
<div class="form-group">
  <strong><%= f.label tag.to_s.titleize %></strong><br />
  <% tag_sym = "#{tag.to_s.singularize}_list".to_sym %>
  <% tag_list = "#{tag.to_s.singularize}_list" %>
  <%= f.text_field tag_sym, value: @article.send(tag_list).to_s, :placeholder => "Comma-separated list of #{tag.to_s}", class: 'form-control' %>
</div>
<% end %>

Don’t forget to change @article to whatever model you’re working with.

Convert Displayed Time to the User’s Local Time

I wanted to show a user’s local time when displaying message, so the time made more sense to them.

I was able to do this easily using Basecamp’s Local Time gem.

The gem was built when the Asset Pipeline was used for Javascript, but it was easy to adjust. All I needed to do was run yarn install local-time.

Fixing ActionController::InvalidAuthenticityToken in Devise::SessionsController#create Error

In my Rails app, which uses the Devise gem, I was getting this error when I tried to sign in:

ActionController::InvalidAuthenticityToken in Devise::SessionsController#create

The trace:

Started POST "/users/sign_in" for 127.0.0.1 at 2017-08-03 14:18:02 +0300 Processing by Devise::SessionsController#create as HTML   Parameters: {"utf8"=>"✓", "authenticity_token"=>"mloexfy8li2dGoMwbjMEKTQ4xQMGVL5XMj+9nK/qzZnnhfwQwXNDtBnsiKvDI0CyEt83c1F+aKw2JFa16EMIgA==", "user"=>{"email"=>"foo@bar.com", "password"=>"[FILTERED]", "remember_me"=>"1"}, "commit"=>"Log in"} Can't verify CSRF token authenticity.

I could not figure out why I was getting this message for days. Then I stumbled on this post by Bob Walsh.

I was skeptical, but when I turned on the rails cache in the dev environment, and then flushed it, as Bob stated (and restarted my server), then the error disappeared.

To try to prevent flushing and toggling the cache every time, I commented out this line:

# config.session_store :cache_store

in development.rb.

Rails Device Confirmable – How to Redirect to a Different URL Than Root After Signup

I implemented the confirmable module of Rails Devise gem. After a user signs up for a new account, the default behavior is that they are redirected to the root path and shown a flash message.

However, I didn’t want to redirect my users to the root path because this page is one that I wanted to remain completely static for performance reasons. In other words, I didn’t want to show flash messages there, so I cache the same page to every user.

There was a lot of documentation on how to redirect users after signup, but it was for when confirmable wasn’t being used. There was also documentation on how to redirect users after they confirmed, but I wanted to redirect users before they confirmed.

The solution was to overwrite the Registrations controller like this (in a registrations_controller.rb file):

class Users::RegistrationsController < Devise::RegistrationsController
 
 protected

 def after_inactive_sign_up_path_for(resource)
     new_user_session_path
   end
 end

How to Make CSS Render Faster in Rails

Using Google’s PageSpeed checker, I was getting told that my CSS was preventing my pages from getting rendered faster.

I found an awesome gem, Rails Critical CSS Server that was made to help with exactly this. It’s very simple to implement and it helps you render pages faster.

What it does is load only the CSS needed to show what’s above the fold. This is all you need to do:

gem 'rails_critical_css_server'
# wrap your stylesheet link like this:
<%= RailsCriticalCssServer::Rewrite.call self do %>
  <%= stylesheet_link_tag "application" %>
<% end %>

Using Lists in TinyMCE

I’m using TinyMCE in one of my Rails apps and I had trouble today pasting in text with bullets.  TinyMCE injects paragraphs <p> in the code, so the HTML ended up looking this.

ScreenHunter 212

That ended up with the text for the bullet point being on a different line (above) the text for that bullet point.

This probably isn’t the proper way to do it, but I ended up going to the second item in the list and clicking enter.  This created a new line that wasn’t preceded with the <p>.  After that I clicked enter and created new lines in the code for each of the bullet points.

On my toolbar I don’t have the option to add lists which made it more difficult.  In the future, I may try to add plugins to handle this to see if it makes it easier.

Using ActiveAdmin to Log In As User

When you’re supporting users with issues, it can be handy to log in as them to re-create what they’re experiencing.

ActiveAdmin makes this easy to do.

When you have the gem installed, and have a app/admin/users.rb file, you just need to add this code in there:

# creates a link to sign in as the user on view user page of admin
show do |user|
  attributes_table do
  #We want to keep the existing columns
  User.column_names.each do |column|
    row column
  end
  #This is where we add a new column
  row :login_as do
    link_to "#{user.username}", login_as_admin_user_path(user), :target => '_blank'
  end
end
end

controller do
  def find_resource
   scoped_collection.friendly.find(params[:id])
  end
end

Automatically Handle N+1 Queries

I found a gem that’s helping me a bunch, so I just wanted to give it a quick mention.  After asking people for help on a N+1 query that I couldn’t figure out, one of the people recommended checking out the Goldiloader gem.

I was so impressed that the gem solved my N+1 query so easily, I decided to use it across my site.

It’s ridiculously simple to use once you have model associations defined.

All you need to do is to add the gem to your gemfile and it does the eager loading for you!  If there are places you want to avoid eager loading, you can disable Goldiloader for a query.

Improving ActiveAdmin Performance

ActiveAdmin is my favorite gem for creating admin features in Rails.  It makes it so easy to create views to monitor and manage apps.  Much of the heavy lifting is done for you by them gem.

I found that I need to do some tuning on my ActiveAdmin views to get the functionality I wanted without placing too heavy a burden on my server.

I mainly did this by doing two simple things:

(1) Specify Filters – if you don’t specify your filters, you may get far too many (and consuming too many resources when you don’t need to).  Specifying filters are easy, just go into you admin files for the resource (i.e. app > admin > article.rb), then add a line for each filter you want

filter :title
filter :created_at

(2)  Specify Index (and other) Columns – similar to above, if you don’t specify values, you may be receiving too much data.  Be more efficient by only showing what you need to see in a view.

You can do this in your admin file for a resource, simply by adding this:

index do
column :title
column :description
column :created_at
column :updated_at
end

 

 

Seeding DB with Paperclip Images with CSV

I needed to seed my app, hosted on Heroku, with new users.  Since I wanted to created a lot of the them, I wanted to CSV.  My users have avatars, so I wanted to upload those for the users as well.

Here’s how I did it:

1. I stored the original images I wanted to use for the avatars on AWS S3 (make sure that they are set with public permission to read them.

2. I created a CSV that had columns (in this order) for the users: username, email, password, password_confirmation, avatar.  In the avatar field, I put the URL of the S3 image.  I named this CSV file “user_data” and put it in the DB directory.

3. Using the answer to this Stack Overflow question, I created a file (I named user_seed.rake) in lib/tasks.  The code in the file I used was:

require ‘csv’

namespace :csv do

desc “Import CSV Data”
task :import_stuff => :environment do

csv_file_path = ‘db/user_data.csv’

CSV.foreach(csv_file_path) do |row|
User.create!({
:username => row[0],
:email => row[1],
:password => row[2],
:password_confirmation => row[3],
:avatar => URI.parse(row[4])
})
puts “Row added!”
end
end

end

4.  Run rake csv:import_stuff