简体   繁体   中英

Where should I put my own classes that are not models/views/controllers?

In my app, I want to define a class that my models, views, and controllers will use. My thought was to create a new directory, app/lib , where I created:

# /app/lib/donut.rb
class Donut
  def initialize(sprinkle_color)
    @sprinkle_color = sprinkle_color
  end

  def sprinkle_color
    @sprinkle_color
  end
end

Now this works fine, but when I added test/lib , those tests are not run when I run rake test . I can run rake test:all which works, but feels wrong.

Is this the right place to put classes, and if so, how do I get them into the tests?

PS Why do I need a class like this? Of course, I'm not actually creating a donut. It's a class that takes a set of arguments, and there are many models that have these objects. In addition, there are views that take these objects, or arrays of these objects. Finally, there is code that operates on lists of these objects, and I've put that code as static methods into this class.

Create folders in the app directory for custom classes but try to make them as descriptive as possible. For eg I use custom classes to properly format json for ajax loading datatables so the classes are located in app>datatables eg

app>datatables>users_datatable.rb

class UsersDatatable
  [...]
end

And so in the controller action I can render a view using the custom class:

respond_to  do |format|
  format.html
  format.json { render json: UsersDatatable.new(view_context, current_user) }
end

Here's another example that uses prawn pdf to generate a pdf view:

app>pdfs>quote_pdf.rb

class QuotePdf < Prawn::Document
  [...]
end

And in the controller action:

respond_to do |format|
  format.html
  format.pdf do
    pdf = QuotePdf.new(view_context, @quote)
    send_data pdf.render, filename: "quote_#{@quote.number}.pdf",
                          type: "application/pdf",
                          disposition: "inline"
  end
end

Testing is easy. Since the custom classes I use are associated with other resources I include the tests with them. ie with users, quotes. However you can create separate tests as you have done to be able to run them separately.

I would argue that app>lib is not descriptive enough. If possible, try and be more specific on what the custom class is actually doing.

I really dislike using "lib". Instead, I recommend using common design patterns as top-level directory names for other POROs. I do this in Rails projects. So that I have something like this:

app/
  models/
  controllers/
  services/
  policies/
  validators/

Etc.

A great showcase of this can be found here: http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM