One Controller, Many models


#1

Hello all,

I am working on a app right now that is going to replace a paper form
process out client has. This process has quite a few forms (about 30)
and different groups of forms (section) need to be filled out based on
what information is required from the user. For example, here is a
possible process of 2 users:

user 1 user 2
Section 1 Section 1
Section 2 Section 2
Section 12 Section 3
Section 13 Section 8
Section 15 Section 15

I am trying to figure out the most efficient way to do this in Rails. I
know I could just scaffold all the section tables, but then I would have
30 controllers for 30 models that are doing pretty similar things. I
believe that I will make the models for each section to allow for
customization in terms of validation and such, but I feel there must be
a way to avoid 30 controllers. Especially when each one will only
differ by which model it is using.

What I would like to do is define the sections and their order for each
“track”., then have a controller pull up the correct section model
depending on where the user is in the process.

I am still getting the hang of Rails and application architecture/domain
model stuff has always been a weakness. Any help or direction on how to
handle this problem would be greatly appreciated. (any recommendations
on some good places/books to learn software architecture would be nice
to)

Thanks

Peer


#2

Hi Peer,

I would take a look at single table inheritance
(http://wiki.rubyonrails.org/rails/pages/SingleTableInheritance) to see
if
it helps solve your problem. Also, it’s pretty simple to load other
models
into your controller. If you want to load and use the model in
“app/models/some_model.rb” you’d use something like

def track
require ‘some_model’
section_1 = SomeModel.new()
section_1.save
end

Validation would still reside in your models like normal.

Additionally, to avoid duplicating controller code across many
controllers
you can put it into app/controllers/application.rb .

I hope this helps!

Daniel


#3

Hi Daniel,

Unfortunately I don’t see how STI will help me in this case as each form
(model) has very different information. If I were to put them in a
single table it would have well over 100 columns. This is assuming that
you are talking about STI for all the models. If not, could you please
describe how I could use STI?

Peer

Daniel H. wrote:

Hi Peer,

I would take a look at single table inheritance
(http://wiki.rubyonrails.org/rails/pages/SingleTableInheritance) to see
if
it helps solve your problem. Also, it’s pretty simple to load other
models
into your controller. If you want to load and use the model in
“app/models/some_model.rb” you’d use something like

def track
require ‘some_model’
section_1 = SomeModel.new()
section_1.save
end

Validation would still reside in your models like normal.

Additionally, to avoid duplicating controller code across many
controllers
you can put it into app/controllers/application.rb .

I hope this helps!

Daniel


#4

Models don’t need to have their own controllers or full-blown scaffolds.
Nothing is stopping you from having one user-accessible controller and
one admin controller, for instance, and any controller can access any
model.

And as long as you’re careful about security in the controller, there’s
nothing wrong with having a single “edit” action in that one big
controller that takes a Secton as an argument and presents an
appropriate partial, for instance.

Peer A. wrote:

Hello all,

I am working on a app right now that is going to replace a paper form
process out client has. This process has quite a few forms (about 30)
and different groups of forms (section) need to be filled out based on
what information is required from the user. For example, here is a
possible process of 2 users:

user 1 user 2
Section 1 Section 1
Section 2 Section 2
Section 12 Section 3
Section 13 Section 8
Section 15 Section 15

I am trying to figure out the most efficient way to do this in Rails. I
know I could just scaffold all the section tables, but then I would have
30 controllers for 30 models that are doing pretty similar things. I
believe that I will make the models for each section to allow for
customization in terms of validation and such, but I feel there must be
a way to avoid 30 controllers. Especially when each one will only
differ by which model it is using.

What I would like to do is define the sections and their order for each
“track”., then have a controller pull up the correct section model
depending on where the user is in the process.

I am still getting the hang of Rails and application architecture/domain
model stuff has always been a weakness. Any help or direction on how to
handle this problem would be greatly appreciated. (any recommendations
on some good places/books to learn software architecture would be nice
to)

Thanks

Peer


#5

Thanks for everyone’s suggestions. I have a couple of ideas that I am
going to experiment with. I have a feeling that this question is not
that difficult to answer, but I am looking for a more complicated
solution because it seems complicated.

Peer

Martin Bernd S. wrote:

I’m not sure if I exactly understood what you want. So my suggestion is
short and maybe doesn’t fit your needs (also it’s definitly hackerish,
might be unsecure and there might be smarter ways to accomplish the same
task, forgive me, I’m relatively new to Ruby and RoR).

We needed an editor to internationalize several lookup tables (which had
some common fields, i.e. the different translations). Some of them had
parent relations. Instead of having a zillion views (and controllers) we
introduced two methods to each model parent_class() and parent_key()
returning the names to access the parent class / table (or nil in case
of a parent table).

Then we were passing the Model name (e.g. from a form) to the controller
and instanciated the corresponding objects with

def klazz
Object.instance_eval(params[:model]).find(params[:id])
end

def parent_klazz(object)
Object.instance_eval(object.parent_class)
end

This in addition with the parent_key method should give you all options
to make such issue generic. Let me know if you need more info.

Note: This might contain errors, I didn’t compare this with the actual
code…


#6

I’m not sure if I exactly understood what you want. So my suggestion is
short and maybe doesn’t fit your needs (also it’s definitly hackerish,
might be unsecure and there might be smarter ways to accomplish the same
task, forgive me, I’m relatively new to Ruby and RoR).

We needed an editor to internationalize several lookup tables (which had
some common fields, i.e. the different translations). Some of them had
parent relations. Instead of having a zillion views (and controllers) we
introduced two methods to each model parent_class() and parent_key()
returning the names to access the parent class / table (or nil in case
of a parent table).

Then we were passing the Model name (e.g. from a form) to the controller
and instanciated the corresponding objects with

def klazz
Object.instance_eval(params[:model]).find(params[:id])
end

def parent_klazz(object)
Object.instance_eval(object.parent_class)
end

This in addition with the parent_key method should give you all options
to make such issue generic. Let me know if you need more info.

Note: This might contain errors, I didn’t compare this with the actual
code…