faustinoaq changed the topic of #amber to: Welcome to Amber Framework community! | https://amberframework.org | Developer happiness, productivity and bare metal performance | GH: https://github.com/amberframework | Docs: https://docs.amberframework.org | Gitter: https://gitter.im/amberframework/amber | IRC Logger: https://irclog.whitequark.org/amber | Amber::Server.start
<FromGitter> <Nicolab> Hi, ⏎ ⏎ When I save a user with `User.create()` wich have a duplicate key (email) error, Granite raise `Could not process User`. ⏎ Is it possible to have a more precise error? [https://gitter.im/amberframework/amber?at=5e17d870bdcaea189127c416]
<FromGitter> <Nicolab> for example the error returned by the DB
<FromGitter> <Blacksmoke16> not a fan of it but call `.errors` on your model
<FromGitter> <Blacksmoke16> 😐
<FromGitter> <Nicolab> Ok I test that, thanks @Blacksmoke16
<FromGitter> <Nicolab> It works, reassuring
<FromGitter> <Nicolab> :)
<FromGitter> <andrewc910> I seem to be having a problem with micrate. My error is `no such column: users.confirmed` ⏎ My migration looks like: ⏎ ⏎ ```code paste, see link``` ⏎ ... [https://gitter.im/amberframework/amber?at=5e17e13d0ba7b60f2052399d]
<FromGitter> <andrewc910> Oh, the db is sqlite3
<FromGitter> <Nicolab> I made a small helper (I will need others depending on the errors. Here, if it can be useful to someone: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ Until a better solution is found :) [https://gitter.im/amberframework/amber?at=5e17e1daa74ac85377823bdc]
<FromGitter> <Blacksmoke16> @andrewc910 hm? granite != micrate
<FromGitter> <Blacksmoke16> @Nicolab whats the background of what you're making? prob be a better way
<FromGitter> <andrewc910> @Blacksmoke16 Yes but i couldn't even find micrate docs.
<FromGitter> <andrewc910> At least on the micrate repo
<FromGitter> <Blacksmoke16> micrate just has up an down
<FromGitter> <Nicolab> @Blacksmoke16 When I created an entry in the DB and the DB generates an error, Granite does not return a specific error (for example duplicate key). So hard to know how to deal with the error and what response returned to the user.
<FromGitter> <Blacksmoke16> the granite migrator is mainly used internally for tests
<FromGitter> <Blacksmoke16> no i mean, what results in the request to create a user? someone submitting a registration form or an API request?
<FromGitter> <andrewc910> I found this little piece of info: `Pending -- 20160524163425_add_address_to_users.sql` which hints that altering tables may be possible? With that said, i downloaded on of the database explorer applications and my user table doesn't have the 3 columns i am trying to add which makes sense with the error i am getting.
<FromGitter> <Blacksmoke16> did you run it?
<FromGitter> <Blacksmoke16> wouldnt it be better to do some validation before trying to save the obj?
<FromGitter> <Nicolab> @Blacksmoke16 Yes on creation or an update with a duplicate key (user or other, the problem is the same)
<FromGitter> <Nicolab> @Blacksmoke16 yes of course, for the pre-validation of the data, I will do with a validator.
<FromGitter> <andrewc910> ```code paste, see link``` ⏎ ⏎ The confirmable migration is the migration is question. `amber db migrate` passes with the above output. Amber builds, then when i go to localhost:3000 i can't hit the root page with the error i provided earlier (column doesn't exist) [https://gitter.im/amberframework/amber?at=5e17e3b9c395034902726586]
<FromGitter> <Blacksmoke16> yea like try to lookup a user with that email, and if they exit, throw an exception
<FromGitter> <andrewc910> Oh i don't think the did you run it question was pointed at me haha my apologies!
<FromGitter> <Blacksmoke16> no it was
<FromGitter> <Blacksmoke16> check the migration table and see if that one is in it
<FromGitter> <andrewc910> Okay! I will also drop the db (just a test application), merge the 2 migrations and see if the create table also creates these new columns. Should help me identify where the problem is.
<FromGitter> <Blacksmoke16> im not too familiar with amber itself
<FromGitter> <Nicolab> @Blacksmoke16 for this case there and even others indeed there is a way to test with a request before making another (insert or update). But is not perfect because the DB can return errors from time to time, I prefer to catch it as much as possible to try to treat if possible
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <Nicolab> I try to find my habits (if possible) that I use in other languages.
<FromGitter> <Nicolab> @Blacksmoke16 what did you not understand in my message (my english is bad, so I may have translated badly)
<FromGitter> <Blacksmoke16> i mean if your DB is throwing errors randomly thats a problem
<FromGitter> <Blacksmoke16> doing a query on request to validate the the given model is valid is totally ok
<FromGitter> <Blacksmoke16> even if the query fails unexpectedly you can more easily handle that
<FromGitter> <Nicolab> ah no no
<FromGitter> <Nicolab> There may be others related to constraints or others (it can happen)
<FromGitter> <Nicolab> I misspoke ^^
<FromGitter> <Blacksmoke16> others meaning different errors that wouldnt be caught by doing that query?
<FromGitter> <Nicolab> also by checking the error (duplicate key), it avoids a request to the DB, just to check if I can do the 2nd. The duplicate key constraint is there for that too
<FromGitter> <Blacksmoke16> the constraint there is to protect the integrity of the data
<FromGitter> <Blacksmoke16> is there*
<FromGitter> <Nicolab> yes
<FromGitter> <Blacksmoke16> on update you'll need to fetch them anyway so it isnt an issue
<FromGitter> <andrewc910> Okay, results are in. With some minor syntax changes( i had a few errors), all 3 columns of the second migration work when placed in the first migration(the create command). However, whatever i try, nothing will alter the table and add columns.
<FromGitter> <Blacksmoke16> on create it would stop the error at a higher level so you know you'll only be working with valid models
<FromGitter> <Nicolab> update is better than select + update
<FromGitter> <Nicolab> (for me)
<FromGitter> <Blacksmoke16> @andrewc910 and you generated ran another migration?
<FromGitter> <Blacksmoke16> @Nicolab i disagree but ok
<FromGitter> <Nicolab> ok
<FromGitter> <Blacksmoke16> i dont think relying on raw db errors for validation is a good idea
<FromGitter> <andrewc910> @Blacksmoke16 Yeah, i tried everything 3 times to ensure my suspicions along with checking in a db explorer. Amber also works. Essentially, i merged the 2 migrations into 1, deleted the old 2, dropped db, migrated. Then i pulled it back into 2 migrations, drop, migrate, test(failed). Just repeated this a few times to make sure this was the case.
<FromGitter> <Blacksmoke16> is the first migration in the table, but not the second?
<FromGitter> <Blacksmoke16> or are both in there but nothing changed
<FromGitter> <andrewc910> I am sorry, i do not understand your question. Can you clarify a bit more?
<FromGitter> <Blacksmoke16> `micrate` creates a table in your db that stores which and when migration scripts were ran
<FromGitter> <Blacksmoke16> i dont remember what its called tho
<FromGitter> <Blacksmoke16> `migration_versions` or something like that
<FromGitter> <andrewc910> Oh! When it's 2 migrations(create table, alter table), micrate and the db explorer show 2 migrations however the 3 columns i am adding don't exist which is really strange.
<FromGitter> <Blacksmoke16> hm gotcha, yea i dont actually use amber so im out of ideas
<FromGitter> <Blacksmoke16> :/
<FromGitter> <andrewc910> No worries! Thank you for helping me explore this problem :) It's always nice bouncing ideas off someone :)
<FromGitter> <Nicolab> @andrewc910 me too, sorry :/
<FromGitter> <andrewc910> @Nicolab No worries :)
<FromGitter> <Nicolab> @Blacksmoke16 to explain why. ⏎ To put it simply, for my use case: `Could not process User.` is not enough, because why "could not"? Duplicate email, ok I know what to answer to the user. The current cluster node of the DB has a synchronization problem, ok I send the log to check that. ⏎ On thousands of requests per second, if I can avoid making a select before each insert or update to check if the email exists
<FromGitter> ... and let the DB answer me in return of the query, it is preferable for me. It's less greedy. ⏎ ⏎ There is surely better but it suits me :) [https://gitter.im/amberframework/amber?at=5e17e98c821b826f5a9558cb]
<FromGitter> <Nicolab> here is the `User` model but there are other cases (tables)
<FromGitter> <Blacksmoke16> how likely is it that there will be 1000s of users being created/updated per second tho?
<FromGitter> <Nicolab> > here is the `User` model but there are other cases (tables)
<FromGitter> <Nicolab> not 1000 lol
<FromGitter> <Blacksmoke16> right, im not saying that you should *always* query before saving/inserting but in this case it makes sense
<FromGitter> <Nicolab> ok, I understand
<FromGitter> <Blacksmoke16> way i look at it, one query early on in the request can prevent other logic from running as well
<FromGitter> <Blacksmoke16> i.e. you create other records, then go to save the user, oh it fails, now you have orphaned data
<FromGitter> <Blacksmoke16> (in that case the user would have to be defined first but you get the idea)
<FromGitter> <Nicolab> no because contraint. Other data after (and + transaction)
<FromGitter> <Blacksmoke16> unless you wrap everything in a transaction, you dont have a way to revert the changes made to other records that succeeded before the failure of the user
<FromGitter> <Blacksmoke16> 👍 transaction would be helpful yea
<FromGitter> <Nicolab> :)
<FromGitter> <Nicolab> Well, I'm going to bed, it's 4 am here (in France). I have to get up in 5 hours. ⏎ Big up to the learning of another language and its ecosystem, it stimulates 😁
<FromGitter> <Nicolab> and thanks again @Blacksmoke16 👍
<FromGitter> <Blacksmoke16> np, o/
robacarp has quit [Ping timeout: 265 seconds]
<FromGitter> <damianham> @Nicolab it might that selects before updates are less efficient because of multiple db queries but placing validations in your model means that you can send useful error messages back to your user and the error messages can be located next to the errant field on a form. All of that functionality is already built into Amber. You can still have database constraints to ensure data integrity at the database level.
<FromGitter> ... The validation features are there to make your life as a developer easier.
<FromGitter> <Nicolab> @damianham Indeed, I also use the validations (in other languages), I will also use with Crystal (I'm just starting out in Crystal)
<FromGitter> <Blacksmoke16> depending on the type of validations you need, https://github.com/Blacksmoke16/assert/ is an option
<FromGitter> <Blacksmoke16> should work with granite models
<FromGitter> <Blacksmoke16> https://github.com/amberframework/granite/issues/358#issue-493555982 shows an example of how it could work
<FromGitter> <Blacksmoke16> would just have to be sure to setup the logic that runs validations
<FromGitter> <Nicolab> Thanks, I'd seen it.
<FromGitter> <Hareem-E-Sahar> Does this room have a bot integration?
<FromGitter> <Blacksmoke16> not as far as i know
<FromGitter> <Nicolab> I can't find a way to manage the enum with Granite. ⏎ ⏎ Postgres SQL type: ⏎ ⏎ ```code paste, see link``` ... [https://gitter.im/amberframework/amber?at=5e1908e90aba1f0d80117e55]
<FromGitter> <Blacksmoke16> pg types uses Bytes under the hood
<FromGitter> <Blacksmoke16> how are you trying to assign to it?
<FromGitter> <Blacksmoke16> trying to set `lang`*
<FromGitter> <Nicolab> From a Hash User.create(ctx.params.body.to_h)
<FromGitter> <Blacksmoke16> and what does that hash look like?
<FromGitter> <Blacksmoke16> i bet its "fr"
<FromGitter> <Blacksmoke16> is the body a JSON string or?
<FromGitter> <Blacksmoke16> or form data*
<FromGitter> <Nicolab> yes `fr`, form data and also in direct like: ⏎ ⏎ ```User.create({"lang": "fr"}.to_h)``` [https://gitter.im/amberframework/amber?at=5e190dab65540a529af5f3f6]
<FromGitter> <Nicolab> the body a JSON
<FromGitter> <Nicolab> with Postman for the test
<FromGitter> <Blacksmoke16> yea the problem there is there is no conversion that happens for enum values when coming from a hash
<FromGitter> <Nicolab> how can i do then?
<FromGitter> <Blacksmoke16> i personally am against using a hash to new up an object
<FromGitter> <Blacksmoke16> option 1, define a a constructor that accepts a `HTTP::FormData` obj
<FromGitter> <Blacksmoke16> option 2, if you are using JSON, `User.from_json`
<FromGitter> <Blacksmoke16> option 3, reopen `Granite::Type` and add a new method to handle the conversion
<FromGitter> <Blacksmoke16> like
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/amberframework/amber?at=5e190f0ecb2aaa2d7818eab5]
<FromGitter> <Blacksmoke16> id push for option 1, when/if https://github.com/amberframework/granite/pull/370 ever gets merged it'll make this stuff more explicit
<FromGitter> <Nicolab> Thank you. ⏎ I'm looking at your PR. Why don't you recommend hash?