Real life use of multiple linked models in the same view


#1

I’m pretty new to Rails and now, in order to fully learn RoR, I’m trying
to replicate a project developed in Java using Hibernate+Tapestry.
Tapestry is based on components and you can really use objects mappings
in views like:

Example from the contact edit (view).

The same RoR code should look like:
<%= text_field ‘contact’, ‘name’ %>


<%= text_field ‘contact[office_phone]’, ‘value’ %>

I would preffer the patched version that should work like:
<%= text_field ‘contact.office_phone’, ‘value’ %>

Why to have other calling method than usual dot? the [] are not even
permitted by the W3C standard.
There is a patch at http://dev.rubyonrails.org/ticket/2053 but nobody
seamns to give it some credit. It’s 9 month old!!

The parameters are putted in a nested hash. The question is why the
above code doesn’t work on submission of the form.

The error reported is “Phone expected, got HashWithIndifferentAccess”

Parameters: {“commit”=>“Edit”, “id”=>“1”,
“contact”=>{“office_phone”=>{“text”=>“123”}, “name”=>“same name”}}

I’m looking for a beautiful solution with some magic in it just because
I want to keep my code as clean as possible. I’ve read the most RoR
books but none seams to target medium-advanced use of RoR and this
problems it’s clear not for the beginners.


Best regards,

Sorin Sbarnea


#2

Sorin Sbarnea wrote:

I would preffer the patched version that should work like:
<%= text_field ‘contact.office_phone’, ‘value’ %>

Why to have other calling method than usual dot? the [] are not even
permitted by the W3C standard.

They aren’t.

The [] were embraced in programming languages to auto-create associative
arrays or hashes from flat POST data. This wasn’t proposed by W3C
because they don’t specify what should server-side scripts do with POST
data. Why the []? Because they usually denote array or attribute
accessors (or hashes in Ruby).

I realize this is counter-intuitive in this particular case but it’s
very intuitive for most of the people doing various languages out there.

There is a patch at http://dev.rubyonrails.org/ticket/2053 but nobody
seamns to give it some credit. It’s 9 month old!!

The patch doesn’t say nothing about ‘.’ character instead of []?

The parameters are putted in a nested hash. The question is why the
above code doesn’t work on submission of the form.

The error reported is “Phone expected, got HashWithIndifferentAccess”

Well, it’s because you are trying to save what you get from POST (or
GET, doesn’t matter) data into an ActiveRecord association. The thing
is, what you get from ‘params’ is HashWithIndifferentAccess, and
ActiveRecord associations expect an ActiveRecord::Base subclasses (in
this case, the ‘Phone’ model). In other words: associations are made out
of models, so you cannot put everything into them.

I’m looking for a beautiful solution with some magic in it just because
I want to keep my code as clean as possible.

What you want (POST/GET data being saved instantly into models) seems
pretty dangerous to me. Not everything can be ‘magic’, even in Rails.
IMO, this will never be core, so the best solution for you is to take a
few days to study Rails internals, make yourself a plugin to add
features you need and use it in your project, even release it into
public.


Mislav


#3

Thanks for your reply and correct me if I’m wrong.

What is bad if the entire HashWithIndifferentAccess is translated to
model(s)?
I think that the best way is to include the security checks in any
attribute=() methods of the class and not in update_attributes method.

I think of this because controller is supposed to control the web pages
and for example if I want to create a gui or an WAP interface I would
like to have the same security rules for all controllers that edits the
same model.

(By security features I mean: user x can write y attribute, and so on…
almost any kinds of constrains)

After I manage how to make rails views similar to Tapestry. I want to
have minimum code in the Controller and View so I’ll be able to develop
better models with lots of business logic in them.

I suppose I could get the desired behavior by writing a better
update_attributes(). I don’t think this would be quite simple because
the edited model can be in various forms: new records (no id), existing
records (with id) or worse combinations of the first two.

The second (#2) problem would be: how can I receive all validation
messages on the page. Let’s say that Phone.value will generate and error
even if the Person is valid.

Still looking for a good Rails FAQ - best found until now was
http://rails.techno-weenie.net and the mailling list archive (>40,000
mesages - quite hard to find in them).


#4

Sorin Sbarnea wrote:

Thanks for your reply and correct me if I’m wrong.

What is bad if the entire HashWithIndifferentAccess is translated to
model(s)?

Well you can make a new entry out of params, that is the translation for
you. As you’ve noticed, that doesn’t fill in associated models, because
it doesn’t know how. You can override the write accessors for the
association, eg. attribute=() that takes a hash and creates a new one,
then adds it to the association.

The second (#2) problem would be: how can I receive all validation
messages on the page. Let’s say that Phone.value will generate and error
even if the Person is valid.

Read about the error object:
http://api.rubyonrails.com/classes/ActiveRecord/Validations.html

Still looking for a good Rails FAQ - best found until now was
http://rails.techno-weenie.net and the mailling list archive (>40,000
mesages - quite hard to find in them).

First, use the API, then the Wiki; if you are still confused refer to
the list, Rails Weenie IRC and blogs (Google search). A book on the side
can’t hurt, too :wink: