RAML dependent required query parameters - raml

I have the following trait:
traits:
feedSortable:
queryParameters:
sortBy:
description: Sort the topic feed
required: false
default: 'created_at'
type: string
enum: [ 'most_recent', 'upvotes' ]
since:
description: Get topics since utc creation date. Required in case of upvotes
required: false
type: datetime-only
until:
description: Get topics until utc creation date
required: false
type: datetime-only
Since and until query parameters are only required when sortBy is defined as upvotes.
How do I enforce this best in my RAML definition?
More generally, I want to know how I define query parameter definitions dependent on other query parameters. Can't be that rare?

Doesn't look like there is a good way although this would seem to be a case that is relatively common. Swagger seems too restrictive, RAML seems to be missing options too.
I circumvented the issue by making the field non-required altogether, and adding more description to the default:
since:
description: Get topics since utc creation date
required: false
default: sortBy = recent -> null, sortBy = upvotes -> now() - 1 month
type: datetime-only

Related

Is it possible to validate date from param is less than date to param in Grape API (Ruby)?

If I have the following params setup in a Grape API endpoint, is there a way to validate that :date_from is less than :date_to?
params do
requires :date_from, type: Date,
description: "The date from in YYYY-MM-DD format",
coerce_with: Date.method(:iso8601),
allow_blank: false
requires :date_to, type: Date,
description: "The date to in YYYY-MM-DD format",
coerce_with: Date.method(:iso8601),
allow_blank: false
end
I can probably do something in an after_validation block but curious to see if there is a way to do it using Grape's standard validations, which doesn't seem the case looking at the docs.

Require at least one non-null child in joi object that allows null

I am defining a Joi schema for an object with some fields for social profiles. The goal is to ensure that all of the fields are present and that at least one of them is a non-empty string, but to allow the others to be null.
Here is what I have so far:
const socialUrl = joi.string().min(1).alphanum().allow(null);
const schema = joi.object({
facebook : socialUrl.required(),
twitter : socialUrl.required(),
youtube : socialUrl.required()
}).required()
This works great except that the following object is considered valid:
{
facebook : null,
twitter : null,
youtube : null
}
Using min() and or() on the object doesn't help because the fields exist, they're just the wrong type.
It would be pretty trivial to do an extra loop myself afterwards and check for the specific case of all fields being null, but that is not ideal.
This is being used for payload validation where it would be nice to know that the client understands the full schema, hence the desire that all of the fields be present. Maybe that is not worth it. I do get the sense that I could use some verbose when() code to get the job done, but it seems like at that point I might as well just make my own loop. Hoping to be proven wrong!
here is ready answer: Using Joi, require one of two fields to be non empty
joi has .alternatives() method, that has .try() method in which you could simply go through all the options
In each case you must keep only one required field
const socialUrl = joi.string().min(1).alphanum().allow(null);
const schema = joi.alternatives().try(
joi.object({
facebook: socialUrl.required(),
twitter: socialUrl,
youtube: socialUrl,
}),
joi.object({
facebook: socialUrl,
twitter: socialUrl.required(),
youtube: socialUrl,
}),
joi.object({
facebook: socialUrl,
twitter: socialUrl,
youtube: socialUrl.required(),
}),
);
So, you don't need to use .min() or .or()
You can use oxor operator, here's a description. It worked for my case, which I was 2 fields that can't be used at the same time, but if both of them are not used I don't want to receive any warnings as if I used xor...

how to solve the conflict of "column not found" on symfony 1.4 using doctrine?

