Where to put to_xls and from_xls in a rails app - ruby-on-rails

So I have a model that I need to be able to serialize to/read from an Excel(XLS) document. I am a bit of a loss as to where this code actually belongs. My initial thought is that the to_xls is a view, but after poking around and seeing things like (to|from)_xml and (to|from)_json in ActiveRecord, I was wondering if maybe this stuff belonged in the model. Alternatively, does it belong in just a whole separate container somewhere?
For what it's worth, users will be downloading models from the site, modifying them in excel, then posting them.

to_xls should definitely be a view. I'd try a /app/views/foos/show.xls.erb, but if you don't like ERB for XLS views, try the RbTemplateHandler to do rendering in pure Ruby.
from_xls is a different beast altogether. It certainly doesn't belong in a controller. It logically belongs in the model, but I'd extract it to a mixin. If you're only pulling in XLS for one model, then the following setup should suffice:
# app/models/foo.rb
class Foo
extend XLS2Foo
...
end
# lib/foo_from_xls
module XLS2Foo
def to_foo(xls)
...
end
end
If you need to do it for a bunch of models, you might try a parser-generator DSL in you lib directory and declare yourself parsers for each model in the model classes.

to/from_xls are not supported by Rails. There is a plugin, but I haven't used it to_xls plugin for Rails. A better way might be for you to go to and from a CSV using FasterCSV and get something that is usable. Here is one example: Export to_csv from ActiveRecord

Related

Where to properly outsource model code in rails 4?

In a model of mine I'm using the bing translator gem for automatic translation of a model attribute via a after_create callback:
class Place < ActiveRecord::Base
after_create :auto_translate
....
# AUTO_TRANSLATE STUFF
def initialize_bing_translator(bing_id, bing_secret)
t = BingTranslator.new(bing_id, bing_secret)
<do other stuff>
end
def auto_translate
<do stuff>
end
<further auto_translate methods>
The whole bunch of functions seems to bloat the model code a little so I want to put it into some extra module. Where exactly shall I place the .rb-file? Is this a use-case for a concern (a concept I did not fully understood)? Is it better to define a seperate module in the model file itself or to place it in /lib/user_modules/? Is there sth like a rule-of-thumb? The information available on the web are confusing me a little and I'd be glad if someone could shed some light on that issue for me!
I started putting stuff like that in subfolders of models and namespacing things accordingly. In your specific case I'd put it in something like models/place/translator.rb (or similar) and call the class Place::Translator.
If you just want a sort of logical separation but will not use the same functionality elsewhere you can use concerning instead of a separate concern.
There are many options and most of them are primarily opinion-based. It depends on if you plan to reuse that class, how complex your application already is and if the new class has any external dependency.
I would think about: create your own gem, add to app/models, add a new app/translators directory, perhaps in lib...

Rails ActiveRecord override default find

I'm building an API wrapper that will query objects from a third-party API and build them into objects to be used in my Rails environment. To do that, I'm building a set of models that use ActiveRecord (for some of its functionality) but are not database backed. I would like to be able to make a call like this:
obj = MyModel.find(1)
And have the code be something like this:
def MyModel.find id
# check for object in cache
# check for object in db
# grab object from API
# return object
end
Am I going to do something horribly wrong if I override the default find method? Am I approaching this in totally the wrong way?
If you are not using a database, then you do not need ActiveRecord. The entire purpose of ActiveRecord is to give you a mapping to a relational database.
I think what you want is for a class to implement certain pieces of what ActiveRecord provides, and Rails 3 has made those pieces into classes that you can include into regular 'ol classes on an as-needed basis. Look at this article for more details: http://www.rubyinside.com/rails-3-0s-activemodel-how-to-give-ruby-classes-some-activerecord-magic-2937.html
For instance, if you only want validations on a class, you can use include ActiveModel::Validations and then you'll get all of the nice error handling and .valid? and validates presence: true kind of behavior you're used to.
I would also suggest the railscast by Ryan Bates: http://railscasts.com/episodes/219-active-model which goes into more detail.

Using ActiveRecord interface for Models backed by external API in Ruby on Rails

