PhilWaldmann / openrecord

Make ORMs great again!
https://openrecord.js.org
MIT License
486 stars 38 forks source link

Model.create({}) and Model.new({}) autoAttributes = true #96

Closed claudioluciano closed 5 years ago

claudioluciano commented 5 years ago

Hey, i using autoAttributes = false andautoLoad = false, because i want to the more controls of my attributes, but the docs say const user = await User.create({login: 'philipp'}) but not work i think is pass null, here the error message:

Error: insert into "users" default values - null value in column "login" violates not-null constraint

will be nice if the project have some exemples the docs is great any way

i thinks this is not the right place to put this issue, but i cant find anything on in the SO

claudioluciano commented 5 years ago

same erro this way

const user = new User()
 user.login = 'philipp'
 user.first_name = 'Hey'
 user.last_name = 'Hoo'
 console.log(await user.isValid()) //true
 await user.save()
PhilWaldmann commented 5 years ago

Hi @claudioluciano if you disable attribute autoloading you have to define your attributes in your model manually via this.attribute().

However, if you enable autoloading, you could modify fields of your model as well.

claudioluciano commented 5 years ago

yeah even with attributes defined (this.attribute('first_name': String) ...), same issues. : /

PhilWaldmann commented 5 years ago

could you please post the whole source (at least the store config and model config)

claudioluciano commented 5 years ago

// store.js

const Store = require('openrecord/store/postgres')
const env = process.env.NODE_ENV

const config = require('./config')[env]

const store = new Store({
  host: config.host,
  port: config.port,
  user: config.username,
  password: config.password,
  database: config.database,
  autoAttributes: false,
  autoLoad: false,
  models: [
    require('./models/User.js')
  ],
  migrations: [
    require('./migrations/1234_create_users.js')
  ]
})
store.connect()
export default store

// User - Model

import Store from 'openrecord/store/postgres'

class User extends Store.BaseModel {
  static definition () {
    this.attribute('id', Number)

    this.attribute('login', String)

    this.attribute('first_name', String)

    this.attribute('last_name', String)

    // this is the `definition scope`
    this.validatesPresenceOf('first_name', 'last_name')
  }

  fullName () {
    return this.first_name + ' ' + this.last_name
  }
}

module.exports = User

// migrations

module.exports = function migration1234 () {
  this.createTable('users', function () {
    this.string('login', { not_null: true })
    this.string('first_name')
    this.string('last_name')
  })
}
async function start () {
  try {
    // add middleware ...
    await store.ready()

    console.log('Hey')
    // const users = await store.Model('user').create({ login: 'philipp', first_name: 'Hey', last_name: 'Hoo' })
    // console.log(users)

    //    const te = await User.create({ login: 'philipp', first_name: 'Hey', last_name: 'Hoo' })
    const te = new User()

    te.login = 'philipp'

    te.first_name = 'Hey'
    te.last_name = 'Hoo'

    console.log(await te.isValid())

    await te.save()

    const user = await User.find(1)

    console.log(user.id)

    // start express server
    app.listen(process.env.PORT, () => {
      console.log(`Example app listening on port ${process.env.PORT}!`)
    })
  } catch (error) {
    console.log(error)
  }
}

start()

basically exemples from the docs

PhilWaldmann commented 5 years ago

Hi Claudio,

please add readable and writable option to this.attribute.

The attribute methods takes a third options argument object with the following values:

  • writable: Make the attribute writable (e.g. record.my_attribute = 'foo'). Default true
  • readable: Make the attribute readable (e.g. record.my_attribute). Default true
  • default: Add a default value
  • track_object_changes: Track changes of a nested object. For objects only

Otherwise all your attributes are only "virtual" attributes.

PhilWaldmann commented 5 years ago

is it working for your?

claudioluciano commented 5 years ago

Sorry about the delay, so i put the writable and the readable like this: this.attribute('login', String, { writable: true, readable: true }) and still has the same issues, then i put it like this: this.attribute('login', String, { writable: true, readable: true, default: true, track_object_changes: true }) and still has the same issues...

PhilWaldmann commented 5 years ago

Hi Claudio,

I've just run some own tests with your examples and I've told you the wrong options! readable and writable is by default true, but there is an option which is not yet in the documentation: persistent. You have to set persistent to true, in order to tell openrecord that the attribute is stored inside your database. This happens automatically if you don't set autoAttributes to false.

Without persistent openrecord will treat these attributes as "virtual" attributes (wont be stored or read from the database).

Another thing that's missing in your example: The user id must be configured as primary in order for openrecord to know which column should be used with .find() (primary key!).

If you define persistent attributes, you also need to specify the store specific type ('string' instead of String), because database operations and filters are linked with these types. (e.g. ILIKE or BETWEEN)

Your model definition should look like this:

class User extends Store.BaseModel {
  static definition () {
    this.attribute('id', 'integer', {primary: true, persistent: true)

    this.attribute('login', 'string', {persistent: true})

    this.attribute('first_name', 'string', {persistent: true})

    this.attribute('last_name', 'string', {persistent: true})

    // this is the `definition scope`
    this.validatesPresenceOf('first_name', 'last_name')
  }

  fullName () {
    return this.first_name + ' ' + this.last_name
  }
}
claudioluciano commented 5 years ago

Hey Phil, {persistent: true} this works :) cool now I can keep working, thanks

PhilWaldmann commented 5 years ago

awesome!! =)