Search code examples
ruby-on-railsvirtual-attribute

Treating the file store as a column in the table


I have a Blog model of which content will be stored in a file and the remaining things will be stored in the table.

My solution for this is as below

I created a virtual attribute with getter/setter method.

def content
    File.read(file_path)
end

def content=(html)
    File.open(file_path, "w") do |file|
        file.write(html)
    end
end

But here I have a problem, I want to store html content to a file only if the record is valid, but when I say something like below in the controller

Blog.new(:content => html,:title => "Title".......)

My setter is called first before other attributes are set. Since other attributes are validated with presence true record will fail to save but still my file will be stored.

So now I want a solution where file will be created only if the record is valid and it is stored.


Solution

  • I think it might be better to use before_save and after_find callbacks here. Add accessors to the class to allow the attributes to be stored in memory when creating/updating the content. Then when you save to the database, save the content to a file. When loading records from the database, load the content from the file and store it using the same accessor

    class Post
      attr_accessor :content
      before_save :save_to_disk
      after_find :load_from_disk
    
      def save_to_disk
        File.open(file_path, "w"){ |f| f.write(content) }
      end
    
      def load_from_disk
        File.open(file_path){ |f| self.content = f.read }
      end
    
    end