I'm trying to use Models in my Rails application that retrieve information from an external API. What I would like to do is access my data models (which may consist of information resulting from multiple API calls) in a way similar to what an ActiveRecord model would provide (specifically associations, and the same style of chain-able query methods).
My initial instinct was to recreate the parts of ActiveRecord that I wanted and incorporate this API. Not wanting to 'reinvent the wheel' and seeing exactly how much work would be required to add more functionality have made me take a step back and reevaluate how to approach this.
I have found ways to use ActiveRecord without a table (see: Railscast #193 Tableless Model and the blog post here) and looked into ActiveRecord. Because ActiveModel only seems to include Validations I'm not sure that's very helpful in this situation. The workaround to using ActiveRecord without a table seems like the best option, but I suspect there's a cleaner way of doing this that I'm just not seeing.
Here is a gist containing some of the code written when I was trying to recreate the ActiveRecord functionality, borrowing heavily from the ActiveRecord source itself.
My question boils down to: I can get the functionality I want (chaining query methods, relations) by either implementing the workaround to ActiveRecord specified above or recreating the functionality myself, but are these really ideal solutions?
Remember that Rails is still just Ruby underneath.
You could represent the external API as instantiated classes within your application.
class Event
def self.find(id)
#...External http call to get some JSON...#
new(json_from_api)
end
def initialize(json)
#...set up your object here...#
end
def attendees
#...external http call to get some JSON and then assemble it
#...into an array of other objects
end
end
So you end up writing local abstractions to create ruby objects from api calls, you can probably also mix in ActiveModel, or Virtus into it, so you can use hash assignment of attributes, and validations for forms etc.
Take a look at an API abstraction I did for the TfL feed for the tube. service_disruption

How to write a custom method for an ActiveRecord using 'acts_as_<something>'?

I am using Ruby on Rails 3 and I am trying to use some custom method for an ActiveRecord so that I can do
Account.<my_method_name>
in order to add, for example, some data to the Account object (but without to change the Account data itself).
I heard of acts_as_<something> statement and it is used, if I am not wrong, on building plugins, but I didn't understand if it is what I need. After adding acts_as_<something> maybe I have to write somewhere a method like the following in order to "act" on the current ActiveRecord on which the <my_method_name> is called:
def self.<my_method_name>
...
end
Can someone explain me how to use that? And, if possible, can you make me a real example of its usage?
BTW: is it better to build a plugin or write a lib in the RAILS_ROOT/app/lib folder?
You can look at how to implement here => http://thoughtsincomputation.com/posts/coding-an-acts_as-gem-for-rails-3
For real example -> https://github.com/mbleigh/acts-as-taggable-on
The acts_as* is just way of adding behavior to a class. You can do the same by having a module ActsAs* and including this module in the class. Use the acts_as* only if you want to take arguments while adding this common behavior, otherwise just create a module and include it in the class
In the gem acts_as_taggable_on it makes sense because it takes arguments while adding the behavior.
acts_as_taggable_on :languages,:skills
You question is similar to rails3 gem: acts_as_something

OO Design in Rails: Where to put stuff

I'm really enjoying Rails (even though I'm generally RESTless), and I enjoy Ruby being very OO. Still, the tendency to make huge ActiveRecord subclasses and huge controllers is quite natural (even if you do use a controller per resource). If you were to create deeper object worlds, where would you put the classes (and modules, I suppose)? I'm asking about views (in the Helpers themselves?), controllers and models.
Lib is okay, and I've found some solutions to get it to reload in a dev environment, but I'd like to know if there's a better way to do this stuff. I'm really just concerned about classes growing too large. Also, what about Engines and how do they fit in?
Because Rails provides structure in terms of MVC, it's natural to end up using only the model, view, and controller containers that are provided for you. The typical idiom for beginners (and even some intermediate programmers) is to cram all logic in the app into the model (database class), controller, or view.
At some point, someone points out the "fat-model, skinny-controller" paradigm, and intermediate developers hastily excise everything from their controllers and throw it into the model, which starts to become a new trash can for application logic.
Skinny controllers are, in fact, a good idea, but the corollary--putting everything in the model, isn't really the best plan.
In Ruby, you have a couple of good options for making things more modular. A fairly popular answer is to just use modules (usually stashed in lib) that hold groups of methods, and then include the modules into the appropriate classes. This helps in cases where you have categories of functionality that you wish to reuse in multiple classes, but where the functionality is still notionally attached to the classes.
Remember, when you include a module into a class, the methods become instance methods of the class, so you still end up with a class containing a ton of methods, they're just organized nicely into multiple files.
This solution can work well in some cases--in other cases, you're going to want to think about using classes in your code that are not models, views or controllers.
A good way to think about it is the "single responsibility principle," which says that a class should be responsible for a single (or small number) of things. Your models are responsible for persisting data from your application to the database. Your controllers are responsible for receiving a request and returning a viable response.
If you have concepts that don't fit neatly into those boxes (persistence, request/response management), you probably want to think about how you would model the idea in question. You can store non-model classes in app/classes, or anywhere else, and add that directory to your load path by doing:
config.load_paths << File.join(Rails.root, "app", "classes")
If you're using passenger or JRuby, you probably also want to add your path to the eager load paths:
config.eager_load_paths << File.join(Rails.root, "app", "classes")
The bottom-line is that once you get to a point in Rails where you find yourself asking this question, it's time to beef up your Ruby chops and start modeling classes that aren't just the MVC classes that Rails gives you by default.
Update: This answer applies to Rails 2.x and higher.
Update: The use of Concerns have been confirmed as the new default in Rails 4.
It really depends on the nature of the module itself.
I usually place controller/model extensions in a /concerns folder within app.
# concerns/authentication.rb
module Authentication
...
end
# controllers/application_controller.rb
class ApplicationController
include Authentication
end
# concerns/configurable.rb
module Configurable
...
end
class Model
include Indexable
end
# controllers/foo_controller.rb
class FooController < ApplicationController
include Indexable
end
# controllers/bar_controller.rb
class BarController < ApplicationController
include Indexable
end
/lib is my preferred choice for general purpose libraries. I always have a project namespace in lib where I put all application-specific libraries.
/lib/myapp.rb
module MyApp
VERSION = ...
end
/lib/myapp/CacheKey.rb
/lib/myapp/somecustomlib.rb
Ruby/Rails core extensions usually take place in config initializers so that libraries are only loaded once on Rails boostrap.
/config/initializer/config.rb
/config/initializer/core_ext/string.rb
/config/initializer/core_ext/array.rb
For reusable code fragments, I often create (micro)plugins so that I can reuse them in other projects.
Helper files usually holds helper methods and sometimes classes when the object is intended to be used by helpers (for instance Form Builders).
This is a really general overview. Please provide more details about specific examples if you want to get more customized suggestions. :)
... the tendency to make huge
ActiveRecord subclasses and huge
controllers is quite natural ...
"huge" is a worrisome word... ;-)
How are your controllers becoming huge? That's something you should look at: ideally, controllers should be thin. Picking a rule-of-thumb out of thin air, I'd suggest that if you regularly have more than, say, 5 or 6 lines of code per controller method (action), then your controllers are probably too fat. Is there duplication that could move into a helper function or a filter? Is there business logic that could be pushed down into the models?
How do your models get to be huge? Should you be looking at ways to reduce the number of responsibilities in each class? Are there any common behaviours you can extract into mixins? Or areas of functionality you can delegate to helper classes?
EDIT: Trying to expand a bit, hopefully not distorting anything too badly...
Helpers: live in app/helpers and are mostly used to make views simpler. They're either controller-specific (also available to all views for that controller) or generally available (module ApplicationHelper in application_helper.rb).
Filters: Say you have the same line of code in several actions (quite often, retrieval of an object using params[:id] or similar). That duplication can be abstracted first to a separate method and then out of the actions entirely by declaring a filter in the class definition, such as before_filter :get_object. See Section 6 in the ActionController Rails Guide Let declarative programming be your friend.
Refactoring models is a bit more of a religious thing. Disciples of Uncle Bob will suggest, for example, that you follow the Five Commandments of SOLID. Joel & Jeff may recommend a more, er, "pragmatic" approach, although they did appear to be a little more reconciled subsequently. Finding one or more methods within a class that operate on a clearly-defined subset of its attributes is one way to try identifying classes that might be refactored out of your ActiveRecord-derived model.
Rails models don't have to be subclasses of ActiveRecord::Base, by the way. Or to put it another way, a model doesn't have to be an analogue of a table, or even related to anything stored at all. Even better, as long as you name your file in app/models according to Rails' conventions (call #underscore on the class name to find out what Rails will look for), Rails will find it without any requires being necessary.
Here's an excellent blog post about refactoring the fat models that seem to arise from the "thin controller" philosphy:
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
Basic message is "Don’t Extract Mixins from Fat Models", use service classes instead, the author provides 7 patterns to do so

Resources