Is there a Rails3 way to "scope" views?

I am finding my views directory a bit cluttered and I would like to move
some related views into their own subdirectory under app/views. Is
there a Rails way to specify that app/views/** should be searched in
addition to app/views?

You can set view_paths on controller.

James B. wrote in post #957825:

I am finding my views directory a bit cluttered and I would like to move
some related views into their own subdirectory under app/views. Is
there a Rails way to specify that app/views/** should be searched in
addition to app/views?

As Robert said, you can certainly do this.

But why? What does your views directory look like now? Where’s the
clutter? In my experience, views directories generally don’t get that
cluttered, so I’m wondering if something strange is happening with your
design…

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Please quote when replying.

James B. wrote in post #957905:

To me, having several hundred files in a single directory is cluttered.

To me too – if we’re talking files. But again: that should never
happen. Let’s see your views and controllers. I suspect you are trying
to cram too much into a single controller, and ending up with lots of
actions and views as a result.

I think several hundred directories in a single directory, OTOH, is no
problem at all.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

To me, having several hundred files in a single directory is cluttered.
Others have different thresholds of tolerance. Mine is low.

In any case, once given the hint above I managed to locate some
information on ActonController.config.view_paths. Not enough to
actually try anything just yet, but the leads are promising.

Not sure if it’s possible in your architecture, but we are working a
lot with namespaces.
E.g. you could have a Customs::ShipmentParsChecksController and a
Customs::SomeOtherController etc. this would group your controllers,
models and views into related sections.
Your views then would look like:
app

  • views
  • customs
  • shipment_pars_checks
  • some_other

Best, Daniel

Daniel G. wrote in post #957936:

Not sure if it’s possible in your architecture, but we are working a
lot with namespaces.
E.g. you could have a Customs::ShipmentParsChecksController and a
Customs::SomeOtherController etc. this would group your controllers,
models and views into related sections.
Your views then would look like:
app

  • views
  • customs
  • shipment_pars_checks
  • some_other

Best, Daniel

Thanks. I will look into this. I have not worked with namespaces so I
never thought of that approach.

Marnen Laibow-Koser wrote in post #957913:

To me too – if we’re talking files. But again: that should never
happen. Let’s see your views and controllers. I suspect you are trying
to cram too much into a single controller, and ending up with lots of
actions and views as a result.

I mis-wrote. As you picked up I really meant view directories. But, why
should it never happen for view directories?

I am writing an application that handles international freight bookings,
movements and customs formalities including edi cusdec transmissions.
That is never ever going to fit into a handful of controllers. In fact,
but for foreign exchange, most controllers possess only the basic index,
show, new, create, and destroy actions. Many do not have all of these.

A sample controller, one of the more complex ones, is given below:

class CustomsShipmentParsChecksController < ApplicationController

skip_before_filter :authenticated
skip_before_filter :authorised

POST /collection

POST /collection.xml

def create

respond_to do |format|
  if @manifest = CaCustomsManifest.find_by_ccdn(
        params[:ca_customs_manifest][:ccdn].strip)

    @shipment = @manifest.ca_customs_shipment
    @entry = @shipment.ca_customs_entry

    if

@manifest.ca_customs_shipment.ca_customs_entry.is_across_accepted
flash[:info] = accepted_message
# render simply uses the template specified by the :action key
# without calling the method.
format.html { render :action => “show” }
format.xml { render :xml => @shipment,
:status => :accepted,
:location =>
:customs_shipment_pars_check }
else
flash[:notice] = not_accepted_message
format.html { render :action => “show”, :id => @shipment.id }
format.xml { render :xml => @manifest,
:status => :found,
:location =>
:customs_shipment_pars_check }
end
else
new # build a dummy record complex to allow display of messages
manifest.ccdn = params[:ca_customs_manifest][:ccdn].strip
flash[:notice] = not_found_message
flash[:warn] = contact_message
format.html { render :action => “new” }
format.xml { render :xml => @manifest.errors,
:status => :not_found }
end
end
end

DELETE /collection/:id

DELETE /collection/:id.xml

def delete
show
end

Do not raise pointless not found errors

GET /collection/:id/edit

def edit
show
end

GET /collection/new

GET /collection/new.xml

def new
@shipment = CaCustomsShipment.new
@entry = @shipment.build_ca_customs_entry
@manifest = @shipment.ca_customs_manifests.build
end

GET /collection

GET /collection.xml

def index
new
end

GET /collection/:id

GET /collection/:id.xml

def show
get_shipment
end

private

end

James B. wrote in post #957930:

Marnen Laibow-Koser wrote in post #957913:

To me too – if we’re talking files. But again: that should never
happen. Let’s see your views and controllers. I suspect you are trying
to cram too much into a single controller, and ending up with lots of
actions and views as a result.

I mis-wrote. As you picked up I really meant view directories. But, why
should it never happen for view directories?

Why should what never happen? That you should have lots of view
directories? I specifically didn’t say that that should never happen.

I am writing an application that handles international freight bookings,
movements and customs formalities including edi cusdec transmissions.
That is never ever going to fit into a handful of controllers.

Of course it won’t. I didn’t mean to suggest that it would. In fact, I
was suggesting more controllers, not fewer.

If you don’t like the number of controllers, group them in namespaces.

In fact,
but for foreign exchange, most controllers possess only the basic index,
show, new, create, and destroy actions. Many do not have all of these.

A sample controller, one of the more complex ones, is given below:

class CustomsShipmentParsChecksController < ApplicationController

skip_before_filter :authenticated
skip_before_filter :authorised

POST /collection

POST /collection.xml

def create

respond_to do |format|
  if @manifest = CaCustomsManifest.find_by_ccdn(
        params[:ca_customs_manifest][:ccdn].strip)

    @shipment = @manifest.ca_customs_shipment
    @entry = @shipment.ca_customs_entry

    if

@manifest.ca_customs_shipment.ca_customs_entry.is_across_accepted
flash[:info] = accepted_message
# render simply uses the template specified by the :action key
# without calling the method.
format.html { render :action => “show” }
format.xml { render :xml => @shipment,
:status => :accepted,
:location =>
:customs_shipment_pars_check }
else
flash[:notice] = not_accepted_message
format.html { render :action => “show”, :id => @shipment.id }
format.xml { render :xml => @manifest,
:status => :found,
:location =>
:customs_shipment_pars_check }
end
else
new # build a dummy record complex to allow display of messages
manifest.ccdn = params[:ca_customs_manifest][:ccdn].strip
flash[:notice] = not_found_message
flash[:warn] = contact_message
format.html { render :action => “new” }
format.xml { render :xml => @manifest.errors,
:status => :not_found }
end
end
end

Too long. Most of that should be refactored into model methods.
Remember, “skinny controller, fat model”. A controller method over 5-10
lines is a sure sign that you need to do more refactoring.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]