I have the following class that I'd like access to within certain controllers in my app:
class Spreedly
include HTTParty
base_uri 'https://example.com/api/1234'
basic_auth 'user', 'xyz124'
headers 'Accept' => 'text/xml'
headers 'Content-Type' => 'text/xml'
format :xml
end
Where would I put that class so that I could then access it in a controller like Spreedly.post(xyz)?
You can simply place this in a file called spreedly.rb in the lib/ directory. It'll be auto-loaded by rails and will be available for use.
True, but there is nothing stopping you from putting it in your app/models directory.
And to me it seems a better place to put it - because your are accessing data like any other model in your app, and when you reference Spreedly.post etc from your controllers another programmer will naturally (imho) look in the app/models directory first before the /lib ..
Anything that needs to be referenced in multiple places or anything that is large, I put in lib. If it is tiny, and if it is used in a single model, I will put it in the same model file.
I'm very interested in testing this custom classes quickly, just as if you we're testing any other model. One problem I faced by trying to put the file under /lib, is that Spork or Zeus will reboot the environment to run the test.
I love the idea of storing the file under /lib, but this is making my continuos testing process slower. I ended up putting it under app/models.
If there was a way to test a a file under /lib more easily, that'd be great.
Related
I have something defined as a app >model > something.rb
class Something < ActiveRecord::Base
end
Now I want to call this from somewhere else.
I read that w/o rails running, there is an ActiveRecord error(calling ActiveRecord as some unnamed variable);
How can I call , say
Something.create (x => y) from a helper file?
There is a nice blogpost which gives you the rundown on how to connect to ActiveRecord without rails.
In a nutshell, you need to require your AR files, and then call establish_connection with the correct configuration:
Active record works just fine and dandy without rails, but it needs
things to be just so. To start, get the gem and add it to your
gemfile. Next, make all of your classes inherit from AR like so:
Then you need to require it in the right places. Initially I was
requiring AR from the file containing each class, but this was messy
and confusing. So instead I moved to a solution that I’d seen Avi put
into the CLI playlister project, which helped clean things up: I made
a separate file for the entire environment called environment.rb, and
made it do all of the requiring for my min-app. The environment file
requires AR, points AR to the database file to use, and then requires
each of the models. Then the classes don’t have to require anything.
Where should I put my simple classes that are not models (they don't represent any data) and provides only some functionality?
Like for example:
class FileUploader
def save_uploaded_file(filename, tempfile)
path = Rails.root.join('public', 'uploads', filename)
File.open(path, 'wb+') do |file|
file.write(tempfile.read)
end
end
end
What this does is just simply copies file to predefined place.
Do I must to place this under models? Or do Rails have some other location more suitable for those kind of classes? I tried to put in lib before, but it was just too much of the pain as Rails cached those files inside lib directory (edited config to not cache files, but it still cached inside lib).
So, I placed those files in models but testing becomes very painful (I'm just starting Rails, maybe I'm doing something wrong with the tests) as rake spits out errors about not having set up a test database (I want to test classes that are not related to database in any form or shape - why do I need to set up a database?).
I've taken to adding app/lib to some of my projects to accommodate this, but there's also the new Rails 4 concerns locations like app/models/concerns or app/controllers/concerns depending on where this sort of thing is used.
You're right that it's best to avoid putting non-model classes in app/models.
For service-type objects I put them in app/services.
For model-type objects I put them in app/models. I do not think it is necessary to inherit from ActiveRecord to be considered a model.
I think your object classifies as a 'service object' since it is designed to wrap the service of uploading a file, it isn't really a domain object like a model would be.
If i need to add (project specific) classes to my controler in rails, what is the correct way/place to put and "include" them/there .rb files? (quotes for: not the ruby keyword include)
I am new to rails, and did not find the correct way. LIB sounds like for more public libraries and - what I have learned - is not reloaded per default in dev mode.
sure, I could put all in controler.rb, but ...
the anser for me:
First: there are no rules, if you keep in mind (or learn like me) the rails rules:
NameOfCla -> name_of_cla(.rb) <-- not using class as word for clearence
name your class how you like:
class ExtendCon #<--- not using controller here for clearence
....
put it in a file extend_con.rb, wait for the path explaination, please. if you named your class 'MYGreatThing' it will be 'm_y_great_thing' (never testet that), so avoid chineese charachters
if your controller uses
#letssee=ExtendCon.new
rails learns that class and file (extend_con) on its own. i still did not figure out if a server restart is needed. (the first time)
choose the path to put the file: (I preferre Daves way) app/myexten or what you like, making it 'app' specific and still distquishes to standard rails 'things'
if you are not lasy like me (i put it in app/ontrollers)
put the path you have choosen into
config/application.rb like (comments are there to find it)
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/app/controllers)
config.autoload_paths += %W(#{config.root}/app/myexten)
this one workes for me in all modes including "developer" and i did not need to put "my own" things in app/lib
It depends.
I tend to put library code used explicitly (e.g., instantiated, injected, etc. into app-level artifacts) into app/xxx where xxx signifies the "type" of thing, like decorators, services, etc.
Magic stuff tends to end up in lib, like monkey patches, architectural-level artifacts, and so on.
Code anywhere can be added to the autoload paths, required automatically by an initializer, etc.
Rails 4 comes with an internal directory for controllers called concerns. You could try using that.
app/controlls/concerns
If you have concerns/foo_bar.rb, you include it as follows:
class FooController < ApplicationController
include FooBar
end
Models also have their own concerns directory. I find this approach useful, and it can be applied to Rails 3. You just have to add the directories to your load paths.
I'm working on a Rails app that uses an engine. I'm using an initializer to configure one of my engine's controllers so that it will trigger an action in the host app. The code looks something like this:
# config/initializers/my_engine.rb
MyEngine::SomeController.after_filter proc {
# Do something in the host app
}, :only => :update
This works fine in production, but in development mode, the proc is only called on the first request. This is because the classes are getting reloaded and this configuration is lost, because it was stored in a class variable. (For example, MyEngine::SomeController is reloaded from the file it's in, and since the after_filter isn't declared there, it isn't added back on.)
Some Rails background
In development mode, Rails uses the following load strategy:
Code in the app directory is reloaded on each request, on the assumption that you're actively changing it.
Code in the lib directory, along with config/initializer files, are loaded once, when the application boots.
Initializer files are generally used for configuring gems. In the past, gems have mostly had code in the lib directory, so running their configuration once was sufficient.
How engines change things
However, Rails engines have code in the app directory: controllers, models, etc. These files are reloaded in development mode on each request. Therefore, configuration like my example above is lost.
Enter to_prepare
Rails provides config.to_prepare specifically to solve this problem: it run once in production, and on every request in development.
For example, we have this in application.rb, which works fine:
config.to_prepare do
# set up class variables (after_filters, etc)
end
However, if I have to put all my engines' configuration in application.rb, this defeats the point of config/initializers in keeping things organized.
So, for any configuration of classes in my engines' app directories, I want to put that code in files under config/initializers.
Here are my questions.
I'm unclear how to get config into scope in an initializer file. I'm thinking it would be Rails.application.config. Is that right?
Can I add add multiple to_prepare blocks? I'm afraid that calling it multiple times will overwrite previous blocks.
Update
As #Frederick Cheung mentioned, Rails.application.config.to_prepare does work in config/initializer files, and one can use as many of these as needed in the various files; each call appends its block to an array, so nothing is overwritten.
So the solution to this problem is:
# config/initializers/my_engine.rb
Rails.application.config.to_prepare do
MyEngine::SomeController.after_filter proc {
# Do something in the host app
}, :only => :update
end
One thing that still seems odd: I expected the to_prepare block to be called on every request in development mode, but instead it seems to be called randomly every 3rd request or so. I added block:
Rails.application.config.to_prepare do
Rails.logger.info "Running the prepare block!"
end
... restarted my app, and refreshed the page nine times. I only saw the message on the 1st, 5th, 7th and 9th requests. I'm not sure what explains this behavior, but it does explain why my code without the to_prepare worked intermittently in development.
You can add as many to_prepare blocks as you want - when you do config.to_prepare, Rails is doing (in configuration.rb in railties)
def to_prepare(&blk)
to_prepare_blocks << blk if blk
end
and then iterates over those blocks handing them over to ActionDispatch::Reloader, where to_prepare is implemented using ActiveSupport::Callbacks (i.e. the same thing that is used for before_save and so on). Multiple to_prepare blocks are fine.
Currently it looks like Rails iterates over to_prepare_blocks after reading application initialisers so adding to Rails.application.configuration.to_prepare should work. You may prefer to use ActionDispatch::Reloader.to_prepare.
There's nothing to stop you from doing initializer code in a file that lives in app/models.
for example
class MyClass
def self.run_me_when_the_class_is_loaded
end
end
MyClass.run_me_when_the_class_is_loaded
MyClass.run_me... will run when the class is loaded .... which is what we want, right?
Not sure if its the Rails way.... but its extremely straightforward, and does not depend on the shifting winds of Rails.
My goal is to generate a directory of static html, javascript, and image files within my Rails (3) app, driven by ERB templates. For example, as a developer I might want to generate/update these files:
#{Rails.root}/public/products/baseball.html
#{Rails.root}/public/products/football.js
..from the following template files:
#{Rails.root}/product_templates/baseball.html.erb
#{Rails.root}/product_templates/football.js.erb
Ideally the templates would have access to my app's Rails environment (including URL helpers, view helpers, partials, etc.).
What's the latest and greatest way to accomplish this?
I experimented with a custom Rails generator, but found that I needed to write custom logic for skipping non-ERB files, substituting file names, etc. There must be a better way.
I'm not sure what you are trying to do exactly, that may help provide better answers, but here is some useful information:
You can call into erb directly, some information on that is here, which have probably already been doing:
http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html
For the list of template files an easy Dir.glob should be able to help find the specific files easily and loop through them:
http://ruby-doc.org/core/classes/Dir.html#M000629
The tricky part I wouldn't know how to advise you on is getting access to the helpers and other things Rails provides. The helpers that you write are just modules, so you could mix those in, something similar might be possible with the built-in rails helpers.
This is interesting and related but doesn't directly answer your question, since its uses the Liquid templating engine instead of ERB, but otherwise, it does some of the static site generation you are talking about:
https://github.com/mojombo/jekyll
This is how I accomplished something similar. It accepts source and destination directories, wipes out the destination, then processes the source directory, either ERB-processing files and placing them in the destination or simply copying them (in the case of on-ERB files). It would need to be modified to handle recursively processing a directory.
I invoke it from a rake task like so:
DirectoryGenerator.new.generate(Rails.root.join('src'), Rails.root.join('public', 'dest'))
class DirectoryGenerator
include Rails.application.routes.url_helpers
include ActionView::Helpers::TagHelper
default_url_options[:host] = 'www.example.com'
def generate(source, destination)
FileUtils.rmtree(destination)
FileUtils.mkdir_p(destination)
Dir.glob(File.join(source, '*')).each do |path|
pathname = Pathname.new(path)
if pathname.extname == '.erb'
File.open(destination.join(pathname.basename.sub(/\.erb$/, '')), 'w') do |file|
file.puts(ERB.new(File.read(path)).result(binding))
end
else
FileUtils.cp(pathname, File.join(destination, pathname.basename))
end
end
end
end
Have you looked into Rails templates?
http://m.onkey.org/rails-templates for instance..
Not sure what you are getting at exactly.. are you trying to generate client sites by providing a few parameters.. that the end goal?