I’m looking into using RoR to develop a front end for an existing
system - one which is accessible via JSON-RPC. As such, there won’t be
any data management performed directly by the web application itself,
all would be done via these RPC calls.
Is this possible? I assume that it is, so the next question is whether
it’s appropriate or not to chop off the model part of Rails. From
tutorials and the like Rails seems quite dependent on convention (and
even boasts of this). Will I get into trouble later on, or will
decoupling the model part be more trouble than it’s worth?
You are most likely going to have models. Those models are your
business objects. In your case you’re not going to be talking to a
database, so the conventional “model” that is backed by a database
will not be needed.
However, a Model in Rails can just be a simple Ruby class. Typically
you’d have data models that did the RPC calls, so that the controllers
interacted with them. The models then do the RPC calls to your
backend, keeping each piece of code separated and easy to test. For
example, say you were making a new front-end to Twitter. A skeleton
model might look like this:
class Twitter
def initialize(user, password) @user = user @password = password
end
returns timeline for the user
def posts
end
creates a new post
def post(message)
…
end
private
end
Heck, you might even break this down farther and have a Post model,
which you’d use to hold the Post you retrieved from Twitter, or even
to have the Post class handle the creation of posts.
class Post
attr_accessor :message, :username, :posted_at
end
The basic idea here is that you’d use models to encapsulate your
logic, and controllers just to route requests around and show views.
So, you’ll have “models”. just not ActiveRecord models.
I’m looking into using RoR to develop a front end for an existing
system - one which is accessible via JSON-RPC. As such, there won’t be
any data management performed directly by the web application itself,
all would be done via these RPC calls.
Models are thin wrappers on external entities. Rails offers ActiveRecord
as the
One True Best external object to wrap. That’s the convention.
To bypass the convention, simply do not use script/generate model. Just
write
the .rb file you want in app/models, put a class inside with the same
name, and
make it use whatever external entities you want to link to. All the rest
of
Rails will work the same…
tutorials and the like Rails seems quite dependent on convention (and
even boasts of this). Will I get into trouble later on, or will
decoupling the model part be more trouble than it’s worth?
I’m assuming you are meaning you don’t want ActiveRecord models. If
thats’ the case, then yes it is possible. In fact, I currently do that
in a couple apps that access objects through XML RPC calls. Here is how
I do it, which will give you validations on errors.
class ModelWithoutDatabase
def save() raise NotImplementedError end
def save!() raise NotImplementedError end
def update_attribute() raise NotImplementedError end
def new_record?() true end
include ActiveRecord::Validations
include ActiveRecord::Errors
def initialize(attributes = nil)
self.attributes = attributes
end
def attributes=(new_attributes)
return unless new_attributes
new_attributes.each do |k, v|
k = “#{k}=”
send(k, v) if respond_to?(k)
end
end
def self.human_attribute_name(attribute_key_name) #:nodoc:
attribute_key_name.humanize
end
Rails 2.2.2 fixes
def self.self_and_descendents_from_active_record; [self]; end
def self.human_name; self.name; end
end
The cool thing about this is that I can still call Model.valid? and use
the validation stuff of ActiveRecord. Then I have my RPC objects that
are Models inherit from the class above so:
class Contact < ModelWithoutDatabase
def method1
rpc calls
end
I’m assuming you are meaning you don’t want ActiveRecord models. If
thats’ the case, then yes it is possible. In fact, I currently do that
in a couple apps that access objects through XML RPC calls. Here is how
I do it, which will give you validations on errors.
class ModelWithoutDatabase
end
Thanks for all the replies guys! Just what I wanted to her.
Is there a list of what methods my new models must implement in order
to work well with the rest of Rails? Or does your ModelWithoutDatabase
cover it all (via the include)?
Yes that will work. I’ve been working on something very similar for an
opensocial container, where I use models not tied to a database. I use
something similar to this, although I also overrite save so you can
validate
on save.
Also, the built in json serializer has really bad performance,
especially in
it’s association handling. I used the json gem and wrote my own code
for
serializing associations.
I’ve been trying to use the active_record_base_without_table and it
seems to work okay, until I try to dynamically create the model
objects. At the moment I assign variables like so:
obj.instance_variable_set(“@#{varname}”, val)
However it seems that ActiveRecords don’t hold values in variables,
but in an attribute hash. This seems to get set like so:
obj.method_missing(“@#{varname}=”, [val], nil)
But this doesn’t seem to work at all.
Is there a way of programatically assigning values to ActiveRecord
columns?
Is there a way of programatically assigning values to ActiveRecord
columns?
You need to call the accessor methods.
Thanks for the heads up, I managed to figure it out. However I’m now
starting to think that using AR (without tables) is more trouble than
its worth for non-trivial models - is it possible to define
relationships if there’s no tables to refer to?
For example, if the RPC returns a Post with a list of Comments, how
would I write a table-less Post model which puts the Comments in the
right place, and then doesn’t let Rails go off and try to complete the
model anyway?