I'm new to the rails environment and come from a java enterprise web application background. I want to create a few classes that allow you to easily interface with an external application that exposes restful web services. In java I would simply create these as stateless java beans/facade's that return Data Transfer Objects which are nice usable objects instead of ugly xml maps/data. What is the best way to do this in Rails/Ruby? Here's my main questions:
开发者_运维技巧Should the facade classes be static or should you instantiate them before using the service?
Where should the DTO's be placed?
Thanks, Pierre
UPDATE: We ended up using services as explained in this answer: Moving transactional operations away from the controller
Code that doesn't fit as a model or controller lives in the lib
folder. helpers
is typically just for view related code that generates HTML or other UI related results.
I'd generally create them as regular classes that are instantiated and have instance methods to access the external rest service - this can make testing them easier. But this is really just a matter of preference (and also depends on how much state/reuse of those objects is required per request - depends on what you're doing exactly).
The "DTOs", would just be plain Ruby classes in this case - maybe even simple Struct instances if they don't have any logic in them. If they are Ruby classes, they'd live in app/models
, but they wouldn't extend ActiveRecord::Base (or anything else)
You probably want to take a look at httparty
Here's an example of how you'd consume the twitter api.
# lib/twitter.rb
require 'httparty'
require 'hashie'
class Twitter
include HTTParty
base_uri 'twitter.com'
def timeline
self.class.get("/statuses/public_timeline.xml")["statuses"].map do |status|
Hashie::Mash.new(status)
end
end
end
# client code
client = Twitter.new
message = client.timeline.first
puts message.text
Notice that you don't have to create DTOs. httparty maps xml (take a look at http://dev.twitter.com/doc/get/statuses/public_timeline for the structure in this example) to Hashes and then Hashie::Mash maps them to methods, hence you can just do message.text. It even works recursively so you can do client.timeline.first.user.name.
If you're creating a rails project then I'd place twitter.rb in the lib folder.
If you'd rather use static methods you can do:
require 'httparty'
require 'hashie'
class Twitter
include HTTParty
base_uri 'twitter.com'
def self.timeline
get("/statuses/public_timeline.xml")["statuses"].map do |status|
Hashie::Mash.new(status)
end
end
end
# client code
message = Twitter.timeline.first
puts message.text
精彩评论