Strange behavior with MAToManyRelationDescription

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Strange behavior with MAToManyRelationDescription

Jason Johnson-5
Hello all,

I am building a form that consists of two components, e.g. House and
Person.  For each of these, when a new one is created I register it.
I have a manager class that displays these using:

   MAToManyRelationDescription new
       classes: (Array with: House);
       label: 'Houses';
       accessor: (MASelectorAccessor new
                        readSelector: #houses;
                        writeSelector: nil;
                        yourself);
                default: Array new;
                priority: 20;
                yourself

People is similar.  The Manager class is a form, but with no buttons
as it is only needed to let the add buttons work on these relation
descriptions.  The accessor shown here, houses just calls "House
instances" to get currently registered houses.  I subclass
MACheckedMemento and create a custom memento that simply overrides the
#push: method to see if the object is new (no members will be set) and
if so, registers the object after called "super push:".

Everything is fine except for Houses, after I create a new hause the
main display always shows 2.  If I leave the page and visit new I see
only one.  I have looked around but I dont see how this is happening.

Any ideas?

_______________________________________________
SmallWiki, Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with MAToManyRelationDescription

Lukas Renggli-2
Hi,

> I am building a form that consists of two components, e.g. House and
> Person.  For each of these, when a new one is created I register it.

what do you register? And -- when you create new ones -- you have more  
than two components? I don't quite get it ...

> I have a manager class that displays these using:

That's the form?

>   MAToManyRelationDescription new
>       classes: (Array with: House);
>       label: 'Houses';
>       accessor: (MASelectorAccessor new
> readSelector: #houses;
> writeSelector: nil;
> yourself);
> default: Array new;
> priority: 20;
> yourself
>
> People is similar.  The Manager class is a form, but with no buttons
> as it is only needed to let the add buttons work on these relation
> descriptions.  The accessor shown here, houses just calls "House
> instances" to get currently registered houses.  I subclass
> MACheckedMemento and create a custom memento that simply overrides the
> #push: method to see if the object is new (no members will be set) and
> if so, registers the object after called "super push:".

Why don't you write your manager class manually and display the  
editors for houses and persons as children? You can use the #onAnswer:  
handler of the Magritte components to get notified when the user hits  
add (save).

I don't quite understand why you need MAToManyRelationDescription and  
a custom MACheckedMemento.

Cheers,
Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch


_______________________________________________
SmallWiki, Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with MAToManyRelationDescription

Jason Johnson-5
Sorry, I was in a hurry because I had to get off the train. :)

Ok, I have a Person class and a House class.  Each of these has a
class side method called #register: that stores the instance in an
ordered collection of the class side.  Person and House both have full
descriptions and are capable of displaying themselves, so the
"manager" class just allows one to make many of these.

So the use case is, you see the first page, it has a list of Persons
and a list of Houses, these are queried from the instances registered
with the class (i.e. in the class side collection variable).  The user
clicks "add" on, say, Person.  Now they get the Person page, as
described by the Person class, they type in there information and
click "Save".

This is where I need the custom memento (and tell me if I'm doing this
wrong):  If you click save that winds up calling "commit" on the
memento and actually writing the data to the object, but this new
object wont be registered in the class side collection (and therefor
will simply cease to exist when this session expires).  So my custom
memento simply lets everything work as normal and then calls "Person
register: self model" to get the new object registered.

The problem happens when "save" returns on Person and you go back to
the manager page.  You see your nice new Person in the report table as
expected, but right below is the same Person again!  And if you edit
either one the changes reflect in both.  And the really hairy thing
is, even though House is almost exactly the same in every way (I can
find no relevant difference) it doesn't have this behavior.

(couple of comments below as well)

On Nov 20, 2007 9:36 PM, Lukas Renggli <[hidden email]> wrote:
>
> That's the form?

Below was the description that the manager uses to show the list of Houses.

> >   MAToManyRelationDescription new
> >       classes: (Array with: House);
> >       label: 'Houses';
> >       accessor: (MASelectorAccessor new
> >                       readSelector: #houses;
> >                       writeSelector: nil;
> >                       yourself);
> >               default: Array new;
> >               priority: 20;
> >               yourself
> >
> Why don't you write your manager class manually and display the
> editors for houses and persons as children? You can use the #onAnswer:
> handler of the Magritte components to get notified when the user hits
> add (save).

Hrm, I thought that's what I was doing.  The above description is
saved in the manager as a component under houseComponent and is
returned from the children method of the manager.  But I will go look
up uses of onAnswer to try and figure out what you mean.

_______________________________________________
SmallWiki, Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with MAToManyRelationDescription

Lukas Renggli-2
> Ok, I have a Person class and a House class.  Each of these has a
> class side method called #register: that stores the instance in an
> ordered collection of the class side.  Person and House both have full
> descriptions and are capable of displaying themselves, so the
> "manager" class just allows one to make many of these.

Ok, got it.

