jonathangeiger / kohana-jelly

See the link below for the most up-to-date code
https://github.com/creatoro/jelly
MIT License
146 stars 34 forks source link

Problems on creating new entries with relationships #10

Closed raeldc closed 14 years ago

raeldc commented 14 years ago

I encountered this issue while creating Jelly Auth.

When saving objects with relationship, Jelly doesn't seem to pass the new insert_id. So this code wouldn't work because it passes NULL to user_id of roles_users:

    $user = Jelly::factory('user');
    $login = Jelly::factory('role', 'login');
    $admin = Jelly::factory('role', 'admin');

    $user->set(array(
        'username' => 'raeldc',
        'password' => 'testuser',
        'password_confirm' => 'testuser',
        'email'   => 'testuser@test.com',
        'roles'   => array($login->id, $admin->id)
    ));
    $user->save();

But it will work if I separate the saving of the roles relationship, and save it again.

    $user->set(array(
        'username' => 'raeldc',
        'password' => 'testuser',
        'password_confirm' => 'testuser',
        'email'   => 'testuser@test.com'
    ));

    $user->save();

    $user->roles = array($login->id, $admin->id));

    $user->save();

I tried other variations like using add(), but same problem, I have to save it twice

Also, notice that I'm manually specifying to pass the ID of $login and $admin models. That's because passing the model objects themselves doesn't seem to work.

Is this an issue or I'm just not getting how things should work?

Regards!

jonathangeiger commented 14 years ago

I'll take a look at this tonight. Is your jelly-auth repo up to date with this broken code? I want to test it.

jonathangeiger commented 14 years ago

There are a couple issues here.

  1. I fixed an issue where validation was causing the primary key to be set as NULL, because it was counted as changed data. This isn't a problem on SQLite (due to its incorrect implementation of auto-incrementing), but fails on MySQL.
  2. You're confusing the purpose of primary keys. In Model_Role, you have an id field and a name field. The name field is set as the primary key. This is all fine (though one might wonder what the purpose of the id field is). Then, in roles_users, you have the room_id column as an int. If Model_Role's primary key is the name field, which is a string, then role_id should be a string as well, because it refers to role's primary key.

Once you figure out what you want your primary key for roles to be, setting the roles relation on the user by just passing a loaded model will work.

Kohana's ORM Auth uses the id column as the primary key for roles, so you may want to follow that convention.

Hopefully that all makes sense and let me know that this all works for you (I got it working over here).

jonathangeiger commented 14 years ago

542b7fdd3aa6e77628ddf1ec0cdd352bc40f6b70

raeldc commented 14 years ago

Thanks Jonathan!

The reason why I made 'name' as my primary key is because I don't want to do this as my code:

$login = Jelly::factory('role', array('name' => 'login'));
$admin = Jelly::factory('role', array('name' => 'admin');

I just want to do a shortcut:

$login = Jelly::factory('role', 'login');
$admin = Jelly::factory('role', 'admin');

Is there a way to do the shortcut without having to set the primary_key as 'name'? In sprig I was able to do this by overriding the unique_key function.

Thanks!

jonathangeiger commented 14 years ago

Unfortunately, there isn't any way to do this currently.

raeldc commented 14 years ago

This is the same as Issue #10.

I think it deserves a new issue.

This is my code:

` $user = Model::factory('user'); $login = Jelly::select('role')->where('name', '=', 'login')->load(); $admin = Jelly::select('role')->where('name', '=', 'admin')->load();

    $user->set(array(
        'username' => 'test',
        'password' => 'testuser',
        'password_confirm' => 'testuser',
        'email'   => 'testuser@test.com',
        'roles' => array($login, $admin),
        'logins' => 0,
    ));

    $user->save();

`

This is the error message:

Database_Exception [ 1452 ]: Cannot add or update a child row: a foreign key constraint fails (`kohana3`.`roles_users`, CONSTRAINT `roles_users_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE) [ INSERT INTO `roles_users` (`role_id`, `user_id`) VALUES (NULL, 1), (NULL, 2) ]
banks commented 14 years ago

Incidentally, it is now possible to use any unique key in select(). Override the builder for the model and override the unique_key() function.

You no longer need name to be your primary key.