Exploring the Magic of Rails and ActiveRecord

For this project, I explored the magic of Rails and the power of the Spotify API to create Jamlist, a collaborative playlist creator that allows groups or communities to create and edit Spotify playlists together. Here I’ll dive into some ActiveRecord and Rails magic that can make your models robust and flexible.

Jesse Gan
3 min readAug 27, 2020

Jamlist — Collaborative Playlists Made Better

Jamlist Homepage

The idea behind Jamlist is to allow groups of friends or communities to be able to share music. Spotify is great for listening to and browsing music but lacks the social aspects for groups to have an interactive music experience. Through Jamlist, you can create groups, join other groups, create playlists, search tracks from Spotify and add them to your playlists. Everything you do on Jamlist syncs to real Spotify playlists where you can jam out with your group!

Example of Playlist

Some features to be added later:

  • Invite code links
  • Track suggestion and voting system
  • Listening to tracks on the website
  • Liking and disliking tracks in playlist
  • Tons of JavaScript to make the UX smoother (!!!)

Digging into the Magic of Rails

Powering Jamlist is a list of models built through ActiveRecord. Here are 3 tips and tricks that I used to make my models and associations more robust:

#1 — Using the dependent option with associations

class Group < ApplicationRecord
has_many :members, dependent: :destroy
has_many :playlists, dependent: :destroy
end
class User < ApplicationRecord
has_many :members, dependent: :destroy
end
class Playlist < ApplicationRecord
has_many :playlist_tracks, dependent: :destroy
end
class Track < ApplicationRecord
has_many :playlist_tracks, dependent: : destroy
end

Nested records often times should only exist if its parent resource exists. In the example above, Members require a User and a Group, Playlists require a Group, and PlaylistTracks require a Playlist and a Track. In those cases, if the parent record is destroyed, the child should also be destroyed or else there would be members in a Group without a User being connected to it.

The dependent: :destroy option tells ActiveRecord that if the parent record is destroyed, the child object is destroyed as well. These options are chained as well so if a Group is destroyed, its playlists are destroyed and the PlaylistTracks in that playlist are also destroyed. No more having to worry about unassociated records in your database.

#2 — Adding a default_scope

default_scope { order(name: :asc) }

If you find yourself ordering a record in the same ways every time you need to display them in your views, using a default scope will make your code more DRY. Here, I created a default scope for the Group record that sorts them alphabetically by name. This means that every time I call Group.all, the ActiveRecord collection will be automatically sorted by name.

The magic of rails also works through other queries. user.groups will return the list of a User’s Groups sorted by name without needing to explicitly order it, saving you more lines of code.

#3 — Using merge to filter through another association

class Group < ApplicationRecord
def admin_users
self.users.merge(self.admins)
end
end

With any has-many-through associations, you may need to filter a record’s association by an attribute in their join table. In my case, I wanted to filter a Group’s Users by the admin attribute in their join table called Members. What merge does is it returns the intersection of the two sets of records (read more here). So in this example, it takes the collection of the Group’s Users with self.users and then finds the intersection with the collection of the Group’s Members that are admins with self.admins.

See More…

You can watch a video walkthrough here and check out the GitHub Link.

--

--

Jesse Gan

Software Engineer helping companies bring new products to life. Follow along with my coding journey here!