Pick a specific item from a list with objects

Hi,

When I do this:
debug user.declarations_payers

I get this:

  • !ruby/object:DeclarationsPayer
    attributes:
    declaration_id: “1”
    id: “1”
    additional_persons: “3”
    user_id: “1”
  • !ruby/object:DeclarationsPayer
    attributes:
    declaration_id: “2”
    id: “2”
    additional_persons: “2”
    user_id: “1”

Is there a way I can pick the one with declaration_id: “1” without
looping throught the list?
I tried this:
DeclarationsPayer.find(:first, :conditions => [‘user_id = ? AND
declaration_id = ?’, user.id, @declaration.id])

But the disadvantage is that it generates a query. And it fails if
find() does not return an object.

Thanks!

On 3/13/07, LeonB [email protected] wrote:

id: "1"

looping throught the list?

user.declarations_payers.find_by_declaration_id 1

Yes it’ll generate a query, but so would just pulling all the
declarations_payers.

You can also do user.declarations_payers.select {|p| p.declaration_id
== 1} but that loops through the list. Anyway I’d prefer the first
method by far.

Pat

Thanks! And is there a way to ignore errors while doing this:
DeclarationsPayer.find(:first, :conditions => [‘user_id = ? AND
declaration_id = ?’, user.id, @declaration.id])

I think a try/catch or if block would do the trick. But is there any
other way?

Ah, sorry. I saw it was incomplete… I did something like this:
<%= DeclarationsPayer.find(:first, :conditions => [‘user_id = ? AND
declaration_id = ?’, user.id, @declaration.id]).additional_persons %>
And then it throws a message because (of course) the method does not
exist.

Anyone? Maybe a supershort if-statement? Like: <%= 1 = 1 ? ‘OK’ : ‘Not
OK’ %>

On 3/13/07, LeonB [email protected] wrote:

Thanks! And is there a way to ignore errors while doing this:
DeclarationsPayer.find(:first, :conditions => [‘user_id = ? AND
declaration_id = ?’, user.id, @declaration.id])

No errors are thrown if you do it that way. If there’s no record that
matches those criteria, the find method will return nil.

Pat

LeonB [email protected] wrote:

Anyone? Maybe a supershort if-statement? Like: <%= 1 = 1 ? ‘OK’ : ‘Not
OK’ %>

First off, you shouldn’t be putting something like that in an rhtml
document, your controller should do all your find()'s for you and then
pass
the resultsets in as local variables to your views.

Views should be just that - they shouldn’t know that models, etc exist
at
all… they just get handed some data to work into a template.

That said, try this in your controller:

def declarations
if person = DeclarationsPayer.find(…)
collection = person.additional_persons
else
collection = []
end

render :locals => { :collection => collection }
end

Then, you can just have your view (in this case declarations.rhtml)
iterate
over the collection, which, if the person was found, will be populated
with
additional_persons… if not, it will be empty.

Cheers,
Tyler

On 3/13/07, LeonB [email protected] wrote:

Thanks! But what does render :locals => {:collection => collection}
do?
What are locals? And why “collection”? Is that something from Ruby? Or
did you make that up? And why twice the “collection”?
Should I then create a partial that’s called _collection or something
like that?

I now created a method in my user model like:

def getAdditionalpersonsForDeclaration(declaration_id)
declarations_payer =
self.declarations_payers.find_by_declaration_id(declaration_id)

if !declarations_payer.nil?
  return declarations_payer.additional_persons
end

end

Is that all right too?

Thanks in advance.

On Mar 14, 9:28 pm, Tyler MacDonald [email protected]

LeonB [email protected] wrote:

Thanks! But what does render :locals => {:collection => collection}
do?

Locals are passed into your view as local variables. So if you say

:locals => { :foo => “bar” },

then the variable “foo” in your view will contain the string bar, and
you
can use it like so:

<%=foo%>

What are locals? And why “collection”? Is that something from Ruby? Or
did you make that up? And why twice the “collection”?

“Why twice” should be obvious from my above comment. I picked
“collection”
because that’s what you’re returning, a collection of “additional
people”.

Should I then create a partial that’s called _collection or something
like that?

If you want, then in the view that’s actually displaying it, you could
do
something like:

<%=render :partial => ‘additional_person’, :collection => collection%>

… which would cause that partial to be rendered once for each
additional
person in that collection.

end

Is that all right too?

I guess it’s fine, but since it’s all about declarations and isn’t
thinking about users at all, does it really belong in the user model?

I could see something like this being in the user model if you wanted
to
assert that the declaration actually BELONGED to the user, eg;

def declaration_additional_persons(declaration_id)
payer = DeclarationsPayers.find_by_declaration_id(declaration_id)

if payer
  unless payer.user_id == self.id
    raise RuntimeError.new, "Declaration payer does not belong to 

this user!"
end
return payer.additional_persons
else
return nil # or [] if you dont want to catch nil in your
controller/view
end
end

Cheers,
Tyler

OK. Thanks. A lot clearer. But why:
render :locals => { :collection => collection }
instead of:
@collection = person.additional_persons

And I have a block of code that has to be in update and create. How
would you do that?

It’s this code:

@declarations_payers = params[:declarations_payers]
@additional_persons = params[:additional_persons]

#First remove all declarations
@declaration.declarations_payers.destroy_all

#Daarna één voor één weer toevoegen
if @declarations_payers
  @declarations_payers.each_value { |user_id|

    #Add new object
    @declarations_payer = DeclarationsPayer.new

    #Set user_id variable (from post)
    @declarations_payer.user_id = user_id

    #Add aditional persons (from post)
    @declarations_payer.additional_persons =

@additional_persons[user_id]

    #Add the object to the declaration object
    @declaration.declarations_payers << @declarations_payer
  }
end

Thank you very much for all your help!

On Mar 14, 9:52 pm, Tyler MacDonald [email protected]

LeonB [email protected] wrote:

OK. Thanks. A lot clearer. But why:
render :locals => { :collection => collection }
instead of:
@collection = person.additional_persons

It’s a matter of style, really… the only technical difference is,
doing
@collection” sets an instance variable on your controller, whereas
passing
it via :locals makes it a local variable in the view (nothing to do with
the
controller).

And I have a block of code that has to be in update and create. How
would you do that?

I’d override the “save” method with:

def presave
[your code…]
end

def save
presave
super
end

Thank you very much for all your help!

No problem! :slight_smile:

Cheers,
Tyler