Complex associations

I’m building an association to version control edits of, essentially,
an array. I thus have a parent table, called, say “books”. This has
an id and a current edit version. There is another table called, say,
“chapters”. Each chapter belongs to a book and hence contains a
book_id. Each chapter also has an edit_version. So, if you want a
specific version of a book, you grab all chapters with a specified
edit_version.

Thus, most of the time we are only interested in chapters whose
edit_version matches the book edit_version.

One way or another, it seems clear that the book model wants to specify
that a book has_many chapters. It then seemed reasonable to suggest
that when eager fetching chapters for a book, we should attach a
:constraint to the has_many association to only fetch those chapters
with the same edit_version as the book.

This worked great until I went to save the book and chapters. At that
point, rails generated code that looked something like “update chapters
where id = 14 and (chapters.edit_version = books.edit_version)”.

This appears to be a bug. [Of course, the powers that control the bug
list don’t like bugs to be reported and don’t like trying to decide if
something is a bug or not and so rejected this suggestion that there
might be a bug out of hand. (Why do people make publicly accessible
bug lists if they are just going to ignore the crowdsourced bug reports
and get all snotty when people don’t want to read the entire bug
database to see if someone has commented on the issue before?)] The
specific bug here is: if you know exactly which record you are going
to update (and you do because you are specifying the ‘id’ field and the
whole point to that field is so that you can exactly reference a
specific record) why would you drag in the :constraints field from the
association?

Then there’s the enhancement request portion of this. If we have an
array hanging off of an object, and we typically want to work with a
small slice of the array, is it reasonable to have an association that
works with that type of structure?

And, finally, there’s the documentation enhancement request portion of
this. There must be a way to describe in the documentation the real
purpose of the :constraints field. It is not at all clear from the
documentation that you can use the constraint to force records in the
child table to match records in the parent table. It’s also not clear
that the constraint will be pulled in when updating records. So there
is some meta-reasoning and meta-logic that in someone’s mind about what
the constraint is and does that is not being documented.

On Friday 15 September 2006 10:54, cesium62 wrote:

that point, rails generated code that looked something like “update
chapters where id = 14 and (chapters.edit_version =
books.edit_version)”.

This appears to be a bug.

Does it hurt? If you’re using MySQL or PostgreSQL, try EXPLAIN
UPDATE … with the statement Rails generates and with the one you
think is correct. Then see what the DB makes of it.

[Of course, the powers that control the
bug list don’t like bugs to be reported and don’t like trying to
decide if something is a bug or not and so rejected this suggestion
that there might be a bug out of hand.

Would you mind to put the sarcasm aside? If you really think it is an
important bug, than provide a patch including tests. At least you could
give readers a link to the ticket you wrote so that we can judge for
ourselves.

Then there’s the enhancement request portion of this. If we have an
array hanging off of an object, and we typically want to work with a
small slice of the array, is it reasonable to have an association
that works with that type of structure?

That’s rather unspecific. Arguably, Rails already offers this with
conditions on associations.

And, finally, there’s the documentation enhancement request portion
of this. There must be a way to describe in the documentation the
real purpose of the :constraints field. It is not at all clear from
the documentation that you can use the constraint to force records in
the child table to match records in the parent table. It’s also not
clear that the constraint will be pulled in when updating records.

I don’t see a :constraints option (field?) anywhere, I take it you’re
talking of :conditions. What is indeed not documented, only alluded to
through examples in the API docs is that conditions can contain
references to instance variables.

So there is some meta-reasoning and meta-logic that in someone’s mind
about what the constraint is and does that is not being documented.

I’m rather sure you expect others to be lenient concerning your
confusion of :conditions with :constraints. That’s quite alright. But
you should be equally lenient when it comes to the failings of others.
Better still, go ahead and write the documentation you’re missing.
After all, someone’ got to do it.

Michael


Michael S.
mailto:[email protected]
http://www.schuerig.de/michael/

Yes, it hurts. When updating an association that uses conditions, one
cannot reference the parent table of the association because the syntax
is incorrect because the parent table is not joined on the update.
When selecting from a table, on can reference a parent table because
the join clause contains the parent table.

I did not use sarcasm. It is my continued experiece that developers,
despite providing mecanisms for the public to report bugs, will go out
of their way to avoid figuring out whether or not a bug is present much
less trying to mitigate the underlying problems that caused the bug to
be reported.

Rails does not provide support for array slices. As I explicitly
stated, you can read an array slice via conditions, but you cannot
update the array slice.

Since I clearly do not understand the documentation on conditions, how
could I possibly write clearer documentation?

Cs

This worked great until I went to save the book and chapters. At
that point, rails generated code that looked something like
“update chapters where id = 14 and (chapters.edit_version =
books.edit_version)”.

This appears to be a bug.

Does it hurt? If you’re using MySQL or PostgreSQL, try EXPLAIN
UPDATE … with the statement Rails generates and with the one you
think is correct. Then see what the DB makes of it.

On Sunday 17 September 2006 22:53, cesium62 wrote:

Yes, it hurts. When updating an association that uses conditions,
one cannot reference the parent table of the association because the
syntax is incorrect because the parent table is not joined on the
update. When selecting from a table, on can reference a parent table
because the join clause contains the parent table.

Apparently we’re talking past each other. My understanding was that you
complained about an extraneous condition in the SQL generated by
ActiveRecord. Thus I suggested to verify whether this additional
condition affects – “hurts” – performance in any way.

Fromyour reaction I take it that you had something else in mind. I have
a hunch what this might be, but it would be a lot easier if you
provided how the has_many association in question is declared and how
exactly you’re trying to update it.

I did not use sarcasm. It is my continued experiece that developers,
despite providing mecanisms for the public to report bugs, will go
out of their way to avoid figuring out whether or not a bug is
present much less trying to mitigate the underlying problems that
caused the bug to be reported.

You still haven’t provided the ticket # where all this has happened.
I’ve tried without success to find a matching bug report in the Rails
Trac. Also, don’t hold rails developers liable for experiences you’ve
had with “developers”. Keep in mind that presumably you are a developer
yourself.

Rails does not provide support for array slices. As I explicitly
stated, you can read an array slice via conditions, but you cannot
update the array slice.

You sure can

book.chapters_with_condition.each do |chapter|

end

What you cannot do is give an operation to an association and have it
applied to all its records in a single database statement. If you want
to do mass updates, you can use ActiveRecord::Base#update_all and write
the SQL yourself.

Michael


Michael S.
mailto:[email protected]
http://www.schuerig.de/michael/

In the Book model:
has_many :chapters, :condition “chapters.edit_version =
books.edit_version”

I haven’t provided a ticket number because I’d have to figure out where
I logged the bug and what the bug number is and I really don’t think
it’s germane to the conversation.

Yeah, sure, I could write my application in C too. In the context of
this conversation… Rails does not provide an association that manages
array slices. Should it?

Additionally, what is the meta-object that conditions were created to
handle? It isn’t an array slice.

And… why is the condition dragged into an update or delete
statement when the ‘id’ is known? The paradigm should be that ‘id’
uniquely identifies the record. Presumably the answer to this question
is related to the answer to the previous question.

Now, for my particular application, array slices aren’t necessary. If
I view the problem from a different point of view, I can state that the
‘book_version’ is usually the object that i’m interested in. A
‘book_version’ belongs to a book and can eager fetch that data, and a
book_version has many chapters which can also be eagerly fetched and
updated via the simple has_many association.
This does require declaring an extra table, but that probably
normalizes my data better.

So I may have answered my first question… array slices might not be
necessary because for any interesting slice, it might be better to pull
out a separate table and twist one’s point of view to be from the view
of the slice instead of the parent of the slice.

However, I still don’t understand the purpose of the condition nor why
the condition is dragged in when the id is known.