Sorry for this very specific question, Ive got this problem couple of times, and my solution (not the best was rename tables and do more stuffs), obviously its not a real solution, this time i got into same situation again, with a table I am not even manipulating, I wonder if someone got the same problem before.
Working with symfony 1.4 and doctrine, I get this error from a query of a not related table
Column not found: 1054 Unknown column 'o.training_id' in 'field list'
I really have no idea whats wrong, at my schema.yml i have something like this
OhrmTraining:
connection: doctrine
tableName: training
columns:
id_training:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
name:
type: string(60)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
TrainingDetail:
connection: doctrine
tableName: training_detail
columns:
id_training_detail:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
training:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
relations:
OhrmTraining:
local: training
foreign: id_training
type: one
Its related with other table Detail
like this
TrainingDetail:
connection: doctrine
tableName: training_detail
columns:
id_training_deetail:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
training:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
relations:
Training:
local: training
foreign: id_training
type: one
Which I think its correct, but at my doctrine/base/BaseTraining.class I have something like this at the end (for training)
public function setUp()
{
parent::setUp();
$this->hasMany('TrainingDetail', array(
'local' => 'id', <--- this should be the id_training_detail??
'foreign' => 'training_id')); <--- this should be training?
I dont know why they are like that, or if they should be like that... could anybody help me with this?
I changed them for
public function setUp()
{
parent::setUp();
$this->hasMany('TrainingDetail', array(
'local' => 'id_training',
'foreign' => 'training'));
Still, I get the error, and if I make a remake models all will be gone
There is no easy way to create the schema.yml file from a DB?
EDIT:
the query that throws the exception is this
$query = Doctrine_Query::create()
->from('Times a')
->where('a.employee_id = ?', $employeeId)
->orderBy('a.start_date ASC');
$results = $query->execute();
I checked on the base of employee, and it has no relation with training, it has with training details... but not directly with training, i recreated my models 10 times and still the same
"Still, I get the error, and if I make a remake models all will be gone"
This is because you edited the setup via a base class, base classes ALWAYS get overidden when you build models.
"There is no easy way to create the schema.yml file from a DB?"
This doesn't make sense. It's obvious you were able to generate a schema file from the schema, otherwise you wouldn't have a schema file.
The location of the relations appears correct according to the given schema file. According to Doctrine's docs:
"When specifying relationships it is only necessary to specify the relationship on the end where the foreign key exists. When the schema file is parsed, it reflects the relationship and builds the opposite end automatically. If you specify the other end of the relationship manually, the auto generation will have no effect."
When you build the model files, doctrine will correctly configure the setUp method in the base classes, so you don't need to do it. If you want to change the relationship, change it via the schema file then rebuild the model files.
I suspect the problem you are having is in how you are constructing the query, either via DQL or model references, due to the error you posted:
"Column not found: 1054 Unknown column 'o.training_id' in 'field list'"
-- Edit --
Based on the error, and your query, you could specify the columns to select, try this:
$query = Doctrine_Query::create()
->select('a.*')
->from('Times a')
->where('a.employee_id = ?', $employeeId)
->orderBy('a.start_date ASC');
$results = $query->execute();

How do I setup query cache results for built in doctrine2 repository functions?

I have a site that is for a video game I play and am working on improving the performance of the site by implementing some additional caching. I've already been able to implement query result caching on custom repository functions, but haven't been able to find anywhere that explains how I can include query result caching on the built in functions (findOneById, etc). I'm interested in doing this because many of my database queries are executed from these 'native' repository functions.
So as an example I have a character entity object with the following properties: id, name, race, class, etc.
Race and class in this object are references to other entity objects for race and class.
When I load a character for display I get the character by name (findOneByName) and then in my template I display the character's race/class by $characterObject->getRace()->getName(). These method calls in the template result in a query being run on my Race/Class entity tables fetching the entity by id (findOneById I assume).
I've attempted to create my own findOneById function in the repository, but it is not called under these circumstances.
How can I setup doctrine/symfony such that these query results are cache-able?
I am running Symfony 2.1.3 and doctrine 2.3.x
I've found out that it isn't possible to enable query cache on doctrine build in functions. I will post a link which explains why later after I find it again.
Your entities probably look something like this:
MyBundle\Entity\Character:
type: entity
table: Character
fields:
id:
id: true
type: bigint
name:
type: string
length: 255
manyToOne:
race:
targetEntity: Race
joinColumns:
raceId:
referencedColumnName: id
MyBundle\Entity\Race:
type: entity
table: Race
fields:
id:
id: true
type: bigint
name:
type: string
length: 255
oneToMany:
characters:
targetEntity: Character
mappedBy: race
If that's the case, then modify your Character entity mapping so that it eagerly loads the Race entity as well:
MyBundle\Entity\Character:
...
manyToOne:
race:
targetEntity: Race
joinColumns:
raceId:
referencedColumnName: id
fetch: EAGER
Doctrine documentation on the fetch option: #ManyToOne

How to define current timestamp in yaml with doctrine?

I tried the following yaml code:
columns:
created_time:
type: timestamp
notnull: true
default: default CURRENT_TIMESTAMP
In the outputted sql statement, the field is treated as datetime instead of timestamp, which I cannot define the current timestamp in it...
If I insist to use timestamp to store current time, how to do so in yaml?
If you are willing to sacrifice some portability (see description of columnDefinition attribute) for the ability to use MySQL's automatic initialization TIMESTAMP (see MySQL timestamp initialization), then you can use the following:
Yaml:
created_time:
type: datetime
columnDefinition: TIMESTAMP DEFAULT CURRENT_TIMESTAMP
Annotation:
#ORM\Column(type="datetime", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
Notice that DEFAULT CURRENT_TIMESTAMP does not work the same as Timestampable, and thus you cannot blindly exchange one for the other.
First and foremost, the former uses the date/time of the DB server, while the latter uses a Doctrine magic that calls PHP's date() function on your webserver. In other words, they are two distinct ways of getting the date/time, from two entirely different clock sources. You may be on big trouble if you use Timestampable, your web server runs on a different machine than your DB server, and you don't keep your clocks in sync using e.g. NTP.
Also, the DEFAULT CURRENT_TIMESTAMP being on the table definition makes for a much more consistent database model IMHO, as no matter how you insert the data (for instance, running INSERTs on the DB engine command line), you'll always get the current date/time on the column.
BTW, I'm also looking for an answer to the CURRENT_TIMESTAMP problem mentioned in the initial question, as this is (due to the reasons outlined above) my preferred way of keeping "timestamp" columns.
You could use the 'Timestampable' functionality in doctrine, eg:
actAs:
Timestampable:
created:
name: created_time
updated:
disabled: true
columns:
created_time:
type: timestamp
notnull: true
/**
* #var int
* #ORM\Column(type="datetime", columnDefinition="TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
*/
protected $created;
after run ./vendor/bin/doctrine-module orm:schema-tool:update --force
Updating database schema... Database schema updated successfully! "1"
queries were executed
and run ./vendor/bin/doctrine-module orm:validate-schema
[Mapping] OK - The mapping files are correct. [Database] FAIL - The
database schema is not in sync with the current mapping file.
But FAIL for sync appear
Sorry for necroposting.
But i have encoutered the same problem. There is solution for doctrine 2 and postgreSql. I have used Gemdo extension and added following strings:
$evm = new \Doctrine\Common\EventManager();
$timestampableListener = new \Gedmo\Timestampable\TimestampableListener;
$timestampableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($timestampableListener);
YAML:
created:
type: date
options:
default: 0
nullable: true
gedmo:
timestampable:
on: create
updated:
type: datetime
options:
default: 0
nullable: true
gedmo:
timestampable:
on: update
dump-sql:
ALTER TABLE users ADD created DATE DEFAULT CURRENT_DATE NOT NULL;
ALTER TABLE users ADD updated TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL;
I suggest not to use "default" for timestamp at all.
It will bring unpredictable state in yaml in your application.
This video (PHP UK Conference 2016 - Marco Pivetta - Doctrine ORM Good Practices and Tricks) provides some more information about this topic.
I suggest you to to go through it and create a named constructor.
public function createTimestamp(string $priority, int $priorityNormalized)
{
$this->priority = $priority;
$this->priorityNormalized = $priorityNormalized;
}
I suggest to be stateless, good luck!
You can use:
default: '<?php echo date('Y-m-d H:i:s') ?>'

Resources