RoR TagLib-Ruby: How to set ID3 tags in DB

1k views Asked by At

Thanks for any help in advance.

I would like to set id3 tag data in my database as attributes for my model MasterSong. Specifically, title, artist, and album.

create_table :master_songs do |t|
  t.integer :user_id
  t.has_attached_file :m_song
 **- t.string :title
 - t.string :artist
 - t.string :album**

In my model I'm using a callback to set the data before the object(master_song) is saved.

before_save :set_id3_tags_in_database

def set_id3_tags_in_database
TagLib::MPEG::File.open(self.m_song.path) do |file|
   tag = file.id3v2_tag
   tag.title
   tag.album
   tag.artist
end
  self.update_attributes(:title => tag.title,
  :artist => tag.artist,
  :album => tag.album)
end

I'm pretty sure my syntax is the problem. The object seems to hit an error

undefined method `title' for nil:NilClass with an infinite loop

Controller create action is normal:

 def create
   @master_song = current_user.master_songs.build(params[:master_song])

   respond_to do |format|
    if @master_song.save
     format.html { redirect_to @master_song, notice: 'Master song was successfullycreated.' }
   end

What am I doing wrong here? Update: def set_id3_tags z = TagLib::MPEG::File.open(self.m_song.path) do |file| tag = file.id3v2_tag tag.title end self.update_attribute!(:title => z) end

get stack level too deep error now.

2

There are 2 answers

2
Jches On BEST ANSWER

OK! So I did it, after playing and playing and playing.

def set_id3_tags
z = TagLib::MPEG::File.open(self.m_song.path) do |file|
 unless tag.nil?
  tag = file.id3v2_tag
  self.title = tag.title
  self.album = tag.album
  self.artist = tag.artist

  else
end

end

Adding the if title.nil? did it for me. Callbacks are weird but definitely valuable. Hope this helps someone else.

3
robinst On

First of all, ensure that self.m_song.path is the right path and that a file exists there.

Next, the following line:

tag = file.id3v2_tag

Doesn't create a tag when the file does not yet have a tag, and therefore may return nil. Set the optional parameter "create" to true for it to automatically create a tag:

tag = file.id3v2_tag(true)

Ok, then it appears that you would want to save the tag data after you have set it. For that you have to explicitly call save, like this (notice the last line of the block):

TagLib::MPEG::File.open(self.m_song.path) do |file|
   tag = file.id3v2_tag(true)
   # set data
   file.save
end

For more information, please see the documentation here: http://rubydoc.info/gems/taglib-ruby/frames