Git Product home page Git Product logo

lucid's Introduction

@adonisjs/lucid


gh-workflow-image npm-image license-image

Introduction

SQL ORM for AdonisJS built on top of Knex. Comes with a db query builder, Active record ORM, migrations, seeders and model factories.

Official Documentation

The documentation is available on the Lucid website

Contributing

One of the primary goals of AdonisJS is to have a vibrant community of users and contributors who believes in the principles of the framework.

We encourage you to read the contribution guide before contributing to the framework.

Run tests locally

Easiest way to run tests is to launch the redis cluster using docker-compose and docker-compose.yml file.

docker-compose up -d
npm run test

Code of Conduct

In order to ensure that the AdonisJS community is welcoming to all, please review and abide by the Code of Conduct.

License

AdonisJS Lucid is open-sourced software licensed under the MIT license.

lucid's People

Contributors

alyxsqrd avatar belozer avatar benallfree avatar benjamincanac avatar brkn avatar craytor avatar greenkeeper[bot] avatar julien-r44 avatar lookingit avatar mastermunj avatar mathieuh avatar maximemrf avatar mcsneaky avatar mdsadique-inam avatar melchyore avatar mul14 avatar mzanggl avatar othierry avatar pokedpeter avatar ptrpiero avatar radmen avatar reptiluka avatar romainlanz avatar shahshahid81 avatar snyk-bot avatar tahul avatar targos avatar temasm avatar thetutlage avatar yodosan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lucid's Issues

Truncating table in Factory doesn't work

yield Factory.get('favourites').reset();
yield Factory.get('favourites').create(500);

Shows

Error: delete from - SQLITE_ERROR: near " ": syntax error

error. #55 fixes the issue.

Support data migrations

Currently, Adonis only supports schema migrations which only modify the schema of the database.

It would be convenient to also be able to run data migrations which modify the contents of the database.

I can already do this by using the Database provider in a migration but it seems out of place and I can't use co.

Migration rollback does not work if constraints are used.

I created migrations for my tables users, categories and category_user. I create references in CategoryUser. If i want to rollback it crashs with drop table users - ER_ROW_IS_REFERENCED_2: Cannot delete or update a parent row: a foreign key constraint fails because it tries to remove the user table first. Shouldn't it run backwards through the migrations?

// 1457269462275_create_users_table.js
class User extends Schema {
  up () {
    this.create('users', function (table) {
      table.increments('id')
      table.string('username').unique()
    })
  }
  down () {
    this.drop('users')
  }
}

// 1457269765358_create_categories_table.js
class Category extends Schema {
  up () {
    this.create('categories', function (table) {
      table.increments('id')
      table.string('name')
    })
  }
  down () {
    this.drop('categories')
  }
}

// 1457270359783_create_category_user_table.js
class CategoryUser extends Schema {
  up () {
    this.create('category_user', function (table) {
      table.increments('id')
      table.integer('user_id').unsigned().references('id').inTable('users')
      table.integer('category_id').unsigned().references('id').inTable('categories')
    })
 }
  down () {
    this.table('category_user', function (table) {
      table.dropForeign('user_id')
      table.dropForeign('category_id')
    })
    this.drop('category_user')
  }
}

As a workaround i tried to reverse the difference in _getDifference() if the direction is down and it worked.

Problem with beforeUpdate hook

I have a problem with beforeUpdate hook. There is a method Slugify, that supposed to process title and set category slug, while working in beforeCreate, the same method gives no luck in beforeUpdate.

// boot method in model
static boot () {
  super.boot()
  this.addHook('beforeCreate', 'Category.slugify')
  this.addHook('beforeUpdate', 'Category.slugify')
}
// slugify method by itself
Category.slugify = function * (next) {
  this.slug = slug( this.title )
  yield next
}
// controller update method
let data = request.only(['title', 'published'])
let category = yield Category.findBy('id', request.param('id') )
category.title = data.title
category.published = data.published
yield category.save()

Model instance delete() function defaults to "id" primary key column name

Using AdonisJS 3.0