> This is where I need the custom memento (and tell me if I'm doing this
> wrong):  If you click save that winds up calling "commit" on the
> memento and actually writing the data to the object, but this new
> object wont be registered in the class side collection (and therefor
> will simply cease to exist when this session expires).  So my custom
> memento simply lets everything work as normal and then calls "Person
> register: self model" to get the new object registered.

Sure that's a possibility, but why not use the return value if you are  
using #call: or set an #onAnswer: handler if you are using composition?

So in your manager you have something along:

   house := self call: House new asComponent.
   house ifNotNil: [ House register: house ].

or (in case of composition):

   editor := House new asComponent onAnswer: [ :house |
     house ifNotNil: [ House register: house ].
     editor := nil ]

> The problem happens when "save" returns on Person and you go back to
> the manager page.  You see your nice new Person in the report table as
> expected, but right below is the same Person again!  And if you edit
> either one the changes reflect in both.  And the really hairy thing
> is, even though House is almost exactly the same in every way (I can
> find no relevant difference) it doesn't have this behavior.

Looks like your memento method gets called twice? Why not check if the  
object is already present? Why not use a Set then?

Cheers,
Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch


_______________________________________________
SmallWiki, Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with MAToManyRelationDescription

Jason Johnson-5
Thanks for the response.  Sorry I was so long in getting back to this.
 December is a pretty insane month for me at the moment. :)  (comments
below)

On Nov 29, 2007 8:00 AM, Lukas Renggli <[hidden email]> wrote:

>
> > This is where I need the custom memento (and tell me if I'm doing this
> > wrong):  If you click save that winds up calling "commit" on the
> > memento and actually writing the data to the object, but this new
> > object wont be registered in the class side collection (and therefor
> > will simply cease to exist when this session expires).  So my custom
> > memento simply lets everything work as normal and then calls "Person
> > register: self model" to get the new object registered.
>
> Sure that's a possibility, but why not use the return value if you are
> using #call: or set an #onAnswer: handler if you are using composition?

Well, the thing is, I'm using a shortcut here. :)  The manager just
basically provides a web page that allows one to use the descriptions
of other two.  It doesn't use call because it doesn't want anything
back.  Maybe an example will make it clearer.

Manager>>renderContentOn: html
  html render: self component

>>component
  ^ component ifNil: [
                        component := ((self housesComponent, self peopleComponent)
                                asComponentOn: self)
                                addForm: #();      "I don't want any buttons on this form since
submitting it would make no sense, I do nothing with the values here"
                                yourself ]               "since the House and Person classes
manage their own instances"

>>housesComponent    "gives a nice view for managing houses"
        ^ MAToManyRelationDescription new
                classes: (Array with: House);
                label: 'Houses';
                accessor: (MASelectorAccessor new
                        readSelector: #houses;
                        writeSelector: nil;
                        yourself);
                default: Array new;
                priority: 20;
                yourself

>>peopleComponent  "ditto for people"

        ^ MAToManyRelationDescription new
                classes: (Array with: Person);
                label: 'People';
                accessor: (MASelectorAccessor new
                        readSelector: #people;
                        writeSelector: nil;
                        yourself);
                default: Array new;
                priority: 20;
                yourself

>>houses
  ^ House instances

>>people
  ^ Person instances

> So in your manager you have something along:
>
>    house := self call: House new asComponent.
>    house ifNotNil: [ House register: house ].
>
> or (in case of composition):
>
>    editor := House new asComponent onAnswer: [ :house |
>      house ifNotNil: [ House register: house ].
>      editor := nil ]

This I tried.  It doesn't work when I put it on #houseComponent or
#storeComponent since I'm using #, and when I put it in #component it
seems to be ignored.

> > The problem happens when "save" returns on Person and you go back to
> > the manager page.  You see your nice new Person in the report table as
> > expected, but right below is the same Person again!  And if you edit
> > either one the changes reflect in both.  And the really hairy thing
> > is, even though House is almost exactly the same in every way (I can
> > find no relevant difference) it doesn't have this behavior.
>
> Looks like your memento method gets called twice? Why not check if the
> object is already present? Why not use a Set then?

Ah but I do.  Since I'm in the momento I have to check if there
already exists an object that has the same value as the ones cached in
the momento.  I had a #break call in the momento and I'm sure it's not
getting called twice, which wouldn't hurt anything if it did.  It
seems like the MA machinery is doing some caching of some kind.  The
part that baffles me is that it doesn't happen for Houses, even though
they are fundamentally exactly the same.

I suppose this would be so much easier if I just let Magritte manage
everything completely, but this code gets managed in other places then
on these web pages.

>
>
> Cheers,
> Lukas
>
> --
> Lukas Renggli
> http://www.lukas-renggli.ch
>
>
> _______________________________________________
> SmallWiki, Magritte, Pier and Related Tools ...
> https://www.iam.unibe.ch/mailman/listinfo/smallwiki
>

_______________________________________________
SmallWiki, Magritte, Pier and Related Tools ...
https://www.iam.unibe.ch/mailman/listinfo/smallwiki