listing things in groups (adverts by advert_type)

OK, following on - I did it, but I have another problem now..

here's some code...

advert.rb

  default_scope :order => "adverts.created_at DESC", :limit => 100
  named_scope :cleared_for_release, :conditions => ['cleared_for_release
= ?', true]
  has_and_belongs_to_many :resorts
  belongs_to :advert_type

advert_type.rb

  acts_as_list
  default_scope :order => 'position'
  has_many :adverts, :dependent => :destroy

resort show controller extract

    @resort = Resort.find(params[:id])
    @adverts = @resort.adverts.cleared_for_release
    @advert_types = @adverts.group_by { |at| at.advert_type }

show view extract

  <% @advert_types.each do |type, advert| %>
  <%= type.name %>
    <% advert.each do |advert| %>
        <%= render :partial => 'adverts/small_advert_for_side_panel',
:locals => { :advert => advert } %>
    <% end %>

show view extract

<% @advert_types.each do |type, advert| %>

Should that be adverts not advert?

<%= type.name %>
<% advert.each do |advert| %>

adverts.each ?

    &lt;%= render :partial =&gt; &#39;adverts/small\_advert\_for\_side\_panel&#39;,

:locals => { :advert => advert } %>
<% end %>

I've realised what I need to do here is probably something like...

@advert_types.sort.each do |type, advert|

Have a look at sort_by, you can do something like
@advert_types.sort_by { |t| t.position }

Colin

Not much to expand, what happens when you do it?

Have you met ruby-debug? I find it invaluable when some code is not
doing what you expect, you can break in at the appropriate point and
examine the variables. Have a look at the rails guide on debugging.
(I presume you have already worked through the getting started guide.
The ActiveRecord associations one is compulsory also.)

Colin

Strange, t should be a single advert_type by the time it gets into the
block. As I expect you saw from the sort_by docs each item to be
sorted is passed into the block and the result used as the thing to
sort by. Can you paste the line of code it is failing on, together
with the surrounding ones. Use copy/paste rather than re-typing in
case there is a typo in it that you have not seen.

Colin

24: <% else %>
25:
26:
27: <% @advert_types.sort_by { |t| t.position } %>

Firstly it would be much better to do this in the controller, or even
better in a method of one of the models. Secondly sort_by does not
modify the array (@advert_types in this case) it just returns another
array, so you have to say @advert_types = @advert_types.sort_by ...
Neither of which explains why t is an array. Are you sure that
@advert_types is what you think it is, an array of AdvertTypes? Could
it be something else. I suggest maybe looking at the docs for
group_by and possibly call it something different. Go in with the
debugger and have a look where you make advert_types. You can do
things like p @advert_types[0] and see what is in it.

28:
29: <% @advert_types.each do |type, adverts| %>

This is a bit of a clue that @advert_types is not an array of
AdvertTypes. You may need to make the contents of the block in
sort_by a little more subtle.

Colin

ok i did this...
  <%= p @advert_types.inspect %>

and got this

"#<OrderedHash {#<AdvertType id: 1, name: \"Accommodation\",
description: \"Accommodation\", created_at: \"2009-08-30 10:20:38\",
updated_at: \"2009-08-30 10:20:38\", position: 2>=>[#<Advert id: 6,
advert_type_id:...SNIP,

#<AdvertType id: 2, name: \"Bars and Restaurants\", description: \"Bars
and Restaurants\", created_at: \"2009-08-30 10:20:38\", updated_at:
\"2009-08-30 10:20:38\", position: 3>=>[#<Advert id: 9, advert_type_id:
2, user_id: 13, name: \"Bobs Bar\", tag_line: \"aksl daslkas kl askl
sadklashkld hklas hlskahasklhd...\", body: \"aksl das...SNIP..

So yes, it's misleading calling it advert types. It's Advert Types and
adverts within it as an order hash!

How can I control the order of the outer Advert Type in this case?

I guess a better name would be adverts_by_type or somesuch.

Have you considered grouping on the position rather than the type,
then the key will be the position itself and I think you should be
able to do something like
@whatever_you_want_to_call_them_sorted = @adverts.group_by { |advert|
advert.advert_type.position }.sort

Colin

actually scrub that, dont think the number is the ID of the advertype

Since you are grouping on the position 'type' should be the position.
To get the advert type do adverts[0].advert_type.name, or do it in the
adverts.each loop.

Colin

Colin, You nailed it. Working great in my app - lovely.
Many thanks indeed for your help.
Rupert

Glad to be of help.

Colin