Forum: Ruby on Rails Design Question

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Steven <> <> (Guest)
on 2005-11-22 04:49
I'm having some trouble figuring out how to break a project into various
controllers.  Here's my situation.  Say I'm building a small web store
that sells software.  Each piece of software will belong to a given
Vendor.

Ok, so there are my two models 'Software' and 'Vendor'.  I'd like to be
able to do basic CRUD on both a Vendor and and or a Product.  However, I
want the Vendor to be a sort of Gateway to the Product.  So let's say I
create the basic CRUD actions for the Vendor.  If I'm viewing a Vendor's
info--name, address, url, etc-- that's where I would also see options
like: 'List Products', 'Create Product'.

So the real question is should I use one controller or two controllers?

If I used one controller I would have actions like:
/admin/vendor/add
/admin/vendor/list
/admin/vendor/view
/admin/vendor/add_product
/admin/vendor/list_products
/admin/vendor/view_product

If I used two controllers:
/admin/vendor/add
/admin/vendor/list
/admin/vendor/view
/admin/product/add
/admin/product/list
/admin/product/view

Thanks,
Steven
michael.gorsuch (Guest)
on 2005-11-22 14:00
(Received via mailing list)
This is probably very subjective, but I build a controller for each
'gateway' as you put it.

For example, I would build a vendor controller that allowed the vendor
to do everything that was needed for its interface.  I usually name my
actions things like "vendor_add", "vendor_edit", "product_add",
"product_destroy", etc just to make it more clear when reviewing
later.

I suppose the next step would be an interface for customers, which you
might just call 'store' or something like that.

Hope this makes sense,

Michael

On 11/21/05, Steven <removed_email_address@domain.invalid> 
<removed_email_address@domain.invalid>
christopher.k.hall (Guest)
on 2005-11-22 14:24
(Received via mailing list)
i do something like this, using the 2 controller method, within
/vendor/view, do:

link_to "view products for this vendor", :controller => "product",
:action
=> :list, :criteria => "vendor", :id => @vendor.id <http://vendor.id>
link_to "add new products for this vendor", :controller => "product",
:action => :new, :criteria => "vendor", :id => @vendor.id
<http://vendor.id>

in routes.rb, add (above the default route):

map.connect "/product/list/:criteria/:id", :controller => "product",
:action
=> "list", :criteria => nil, :id => nil, :requirements => { :id => /\d+/
}
map.connect "/product/list/:criteria/:id", :controller => "product",
:action
=> "add", :criteria => nil, :id => nil, :requirements => { :id => /\d+/
}

then in product controller:

class ProductController < ApplicationController
def list
case @params[:criteria]
when "vendor"
# list products for a specific vendor
@products = Product.find_by_vendor_id(@params[:id])
else
# otherwise just list all products
@products = Product.find_all
end
end

def new
case @params[:criteria]
when "vendor"
# new product for a specific vendor (preset the vendor id so it is
selected
in the view form)
@product = Product.new(:vendor_id => @params[:id])
else
@product = Product.new
end
end
end

in the new.rhtml view, do:

<%= start_form_tag :action => :create %>
.<%= text_field("product", "name") %>
<%= select("product", "vendor_id", Vendor.find(:all).collect { |v|
[v.name<http://v.name>,
v.id <http://v.id>] }, { :include_blank => true }) %>
<%= submit_tag "save product" %>
<% end_form_tag %>

this should automatically select the vendor in the select options

hope this helps

Chris



On 11/21/05, Steven <removed_email_address@domain.invalid> 
<removed_email_address@domain.invalid> <
Steven <> <> (Guest)
on 2005-11-22 16:48
Mike, Chris

Thanks for the feedback.  I think I may go with the two controller
method since this is how I've done things in the past with the PHP
framework I was using.

-Steven
Steven H. (Guest)
on 2005-11-28 02:50
@Chris....or anyone else who has an opinion

Thanks again for you detailed example.  Just getting around to figuring
out how the whole Map.connect thing works and I'm a bit blown away at
it's power.
The more I use rails the more I like it :)

Anyway, in your previous post you mentioned how one option is to pass
the id of the vendor into the product controller.  Then you could do
product actions specific to the vendor with a url like:

product/list/vendor/5
product/new/vendor/5
product/edit/66/vendor/5

ok so my questions is about passing the vendor id around.  I guess I'm
just lazy and wondering why not just set a session parameter and the
forget about passing the vendor id around while in the product
controller.  What if in product/list I did something like:

def list
  if params[:criteria] == 'vendor' && !params[:vendor_id].nil?
    session[:vendor] ||= Vendor.find(params[:vendor_id]
    # get list of products for this vendor
  else
    # get list of all products
  end
end

Then in the rest of my product controller's actions I could just check
to see if session[:vendor] is set, and act accordingly.  In vendor/list
I could just blow the session var away 'session[:vendor] = nil'

Anyway, I've done this type of thing in the past with php and it's
worked fairly well.  Just wondering if perhaps doing this may come back
to bite me and or if it violates any rails best practices.

-Steven
christopher.k.hall (Guest)
on 2005-11-28 15:48
(Received via mailing list)
if you notice, the only time the vendor info is getting passed via the
URL
is when I am requesting information.

so for list and new actions, i would use:

/product/list/vendor/X       # list products for vendor X
/product/new/vendor/X     # show new product for and pre-select vendor X
in
the 'new' form

where X is the vendor id

i wouldn't use it for the edit action, since the vendor would already
exist
for that product, so a simple /product/edit/X (where X is the product
ID)
would suffice.

for create and update actions, the vendor ID would be submitted in the
form

so you really aren't passing around the vendor ID except for those 2
situations.

it's just my way of doing it.  i'm sure there are just as many other
valid
ways to accomplish the same thing.  to me, it's intiuitive and easy to
follow.

Chris
This topic is locked and can not be replied to.