I defined an Employee class:
class Employee extends Lucid {

static get primaryKey () {
    return **'employee_id';**
} 

[...]

In my EmployeeController class destroy function
[...]
const employee = yield Employee.find(2); // hard-coded ID for test
yield employee.delete();
[...]

Sqlite3 debug statement:
{ method: 'update',
options: {},
bindings: [ '2016-09-27 00:15:46', '2016-09-27 00:15:46', 2 ],
sql: 'update "employees" set "deleted_at" = ?, "updated_at" = ? where "id" = ?' }

Problems while extending classes inside services

Hi,

i have problems with extend classes with services. I use many classes which extended from BaseBMC which is also extend from BaseRemote. I cannot find the reason for my problem and thought this can be a problem in Lucid.

All classes/services will be called scheduled. Each service called the "getCredentialsObject" in BaseRemote - sometimes exactly the same time.
Every getCredentialsObject-call will be successful, the result is always a valid credentialobject in the console output of BaseRemote.
But i the class TicketService sometimes the credentialobject is false.

Where is my fault?

'use strict';

const Database = use('Database');                 
const SysLogins = use('App/Model/SysLogins');     
const SysLoginsLogs = use('App/Model/SysLoginsLogs');  
const Helpers = use('Helpers');

const _ = require('lodash');              
const CatLog  = require('cat-log');             


class BaseRemote {

  constructor (prop) {
    this.prop = prop;

    this.log = new CatLog(prop.logCat || 'BaseRemote-Service');

    this.storagePath = Helpers.storagePath();
    this.storeLastResult = prop.storeLastResult || false;
    this.Database = Database;
    this.sysLogins = SysLogins;
    this.sysLoginsLogs = SysLoginsLogs;
    this.helpers = Helpers;
    this._ = _;
  }

  * getCredentialsObject (system){
    var cObj = yield this.sysLogins.new().where('name', '=', system).first().fetch();  // must use new()!!!
    if (!cObj.size()) {
      throw new Error('System credentials not available');
    }

    cObj = cObj.toJSON();

    if (!cObj.enabled) {
      return false;
    }

    console.log('BaseRemote', cObj);    //   <---   here every call is ok
    return cObj;
  }
}

module.exports = BaseRemote;
'use strict';

const BaseRemote = use('App/Services/BaseRemote');
class BaseBMC extends BaseRemote {

  * execute (title, options, sql) {
    let me = this;

    return new Promise(function (resolve, reject)  
        resolve([{
        foo : 'bar'
    }]);
    });
  }
  // [...]
}

module.exports = BaseBMC;
'use strict';

const BaseBMC = use('App/Services/BaseBMC');

class TicketService extends BaseBMC {

  constructor () {
    // [...]
    super(prop);
  }

  * getTickets() {
    var me = this,
        sql,
        credentialsObject;

    credentialsObject = yield me.getCredentialsObject('TicketService');    
    console.log('TicketService', credentialsObject);    // <--- sometime false  
    if (!credentialsObject) {
      me.log.info('credentials not available or systemservice not enabled');
      return [];
    }


    return true
  }
}

module.exports = TicketService;

Changes to model in beforeUpdate hooks not persisting to model when saved

Consider password encryption per : Basic Example

Works perfectly using beforeCreate hook
However, when using beforeUpdate hook, with the same hook method, the unencrypted password is persisted to the db when using using model.save() from the controller, even though this.password in the hook shows encrypted value

// controller
const user = yield User.findBy('id', 1)
user.password = 'password_1'
yield user.save()

// hook, which DOES get called
User.encryptPassword = function * (next) {
  if (this.password) {
    this.password = yield Hash.make(this.password)
  }
  console.log('encryptPassword', this.password) // '$2a$10$s8K2HOKlSISYTxvPpRJRJOmBZzZWIWfx7k1Tx6bC7r/MCRROGa7jm'
  yield next
}

// password persisted to the db = 'password_1'

Sequelize

Any chance of getting Sequelize as an option for migrations as well? It offers a more friendly API specially when it comes to NxN relationships like this.

