Self joins in Batmanjs - self-join

How can I implement the self-joins in Batmanjs?
In rails, as found here, it goes like this:
class Employee < ActiveRecord::Base
has_many :subordinates, class_name: "Employee", foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee"
end
My current Batmanjs equivalent model looks like this:
class Employee extends Batman.Model
#resourceName: 'employees'
#storageKey: 'employees'
#persist Batman.LocalStorage
#has_many 'subordinates', name: "Employees", foreignKey: "manager_id"
#belongs_to 'manager', name: "Employee"

I think that should work, if you just switch:
has_many/belongs_to => hasMany/belongsTo
name: "Employees" => name: "Employee".
Also, you may have to add an encoder for id with the LocalStorage adapter. LocalStorage converts the value to a string, but batman.js expects an integer, so you have to coerce it back to integer in the encoder.
Here's an example of self-joins (you can copy-paste the encoder from there, too):
http://jsbin.com/cukapedo/18/edit
Pasted here for posterity:
class App.Color extends Batman.Model
#resourceName: 'color'
#persist Batman.LocalStorage
#encode 'name', 'source_color_id'
# required for numbers in localStorage:
#encode 'id',
encode: (val) -> +val
decode: (val) -> +val
#hasMany 'child_colors', name: 'Color', foreignKey: 'source_color_id'
#belongsTo 'source_color', name: 'Color'

Related

Api-platform how to use assertJsonContains with dynamic data in test class?

Sometime, the json response has some properties that have "dynamic data", like id, createdAt below:
$this->assertJsonContains(
[
"data" => [
"id" => "#integer",
"type" => "resource-category",
"attributes" => [
"name" => "Office",
"slug" => "office",
"createdAt => "#string"
]
]
]
);
So I would like to expect these field same the type like integer, string,... How could I do that?
API-Platform will generate a schema for your operations, i.e. describe what the output should look like, which fields it should have and what the expected types are. You can store this schema and then test against it using something like justinrainbow/json-schema, which should come with api-platform anyway. Here is the basic example from the docs, which you can use for your test:
<?php
$data = json_decode(file_get_contents('data.json'));
// Validate
$validator = new JsonSchema\Validator;
$validator->validate($data, (object)['$ref' => 'file://' . realpath('schema.json')]);
self::assertIsTrue($validator->isValid());
The thing you need to look out for, is that you can’t use the automatically generated schema directly. Your test will always fit the output as the schema is generated from it.

How to order ngrx entity collection

I have a response from backend like this:
[{ id: 4, name: 'Andrew'},
{id: 3, name: 'Rebecca'},
{id: 2, name: 'Joseph'},
{id: 1, name: 'Kristin'}]
The order is by descending id. From the last one to first one.
I have an entityAdapter defined in this way:
export const folderAdapter: EntityAdapter<Person> = createEntityAdapter<Person>({
selectId: person => person.id,
sortComparer: false,
});
into the reducer I created this function:
on(PeopleActions.loadAllPeople, (state, action): PeopleState => {
return {
...state,
people: adapter.addMany(action.people, state),
};
}),
when I go to see my state I have this situation:
ids:[4,3,2,1],
entities: {1: {id: 1, name: 'Kristin'}, 2: {id: 2, name: 'Joseph'}, 3: {id: 3, name: 'Rebecca'}, 4: { id: 4, name: 'Andrew'}}
}
This also happen into the ngFor. I tried to set return value to zero in ngfor keyvalue but nothing change. How can I change the order in entities? is there a particular property?
The EntityAdapter has the parameter sortComparer for this exact purpose.
All you need it to instead of using
sortComparer: false
you give it the function you would like to have sorting your entity ids
sortComparer: (a ,b) => a.id - b.id
As per ngrx's docs:
If provided, the state.ids array will be kept in sorted order based on comparisons of the entity objects, so that mapping over the IDs array to retrieve entities by ID should result in a sorted array of entities.
If not provided, the state.ids array will not be sorted, and no guarantees are made about the ordering. In other words, state.ids can be expected to behave like a standard Javascript array.

how to pass the name attribute insted of id in mongoid?

