Model-less Rails?


#1

Hi,

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?

Thanks,

Shak


#2

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.


#3

Shak wrote:

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…


Phlip


#4

you can have a look at the active_record_base_without_table plugin…

On Wed, Jan 21, 2009 at 11:30 PM, Shak removed_email_address@domain.invalid wrote:

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?

Thanks,

Shak


Greg
http://blog.gregnet.org/


#5

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

def method2
rpc calls
end
end

I hope that helps.


#6

All you’ll need to do is inherit from the ModelWithoutDatabase. This
should allow you to do normal validations if needed.

for example:

class Contact < ModelWithoutDatabase
attr_accessors :first_name, :last_name, :email, etc…

def method1
do stuff
end

end


#7

On Jan 21, 10:58 pm, Nate L. removed_email_address@domain.invalid
wrote:

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)?

def method2
rpc calls
end
end

I hope that helps.

It does, thanks!

Shak


#8

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.

http://svn.viney.net.nz/things/rails/plugins/active_record_base_without_table/

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.

Chris


#9

On Jan 22, 7:31 pm, snacktime removed_email_address@domain.invalid wrote:

Chris,

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?

Shak


#10

On Feb 16, 2:22 pm, Frederick C. removed_email_address@domain.invalid
wrote:

On 16 Feb 2009, at 12:32,Shakwrote:

But this doesn’t seem to work at all.

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?

Shak


#11

On 16 Feb 2009, at 12:32, Shak wrote:

But this doesn’t seem to work at all.

Is there a way of programatically assigning values to ActiveRecord
columns?

You need to call the accessor methods.

Fred