'set' on proxy: trap returned falsish for property

Hello, I have tried to follow from the documentation, but I keep getting this error.

TypeError (500)
'set' on proxy: trap returned falsish for property 'program_name'
// Controller
const Program = use('App/Model/Program');

class ProgramController {

    * index (request, response) {
        let program = new Program();
        program.program_name = "program 1";
        yield program.create();

        response.send('index');
     }
}

// ... migration
this.create('programs', function (table) {  
  table.increments('id')                 
  table.string('program_name', 255);  
  table.timestamps() 
  table.timestamp('deleted_at')  
}) 

problems when access a model twice exactly the same time

From @rbartholomay on February 11, 2016 15:36

Hi,

i use the node-scheduler inside an adonis app. I define my ServiceProvider like this:

const ServiceProvider = require('adonis-fold').ServiceProvider;

class ScheduleProvider extends ServiceProvider {

  * register () {

    this.app.bind('App/Schedule', function (app) {
      return require('node-schedule');
    })
  }
}

module.exports = ScheduleProvider;

All my jobs using co and starts with the same code block like this:

Schedule.scheduleJob('0 */5 7-21 * * 1-6', function () {

  // because yield must be at top-level we need co for wrapping
  co(function* () {

    // fetch the Credentials
    let sysLoginOptions = yield SysLogins.where('name', '=', 'MySystem').first().fetch();
    if (!sysLoginOptions.size()) {
      throw new Error('System credentials not available');
    }


    sysLoginOptions = sysLoginOptions.toJSON();

When two or more jobs start exactly the same time i get the following error:

[Error: System credentials not available] 'Error: System credentials not available\n at C:\\Users\\rb\\Sourcen\\ad\\app\\CronJobs\\IDR.js:55:13\n at next (native)\n at onFulfilled (C:\\Users\\rb\\Sourcen\\ad\\node_modules\\co\\index.js:65:19)\n at tryCatcher (C:\\Users\\rb\\Sourcen\\ad\\node_modules\\bluebird\\js\\main\\util.js:26:23)\n at Promise._settlePromiseFromHandler (C:\\Users\\rb\\Sourcen\\ad\\node_modules\\bluebird\\js\\main\\promise.js:507:31)\n at Promise._settlePromiseAt (C:\\Users\\rb\\Sourcen\\ad\\node_modules\\bluebird\\js\\main\\promise.js:581:18)\n at Promise._settlePromises (C:\\Users\\rb\\Sourcen\\ad\\node_modules\\bluebird\\js\\main\\promise.js:697:14)\n at Async._drainQueue (C:\\Users\\rb\\Sourcen\\ad\\node_modules\\bluebird\\js\\main\\async.js:123:16)\n at Async._drainQueues (C:\\Users\\rb\\Sourcen\\ad\\node_modules\\bluebird\\js\\main\\async.js:133:10)\n at Immediate.Async.drainQueues [as _onImmediate] (C:\\Users\\rb\\Sourcen\\ad\\node_modules\\bluebird\\js\\main\\async.js:15:14)\n at processImmediate [as _immediateCallback] (timers.js:383:17)'

if i let start the jobs with one second difference all runs fine:

Schedule.scheduleJob('0 */5 7-21 * * 1-6', function () {
 [...]

Schedule.scheduleJob('1 */5 7-21 * * 1-6', function () {
 [...]

Schedule.scheduleJob('2 */5 7-21 * * 1-6', function () {
 [...]

Schedule.scheduleJob('3 */5 7-21 * * 1-6', function () {
 [...]

Copied from original issue: adonisjs/core#96

Trashed rows are being retrieved

When I try something like

let row = yield Opinion
              .where('user_id', request.param('id'))
              .where('game_id', request.input('game_id'))

I get some entries which have deleted_at not null. I need to use .whereNull('deleted_at') in order to get the expected behaviour.

How do you close a Database Query in Ace Commands

const Database = use('Database')

const users = yield Database.connection('mysql').table('users').select('*');
I get my data but the database connection is still open so the command doesn't stop running.

Using Lucid i don't face any issue and can close with Model.activeConnection.client.destroy().

Issues with relations

Hello,

I have a Model, which i want to create and then create a related item of this model. The funny part is, that the creation of both items works, but they are not associated. Here are my models.

Customer:

'use strict'

 const Lucid = use("Lucid")

 class Customer extends Lucid {

  static get table () {
    return "customer"
  }

  static get softDeletes () {
    return false
  }

  static get timestamps () {
    return false;
  }

  static get primaryKey () {
    return 'CustomerId'
  }

  address () {
    return this.hasOne('App/Model/Address', 'AddressId','AddressId');
  }
}
module.exports = Customer

Address:

'use strict'

const Lucid = use("Lucid")

class Address extends Lucid {

  static get table () {
    return "address";
  }

  static get softDeletes () {
    return false
  }

  static get primaryKey () {
    return 'AddressId'
  }

  static get timestamps () {
    return false;
  }

  customer () {
    return this.belongsTo('App/Model/Customer', 'AddressId', 'AddressId');
   }

  position () {
    return this.hasOne('App/Model/Position','PositionId', 'PositionId');
  }
}

module.exports = Address

Controller-Code

let input = request.all();
const customer = new Customer();
customer.DeliveryFrom = input.DeliveryFrom;
customer.DeliveryTo = input.DeliveryTo;
customer.HasRamp = input.HasRamp;
customer.HasStapler = input.HasStapler;
customer.HasTrailer = input.HasTrailer;
customer.Name = input.Name;
customer.Notices = input.Notices;

yield customer.create();
yield customer.address().create({
  City: input.Address.City,
  Country: input.Address.Country,
  Number: input.Address.Number,
  Street: input.Address.Street
});

yield customer.address().position().create({
  Latitude: input.Address.Position.latitude,
  Longitude: input.Address.Position.longitude
});

response.status(200).send();

Aggregate functions on lucid relations don't respect relation

e.g.,

I can query by a hasManyThrough relation:

yield location
  .experiences()
  .fetch();

But if I try to count like so:

yield location
  .experiences()
  .count();

Then, it gives me the count for all experiences, not just experiences related to that relation.

The SQL generated is select count(*) from "experiences but it should be something like select count(*) from "experiences" inner join "customers" on "customers"."id" = "experiences"."customer_id" where "customers"."location_id" = 2;

Thanks!

Migrations

Is there a standard way to work with Lucid and migrations? I couldn't find anything in the docs.

this.belongsTo is not a function

I'm trying the basic example shown in the docs but I'm getting the title error. The code I'm running is as follows:

'use strict'

const Lucid = use('Lucid')

class Opinion extends Lucid {
  user () {
    return this.belongsTo('App/Model/User')
  }
}

module.exports = Opinion

And using like:

let opinion = new Opinion
opinion.user().associate(user)

Should I create it before associating?

Not saving multiple associations

When trying to add multiple belongsTo relationships, only the last one is actually saved.

For instance:

let user = yield User.find(1)
let game = yield Game.find(1)

let opinion = new Opinion

opinion.game().associate(game)
opinion.user().associate(user)

yield opinion.create()

Will add a tuple in the DB which has user_id = 1 and game_id = NULL, whereas reversing the association lines will add user_id = NULL and game_id = 1.

Using lucid by it self

How can you use lucid by it self? I love Adonis' migrations and model setup and would love to use it with my application.

I just need the migrations and models with my simple web application. Adonis ships with a lot of amazing things but many of them I don't need, I only need the migrations and models. How can I implement the migrations and models with something like a Koa application?

Is there a way to load all of the models and write migrations without having to use Adonis? I can't seem to find any documentation which explains how you can implement it as a separate module.

Lucid fails to return data when same nested model used more than once

When querying via Lucid for a primary model Order, which has multiple joins to another model Customer, (eg. a company, or a contact (person)), each of which then has multiple joins to another model ContactInfo (eg, phone numbers, email addresses), Lucid fails to return data for subsequent models joined in the with() array.

class Order {
  // ... 
  // company who the order is for
  customer () {
    return this.belongsTo('App/Model/Customer') // joins as default customer_id
  }

  // companies' contact assigned to the order
  contact () {
    return this.belongsTo('App/Model/Customer', 'id', 'contact_id')
  }
  // ...
}

And then each type of customer (company, contact) can have multiple ContactInfo, of different types (phone, email)

class Customer {
  // ... 
  // main email
  email () {
    return this.hasOne('App/Model/ContactInfo', 'id', 'model_id').where({ type: 'email', is_primary: 1, model: 'customer' })
  }
  // main phone
  phone () {
    return this.hasOne('App/Model/ContactInfo', 'id', 'model_id').where({ type: 'phone', is_primary: 1, model: 'customer' })
  }
  // ...
}

The bug shows itself when requesting queries with 'customer.phone', 'contact.phone', 'contact.email', eg:

        with([
          'customer.phone',
          'contact.phone',
          'contact.email',
          // - all the below records come back as null
          'inside',
          'outside',
          'billing',
          'billing_address',
          'shipping',
          'shipping_address',
          'meta',
          'items.meta'
        ])

In this case, any other subsequent relations after the multiple Customer->ContactInfo relations in the with() array come back as null. Removing in the multiple joins to Customer->ContactInfo restores the other relations.

I'm unable to determine where in Lucid this fails!

Query caching issues (?)

Following scenario:

var User = use('App/Model/User')

 User.where('email','=',request.param('email')).first().then(function(user){
      response.json(user);
       console.log("GETTING ONE USER VIA It's email");
       console.log(JSON.stringify(user));      
});

User.all().then(function(result) {
      console.log("GETTING ALL USERS ? -> NOPE returns same result as in first query");
      console.log(JSON.stringify(result));
})

User.all().then(function(result) {
  console.log("GETTING ALL USERS AGAIN -> returns a list but only item is the user we got initially");
  console.log(JSON.stringify(result));
  User.all().then(function(result) {
    console.log("GETTING ALL USERS YET AGAIN -> this really gives me all users");
    console.log(JSON.stringify(result));

  })

})

This is all happening in a controller action, however as my console.logs describe there is an issue of getting a fresh query started. What am I doing wrong ?

Using 'with' for belongsTo columns, on a where clause, only returns first row of each

Take a case like this one:

class Model extends Lucid {
  related() {
    return this.belongsTo('App/Model/OtherModel')
  }
}

yield Model.where('key', value).with('related').fetch();

This results in only the first matching row from OtherModel being returned.

I'm on adonis 2, not sure if this also affects 3.

I also found a fix: #36
Edit: Ok, I guess that wasn't the best way to fix it, should have ran the test suite first...

Lucid within Ace command

@matthijn commented on Thu Apr 07 2016

Currently I'm writing a very simple command to run some seeds. And writing the command itself goes wel (e.g it searches the seed directory for seed files, and calls a run method on those).

However, as soon as I add a use('App/Model/User') (or any Lucid model) it will hang on that point. It's like it is trying to connect to the database, but it never actually does that (and might be waiting for a timeout of some sort). There is no error, it just hangs.

The database (and same model) is approachable within the same Adonis application from a GET request to a route. So, I'm wondering, is the database connection not loaded?

I took a peek at how it was done in de migration command. But honestly, that did not make me much wiser.


@thetutlage commented on Thu Apr 07 2016

Are you able to seed your database? Means are you able to save records in your database ?

Setter not working

I did the following according to your documentation:

// encrypt password before storing
setPassword(value) {
    return yield Hash.make(value, 10);
}

The database has a password field in the users table, and this code is in the User model.

I get the following error:

Cannot read property 'toString' of undefined

const fs = require('fs')
const check = require('syntax-error')
const filePath = require.resolve(requirePath)
const fileSrc = fs.readFileSync(filePath)
const errors = check(fileSrc,filePath)
const errorsArray = errors.toString().split("\n")

errors.message = errors.message + " " + errorsArray[2]

in node_modules/require-stack/src/index.js.

For reference, my app is here: https://github.com/ChrisTerBeke/yardstick

Is this indeed an error in Lucid or am I misinterpreting your documentation?

Bug due to knex 0.8.6

Lucid uses an old version of knex, which throws an error when trying to rename a column, if the table is referenced by a foreign key.

knex/knex#889

The bug appears to be fixed in knex 0.9.0

Migration fail with multiple create tables in one migration

/database/migrations/1463581000000_init.js

'use strict'

const Schema = use('Schema')

class InitSchema extends Schema {

  up () {
    this.create('users', function (table) {
      table.increments('id')
      table.string('email').unique().notNullable()
      table.string('password').notNullable()
      table.timestamp('activated_at').index()
      table.timestamps()
    })

    this.create('accounts', function (table) {
      table.increments('id')
      table.timestamps()
    })
  }

  // inverse order for drop!
  down () {
    this.drop('accounts')
    this.drop('users')
  }

}

module.exports = InitSchema

Then run migration (used PostgreSQL)

vagrant@vm:/vagrant$ DEBUG=knex:query node ace migration:run
  knex:query create table if not exists "adonis_schema" ("id" serial primary key, "name" varchar(255), "batch" integer, "migration_time" timestamptz) +0ms
  knex:query select "name", "name" from "adonis_schema" +8ms
  knex:query create table if not exists "adonis_schema_lock" ("id" serial primary key, "is_locked" boolean) +6ms
  knex:query select * from "adonis_schema_lock" where "is_locked" = ? order by "id" desc limit ? +7ms
  knex:query insert into "adonis_schema_lock" ("is_locked") values (?) +6ms
  knex:query create table "users" ("id" serial primary key, "email" varchar(255) not null, "password" varchar(255) not null, "activated_at" timestamptz, "created_at" timestamptz, "updated_at" timestamptz) +7ms
  knex:query alter table "users" add constraint users_email_unique unique ("email") +6ms
  knex:query create index users_activated_at_index on "users" ("activated_at") +2ms
  knex:query create table "accounts" ("id" serial primary key, "created_at" timestamptz, "updated_at" timestamptz) +3ms
  knex:query create table "users" ("id" serial primary key, "email" varchar(255) not null, "password" varchar(255) not null, "activated_at" timestamptz, "created_at" timestamptz, "updated_at" timestamptz) +9ms
  knex:query drop table "adonis_schema_lock" +5ms
error: create table "users" ("id" serial primary key, "email" varchar(255) not null, "password" varchar(255) not null, "activated_at" timestamptz, "created_at" timestamptz, "updated_at" timestamptz) - relation "users" already exists

Dependency in package.json:

...
"adonis-lucid": "git+https://github.com/adonisjs/adonis-lucid.git#feature-version-3",

Migration Issue

I have used knex before so I was expecting the following to work fine. However, only the the states table is being created. I've tried multiple ways and always get the same result, even without the Promises. I have also tried using bluebird Promises; same result. Am I missing something?

'use strict'

const Schema = use('Schema');

class Initial extends Schema {

  up() {
    let knex = this;

    return Promise.all([
      knex.create('countries', function (table) {
        table.increments();
        table.string('abbreviation', 8).unique().notNullable();
        table.string('name', 50).notNullable();
        table.dateTime('deleted_at');
        table.timestamps();
      }),

      knex.create('states', function (table) {
        table.increments();
        table.string('abbreviation', 8).notNullable();
        table.string('name', 50).notNullable();
        table.dateTime('deleted_at');
        table.timestamps();
      })
    ]).then(function () {
      return Promise.all([
        knex.table('states', function (table) {
          table.integer('country_id').notNullable().references('id').inTable('countries');
        })
      ]);
    });
  }

  down() {
    return Promise.all([
      this.dropIfExists('countries'),
      this.dropIfExists('states')
    ])
  }

}

module.exports = Initial;

SQLITE_MISUSE: not an error

When I trying to perform .sync on belongsToMany relation with empty array, I get SQLITE_MISUSE: not an error exception. What am I doing wrong?

Lucid v2 to v3 upgrade guide ?

I just updated to v3, however the usual return of a "Promise" for example Model.create(...) has changed.

What are the steps to make v2 code work in v3 ?

Error .with(...).findOrFail is not a function

let server = yield Server.with('machine').findOrFail(id) genarate 500 error .with(...).findOrFail is not a function

However, if i use some code as yield Server.with('machine').fetch() - response is ok.

App/Http/Controllers/ServerController:

'use strict'

const Server = use('App/Model/Server')

class ServersController {

  * index (request, response) {
    let servers = yield Server.with('machine').fetch()
    response.json(servers)
  }

  * show (request, response) {
    const id = request.param('id')
    let server = yield Server.with('machine').findOrFail(id)
    response.json(server)
  }

}

module.exports = ServersController

App/Model/Server:

'use strict'

const Lucid = use('Lucid')

class Server extends Lucid {

  machine () {
    return this.belongsTo('App/Model/Machine')
  }

}

module.exports = Server

App/Model/Machine

'use strict'

const Lucid = use('Lucid')

class Machine extends Lucid {

  servers () {
    return this.hasMany('App/Model/Server')
  }

}

module.exports = Machine

isNew returning wrong value

The model I am using doesn't have an auto-generated ID, it is supplied from a 3rd Party. So every check of isNew comes back false because the primeyKey field has a value in it. isNew should be checking to see if the row exists in the database, not whether the primaryKey has a value as it causes false positives.

I am currently using a try/catch instead of using save(), but it is less then an elegant solution and introduces other problems.

    try {
      yield modelA.insert()
    } catch(e) {
      yield modelA.update()    
    }

Lucid Relations should return consistent output

Lucid output is consistent across all the queries but is not consistent with relationships.

Output Behaviour

Methods which intentionally returns a single will always return model instance or null based upon whether the results have been found or not. For example:- first, find, 'findBy'

Where methods like fetch will always returns a collection of array of model instances, which means if you call toJSON() on the collection, it will always be an array no matter whether array has a single row or not.

With Relationships (Eager Loaded)

Eagerly loaded relations output null no matter the type of the relationship. If we continue with the theory of intentionally return a single row will always have null or instance and others will have array of data. The behaviour should be.

  1. HasOne - null or object
  2. BelongsTo - null or object
  3. HasMany - array
  4. BelongsToMany - array
  5. HasManyThrough - array

Create method error

Hi, todo = yield todo.create() returns {"command":"INSERT","rowCount":1,"oid":0,"rows":[],"fields":[],"_parsers":[],"RowCtor":null,"rowAsArray":false}.

I would have assumed this to either return the newly inserted model or at least its id so I can then pass it from the store method to the show method with a redirect.

Thanks in advance.

Model instance should have toJSON method

When getting a record via Model.find(), the returned object ignores the visible/hidden fields declared in the Model declaration. Also; the record itself is inside the attributes key & calling model.toJSON() doesn't work.

Getting the record via model.where().fetch() works fine. However; I can't access the first object of the returned array.

const record = yield Model.where('id', '=', 1).fetch()
console.log(record)
res.send(record[0])

When logging the record object in console, it looks like an array [{ ... }] but getting the first object of that array record[0] does not work. It does work after calling the model.toJSON() method.

  1. Why do find() & where() behave so differently?
  2. Why isn't it possible to get the first object of the array?

Problem with belongsToMany

for example

class Book extends Lucid {

  authors () {
    return this.belongsToMany('App/Model/User', 'relation_table', 'relation_book_id', 'relation_user_id')
  }

}

// app/Model/User
class User extends Lucid {

  books () {
    return this.belongsToMany('App/Model/Book', 'relation_table', 'relation_user_id', 'relation_book_id')
  }

}

in Controller:

let lstUser = yield User.find(request.user.id);
let books = yield lstUser.books().fetch();

this code generate exception, because belongsToMany generated bad SQL:

select "book".*, "relation_table"."relation_user_id" as "_pivot_relation_user_id", "relation_table"."relation_book_id" as "_pivot_relation_book_id" from "book" inner join "relation_table" on "book"."user_id" = "relation_table"."relation_book_id" where "relation_table"."relation_user_id" = $1
Problem with "book"."user_id" = "relation_table"."relation_book_id" . "book"."user_id" - unknown column

For fix it, change 350 line in file https://github.com/adonisjs/adonis-lucid/blob/master/src/Orm/Proxy/Model/relation.js#L350

from: this.on(${table}.${targetPrimaryKey},${pivotTable}.${pivotOtherKey})
to: this.on(${table}.${relationPrimaryKey},${pivotTable}.${pivotOtherKey})

Problem Simple Data Fetch

I am trying this code in my controller;

'use strict'

const Application = use('App/Model/Application')

class AppController {

  *all (request, response) {
    const applications = yield Application.all();
    response.json(applications.toJSON());
  }

}

module.exports = AppController

There are a lot of record which I have recorded it with Lucid and I can see them in MySQL command line. But the result is empty when I run the code. There is no error, there is no explanation. Just []

mysql> SELECT * FROM applications;
+----+---------+------------------+---------------------+---------------------+---------------------+
| id | user_id | title | created_at | updated_at | deleted_at |
+----+---------+------------------+---------------------+---------------------+---------------------+
| 1 | 1 | My app. | 2016-02-11 15:14:01 | 2016-02-11 15:14:01 | 2016-02-11 15:14:01 |
| 2 | 1 | My application. | 2016-02-11 15:14:03 | 2016-02-11 15:14:03 | 2016-02-11 15:14:03 |
| 3 | 1 | Ok | 2016-02-11 15:14:32 | 2016-02-11 15:14:32 | 2016-02-11 15:14:32 |
| 4 | 1 | Ok | 2016-02-11 15:14:34 | 2016-02-11 15:14:34 | 2016-02-11 15:14:34 |
| 5 | 1 | Ok | 2016-02-11 15:15:39 | 2016-02-11 15:15:39 | 2016-02-11 15:15:39 |
+----+---------+------------------+---------------------+---------------------+---------------------+

Missing Exception on wrong configuration in lucid model

Defining model like so:

'use strict'

const Lucid = use('Lucid')

class ChatRoomHasUser extends Lucid {

  static get table () {
    return 'chatroom_has_user'
  }

........

When you give a wrong table name to your model there is no exception thrown, that you need glasses or sth... took me a while

Anyways hopefully fixed in V3

Thanks heaps

Model.create with mutliple objects in array returns array with single id

// request.post() value: 
//[ { title: 'API-Episode 2', duration: 187 },
//{ title: 'API-Episode 3', duration: 188 },
//{ title: 'API-Episode 4', duration: 189 } ]
const episodeIds = yield Episode.create(request.post())
// episodeIds value: [ 108 ] <- equals id of the last element ('API-Episode-4')
const episodes = yield Episode.where('id', 'in', episodeIds).fetch()
response.json(episodes.toJSON())

I expect to get an array containing all the ids of the created episodes.
However, in the documentation I could not find anything about passing an array to Model.create or the return value.

At the moment this is my workaround:

const data = request.post()
const episodeIds = yield Episode.create(data)

if(data.length) {
    const lastEpisodeId = episodeIds[0]
    for(let i = 0; i < data.length - 1; i++) {
        episodeIds.unshift(lastEpisodeId - i)
    }
}

const episodes = yield Episode.where('id', 'in', episodeIds).fetch()
response.json(episodes)

Improve migrations workflow

Migrations workflow needs to be improved as there are well noted bugs.

  1. Only .js files should be included from migrations directory. As system all files will also select system files like .DS_STORE or .gitkeep
  2. migrations:make command output should include minimal markup required by almost any sql table. Example
 table.increments('id')
 table.timestamps()
 table.timestamp('deleted_at')

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.