i am using mongoid database, i am trying to override the id attribute in url to name, but i am getting error
my model is like this
class Product
include Mongoid::Document
field :name, type: String
field :price, type: BigDecimal
field :released_on, type: Date
field :_id, type: String, default: -> { name.to_s.parameterize }
validates_presence_of :name
embeds_many :reviews
end

FOSElasticaBundle sort not working

The configuration of my elastica type looks like following:
acme_article:
mappings:
title: {type:string, index_analyzer:acme_analyzer}
content: {type:string, index_analyzer:acme_analyzer}
slug: ~
media: {type:string, index_analyzer:acme_analyzer}
categories:
type: "object"
properties:
name: ~
id: ~
instance:
type: "object"
properties:
name: ~
created_by: ~
created_at: ~
I have Repository class which extends FOS\ElasticaBundle\Repository and everything works well except sorting.
$query = new \Elastica\Query();
$query->setSort(array('created_at' => array('order' => 'desc')));
return $this->find($query);
Getting some irelevant result, totally without order. Then, I tried to add model id in index and try to sort by id but also without success.
Solution is to set {type:date} on created_at field. In that case ES sorting by timestamp and everything is ok.
Sorting by id is not working because in some way categories.id override main id and then I got results ordered by category.id instead entity id.

Query builder join on one to many relationship

I have a LastTrait object that has a many to one relationship with my user object: one user can have many different lastTrait:
YOP\YourOwnPoetBundle\Entity\LastTrait:
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
traitCategoryID:
type: integer
verseID:
type: integer
manyToOne:
user:
targetEntity: User
inversedBy: lastTrait
joinColumn:
name: user_id
referencedColumnName: id
I need to retrieve the verseID knowing the userID and traitCategoryID. So I created a Repository for my LastTrait object:
<?php
namespace YOP\YourOwnPoetBundle\Repository;
use Doctrine\ORM\EntityRepository;
class LastTraitRepository extends EntityRepository {
public function findOneByTraitCategoryID($userID, $traitCategoryID)
{
return $this->getEntityManager()
->createQuery('SELECT l
FROM YOPYourOwnPoetBundle:LastTrait l
JOIN l.user u
WHERE l.traitCategoryID = :categoryID AND u.id = :userID')
->setParameters(array(
'categoryID' => $traitCategoryID,
'userID' => $userID,
))
->getResult();
}
}
?>
However, when I call :
$lastTrait = $this->getDoctrine()
->getRepository('YOPYourOwnPoetBundle:LastTrait')
->findOneByTraitCategoryID($user->getID(), $collector->getTraitCategory()->getID());
I always get NULL, even though I should get a LastTrait object back!
What am I doing wrong here?
I think you should be thinking more in entities and less in foreign keys.
Try this in your method.
public function findOneByTraitCategoryID($userID, $traitCategoryID)
{
return $this->findOneBy(
array(
'traitcategoryID' => $traitCategoryID,
'user' => $userID
));
}
You can call ->getVerse()->getId(); after this or return the id directly on the method (too narrow for future uses IMO).
This only works if a user only has one trait per category, otherwise you don't have enough data to get a specific trait.
The issue was that I forgot to register the repository in my entity:
YOP\YourOwnPoetBundle\Entity\LastTrait:
repositoryClass: YOP\YourOwnPoetBundle\Repository\LastTraitRepository
type: entity
table: null
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
traitCategoryID:
type: integer
verseID:
type: integer
manyToOne:
user:
targetEntity: User
inversedBy: lastTrait
joinColumn:
name: user_id
referencedColumnName: id
After adding the repositoryClass line, my custom Repository class is called and I get the desired result.
However, #dhunter's answer made me realize that I didn't even need a custom Repository class. I can get the desired by simply using the regular findOneBy function from my controller:
$lastTrait = $this->getDoctrine()
->getRepository('YOPYourOwnPoetBundle:LastTrait')
->findOneBy(
array('user' => $user->getId(), 'traitCategoryID' => $collector->getTraitCategory()->getID())
);
Hard to tell. Try echoing either DQL or SQL before retreiving results:
$q = $this->getEntityManager()->createQuery(....);
die($q->getSql()); //or getDql();
If, for some reason, you have invalid mapping (which I don't see above) you should see it here.
Also, try wrapping method with try-catch with most general Exception catch and seeing if it catches anything...
Furthermore, what is bugging me is the fact that you get NULL back...

Resources