Adam Kolkman
Adam Kolkman

Reputation: 132

Ruby on Rails app MVC Design decision

Right now I'm working on an app that takes an inventory file (csv), parses it, and persists it to a database. At first I was going to create an Inventory class that would parse the csv and also do business logic on the constructed Inventory database. But now it seems like I should be separating those concerns. The csv file will update daily, so parsing is an important part of the app.

So I'm now creating a class Feed to handle the inventory feed (.csv), parse it, check for errors, and maybe even act as a json endpoint. The only thing is, there is no need for this class to persist its data, the Inventory class will do that. So if this whole Feed class is a good idea, how would I include it in a Rails project? As a controller without a model? As a .rb file in /lib ? Should I be using rake tasks for this? Other options?

Upvotes: 1

Views: 101

Answers (3)

Nikolai Manek
Nikolai Manek

Reputation: 1008

Here is how I would do it:

  1. Create a rake task which reads the CSV file and writes it to the db

  2. Install https://github.com/javan/whenever/blob/master/README.md

  3. Configure whenever to execute your job in the desired interval

  4. Add business logic if needed to the rake task or other "job" style class

  5. Have your app simply read the results from the model

You could also use Resque or Sidekiq but that might be overkill for one simple task.

This way you have a "set and forget" setup and you can set whenever gem to take a look ever X minutes or so and don't have to worry about timing when the CSV comes in.

Clean separation of concerns and fully automated. Never read a CSV from a controller triggered action as you will block the thread for no good reason...

Upvotes: 1

Maksim Gladkov
Maksim Gladkov

Reputation: 3079

I think you should make class Feed in models folder. You can include several helper modules to add necessary functionality to the class.

class Feed
    include ActiveModel::Validations # support validation

    attr_accessor :file_name

    validates :file_name, presence: true

    def process
        if valid?
            ...
        end
    end
end

Upvotes: 1

apneadiving
apneadiving

Reputation: 115541

Feed could be an ActiveRecord model containing:

  • the file attachment (carrierwave, paperclip, never minds).
  • a status: processed or not

In your controller start a background job with the freshly created object responsible to process the file and update its status.

This way you can track all changes required and keep a history (or not, your choice to update status or destroy on success). But the point is background job sometimes fail and you need a solution for this.

As where to put the csv parsing code, I'd use a service object: since you're heavily dependant of your models I wont put this in lib (or maybe a part of the parse logic, but not the model creation)

Upvotes: 1

Related Questions