I'm following along with Yehuda's example on how to build a custom renderer for Rails 3, according to this post: http://www.engineyard.com/blog/2010/render-options-in-rails-3/
I've got my code working, but I'm having a hard time figuring out where this code should live. Right now, I've got my code stuck right inside of my controller file. Doing this, everything works. When I move the code to the lib folder, though, I have explicitly 'require' my file in the controller that needs the renderer or it won't work. Yes, the file gets loaded when it sits in the lib folder, automatically. but the code to add the renderer isn't working for some reason, until I do a require on it.
where should I put my code to add the renderer and mime type, so that rails 3 will pick it up and register it for me, without me having to manually require the file in my controller?
I'd put it in an initializer, or in lib and require it in application controller.
In Jose Valim's book, Crafting Rails applications, this is the first chapter. He creates a PDF mime type & renderer using Prawn.
In his example, he created lib/pdf_renderer.rb with this:
require "action_controller"
Mime::Type.register "application/pdf", :pdf
Since lib is no longer autoloaded, you'll either have to autoload lib or specifically require this file where you want to use it.
An initializer might also be appropriate here.
i did some more digging around on this based on the suggestions here.
i found a "mime_types" initializer was already in our code base. i think this is created by rails, by default. it had several commented out examples in it. so i added my custom mime type to this file.
i also decided to use an initializer for the custom renderer so that it's automatically loaded and available with the app. this way i don't have to remember to include it in the various places i need it. i can just respond_to the format i created, and send the data down.
thanks for the tips, everyone.
Related
I am currently coding an application in Ruby that does some simple external API calls to Soundcloud's API.
I have developed a bunch of code inside a single .rb file and want to put this into the rails architecture. This Ruby file has the following classes:
class SoundcloudUser
class SoundcloudQuery
class SoundcloudFollowers
Currently I understand that I can put these classes into seperate .rb files, and then just put them into the /models/ folder which then gives me the ability to call these classes from elsewhere in my rails application (using require/include).
My question is simply, is this the correct way to go about this? I am familiar with rails, but I am new to transferring a Ruby developed project into the rails format. I tried searching best practices for this in the Ruby style guide but I didn't really find anything.
On a side note - I wanted to also create another class that acts as a ?service? wherein in checks my local database if an entry already exists in the database, and if not, then it will query new data. My side-question here would be similar - where would this .rb file for this 'service' live?
I hope I explained my question clearly enough, if not, I am happy to add some clarifications. Thank you for your time!
If in Rails, you can put them in either lib/ or somewhere in the main app directory. For example, you can create app/services and put them inside there, and when you restart the Rails server you should be able to call SoundcloudUser (provided you name them app/services/soundcloud_user.rb.
I always look at the Gitlab source code for this. It's a gigantic Rails app but look at this file: https://github.com/gitlabhq/gitlabhq/blob/master/app/services/gravatar_service.rb. Because it's inside an app/services (any name actually), GravatarService can be called from anywhere in Rails. If you want to have some namespacing, you have to put it in app/services/soundcloud/user.rb or lib/soundcloud/user.rb and name the class Soundcloud::User.
For the class that acts as a service, it seems like it orchestrates the logic of "check if (song?) exists, else scrape. Some people put it in a model class, I'd probably put it in a service class a la the Gitlab source code. Hope I helped.
I am building XML files inside my application and I would like to validate the generated XML's format against an XSD file. I am not sure where shall I put this schema.xsd file so that it can be easily retrieved inside an RSpec example.
I was thinking about putting it inside spec/support, but I am not sure about it.
I would suggest spec/fixtures, since it is part of your test suite, it's somewhat static data and it can be accessed easily via fixture_path (you can set any other *_path helper in your spec_helper file if you wish to).
I've ended up putting my .xsd file in spec/support/schemas/; it felt more natural for me, since it is a support file.
If I have a ruby class which I want to use it as a library in a rails app, how (what folder) should I include it in the application?
I want to use the class in my controller. Do I just simply use 'require' to include the class?
You can just do a require in the controller assuming the file is somewhere in your load path. I follow a few simple strategies:
If its a class that adds plugin like behavior but isnt quite large enough to write a plugin, I just put it in config/initializers since they the lib is in the load path and all the files are required for you on startup. No additional requires needed.
The other option is to put them in the lib directory and just require them when you need them. If you are using rails 3, the lib directory is not a part of the load path and you will need to add it.
I'd recommend throwing it in the lib folder - you then can require it from your config/environment.rb file and if I recall correctly, that should be all you need to do.
I've seen docs/websites show that custom validators should go in a /lib or /lib/validators directory of a project. I've found (by reading an answer to another post) that they only seem to work in config/initializers. Does anyone know, or have a pointer to official documentation that shows where custom validators should live?
If you place your custom validators in app/validators they will be automatically loaded without needing to alter your config/application.rb file.
If you add this to your /config/application.rb file:
config.autoload_paths += %W["#{config.root}/lib/validators/"]
Then Rails will automatically load your validators on start up (just like /config/initializers/), but you keep the clean structure of having your validators in one nice, well named spot.
lib/validators seems by far the cleanest. However you may need to load them in before your models, so probably from an initializer.
Here's the official docs about custom validations. AFAIK its a good practice to keep them in the relevant models.
I want to add a library that I wrote to a Rails app (and to other Rails apps later). I tried putting it in /lib which seemed logical...
[RAILS_ROOT]/lib/my_lib/the_main_file.rb
[RAILS_ROOT]/lib/my_lib/some_other_file.rb
Then...
require 'my_lib/the_main_file'
That works fine.
But is that a great way to do it?
Now I have to put that require everywhere I want to call the library.
I thought about putting the require in an initializer but that seems kind of weird.
What do people usually do about this?
Using an initializer may look weird when you have a single file to include, but sometimes I have many files that I want to add, and end up using an intializer that only includes stuff. It's actually pretty neat.
I'm not sure about the "best practices"(tm) or anything, but we do a similar thing for our project as well. The library is in lib, and the require in an initializer (app_config.rb in our case). This seems like a good way to do things, and hasn't bitten us in the butt thus far :) Hope that helps.
I usually wrap up my stuff in classes. If you add config.autoload_paths += %W(#{config.root}/lib) to your application.rb then any reference to a missing constant will result in an attempt to autoload it, i.e just using MyClass.new will make it try to load `lib/my_class.rb'.
Have a look at Best way to load module/class from lib folder in Rails 3?