Fat Model Thin Controller

I'm trying to follow Fat Model Thin Controller, and generally just do
things right as much as possible and need some help at this early stage
of development.

I have some users (courtesy of restful_authentication).

I’ve got my relationships such that a User has_many Adverts and an
Advert belongs_to a user.

I have an adverts controller, and I’m structuring things as it stands
such that the index action gets me all the ads for the currently logged
in user (“current_user”).

I have this working with the following code, as I say in the adverts
controllers index action.

@adverts = current_user.adverts

Now then, I figure that in the correct place to do the finding of a
users adverts is in the adverts model. This should give me the ability
to do the find and ordering in lots of different ways in the future, and
I believe it’s just the correct way to go.

So now I have in my controller index action

@adverts = Advert.find_adverts_for_current_user

and that works.

Now the thing is, couple of things I need help with

when a user hasn’t got any adverts I get errors, my thoughts are just if
statement in either the controller or the model which only does the find
when the user has adverts and does something else sensible (“displays a
flash” perhaps) when there are none. Do I do this in the model or the
controller and what’s the syntax – I tried repeatedly this morning but
couldn’t get it. I figure the model is the right place, but I can’t
display a flash with the model!

How do I elegantly make sure that you can only delete your own adverts
(apart from admin who can delete anything of course).

And I suppose when a user is deleted their adverts should be eradicated
with them!

Quite a bit to think about here, I would very much appreciate any help!

bb.

I have this working with the following code, as I say in the adverts
controllers index action.

@adverts = current_user.adverts

Now then, I figure that in the correct place to do the finding of a
users adverts is in the adverts model. This should give me the ability
to do the find and ordering in lots of different ways in the future, and
I believe it’s just the correct way to go.

So now I have in my controller index action

@adverts = Advert.find_adverts_for_current_user

and that works.

good point, but wrong for Rails.
Use your first version.

@adverts = current_user.adverts

and you do not necessarily assign it to a variable,
you can use it in a view like this:

<% current_user.adverts.each do |advert| %>
... display advert code here...
<% end %>

Now the thing is, couple of things I need help with

when a user hasn’t got any adverts I get errors, my thoughts are just if
statement in either the controller or the model which only does the find
when the user has adverts and does something else sensible (“displays a
flash” perhaps) when there are none. Do I do this in the model or the
controller and what’s the syntax – I tried repeatedly this morning but
couldn’t get it. I figure the model is the right place, but I can’t
display a flash with the model!

if current_user.adverts then
...
end

this will do nothing, if there are no adverts (since it's nil then)

How do I elegantly make sure that you can only delete your own adverts
(apart from admin who can delete anything of course).

And I suppose when a user is deleted their adverts should be eradicated
with them!

@adverts = current_user.adverts.find(...you find conditions...)
then do something with the found adverts.

If you want to keep find scopes in models, then look at named_scope:
http://api.rubyonrails.org/classes/ActiveRecord/NamedScope/ClassMethods.html#M001246

you can define some standard finds (and others) with it, eg for
adverts
eg in Adverts model:
named_scope :red, :conditions => {:color => 'red'}

then use
@adverts = current_user.adverts.red

to find all adverts with value 'red' in column "color"

good point, but wrong for Rails.
Use your first version.

@adverts = current_user.adverts

OK, but the thing is, this fails if the user doesn't have any adverts?

You'll need to test for current_user.adverts first before you make a
loop on it. Or you could do a "lazy" approach:

@adverts = current_user.adverts || []

You can then loop through it without testing for @adverts being nil
(since it never will be), although I'm practically sure that this is
not standard practice.

OK,

But two things

@adverts = current_user.adverts || [] <-- can you explain the "|| []" part?

and...

I want to check for it being nil, would I do this in the controller (I
think I must as the error is generated from that point - i.e. it doesn't
get as far as the view if there are no ads for that user).

How do I do it...like the following...?

if current_user.adverts = nil

redirect somewhere and flash something.

else

@adverts = current_user.adverts

end

But two things

> @adverts = current_user.adverts || [] <-- can you explain the "|| []" part?

It assigns the empty array [] to @adverts if current_user.adverts is
nil, otherwise it works just like a normal assign. Think of it as a
shortcut of:

if current_user.adverts
  @adverts = current_user.adverts
else
  @adverts = []
end

I want to check for it being nil, would I do this in the controller (I
think I must as the error is generated from that point - i.e. it doesn't
get as far as the view if there are no ads for that user).

How do I do it...like the following...?

if current_user.adverts = nil
redirect somewhere and flash something.
else
@adverts = current_user.adverts
end

If you're testing for equality, you will need to use the == operator,
and not the assignment operator =. You can also do this:

if current_user.adverts.nil?
  ...
else
  ...
end

That's very helpful, many thanks. The mists have cleared!
Until the next time. hehe.
bb