I've got two little questions:
actAs: { Timestampable: ~ }
What the "~" what mean in the code above?
Then, I've seen that tables with actAs: { Timestampable: ~ } have two fields (created_at and updated_at).
Is it possible to bind the updated_at field to a particular field (I update this field, then updated_at get a new value) ?
The "~" means that you will use default values or default configuration. In your case, the behavior Timestampable, will use the default value and configuration. So you don't have to redefine them.
From the doc, here are some configuration:
Timestampable:
created:
name: created_at
type: timestamp
format: Y-m-d H:i:s
updated:
disabled: true
You will also find this "~" (a lot) in the default generator.yml. This way, the generator, even empty, will generate a nice admin:
config:
actions: ~
fields: ~
list: ~
filter: ~
form: ~
edit: ~
new: ~
For your second question, the goal of the Timestampable is for each modification on a row, the field updated_at will be set with the current date. So you don't need to take care of it.
Edit:
And if you want to manually update the updated_at field:
first: you will have to disable the timestampable behavior for this field (see the example above
second: you will have to do the behavior on your own.
The easiest way is to extends the preSave function of your model and do the job here. Like:
class Article extends BaseArticle
{
public function preSave($event)
{
if(array_key_exists("your_field", $this->getModified())
{
$this->setUpdatedAt(time());
}
}
Related
I'm trying with all the latest version of apollo-ios but i'd like to solve this one lingering problem: I keep getting optional values (see image below).
Here's what I've explored (but still can't find whyyy)
When I created the table, Nullable is false. Then, I create a view which is for public to access it.
With apollo schema:download command, here's the generated json: schema.json
With graphqurl command, here's the generated schema.graphql: schema.graphql. Here's the snippet.
"""
columns and relationships of "schedule"
"""
type schedule {
activity: String
end_at: timestamptz
id: Int
"""An array relationship"""
speakers(
"""distinct select on columns"""
distinct_on: [talk_speakers_view_select_column!]
"""limit the number of rows returned"""
limit: Int
"""skip the first n rows. Use only with order_by"""
offset: Int
"""sort the rows by one or more columns"""
order_by: [talk_speakers_view_order_by!]
"""filter the rows returned"""
where: talk_speakers_view_bool_exp
): [talk_speakers_view!]!
start_at: timestamptz
talk_description: String
talk_type: String
title: String
}
I am suspecting that it looks like id: Int is missing ! in the schema, is the cause of codegen interpreting it as optional. But I could be wrong too. Here's the repo for the complete reference https://github.com/vinamelody/MyApolloTest/tree/test
It's because Postgres marks view columns as explicitly nullable, regardless of the underlying column nullability, for some unknown reason.
Vamshi (core Hasura server dev) explains it here in this issue:
https://github.com/hasura/graphql-engine/issues/1965
You don't need that view though -- it's the same as doing a query:
query {
talks(
where: { activity: { _like: "iosconfig21%" } },
order_by: { start_at: "asc" }
}) {
id
title
start
<rest of fields>
}
Except now you have a view you need to manage in your Hasura metadata and create permissions for, like a regular table, on top of the table it's selecting from. My $0.02 anyways.
You can even use a GraphQL alias if you really insist on it being called "schedule" in the JSON response
https://graphql.org/learn/queries/
The columns use current timestamp. How do I make it UTC?
#CreateDateColumn({
type: 'timestamptz',
name: 'create_date'
})
private createDate: Moment;
#UpdateDateColumn({
type: 'timestamptz',
name: 'update_date',
})
private updateDate: Moment;
You have some options.
1 - Create the columns directly from postgres query:
create temporary table test(
id int,
create_date timestamp without time zone default (now() at time zone 'utc')
);
2 - Convert to UTC in application and create the column with { type: 'timestamptz' }
You can take a look at this link and check if one of the solutions solves your problem.
We want to alter a table to include a non-primary key reference to a new table. The old definition is:
#schema
class SpikeSortingParameters(dj.Manual):
definition = """
# Table for holding parameters for each spike sorting run
-> SortGroup
-> SpikeSorterParameters
-> SortInterval
---
-> SpikeSortingMetrics
-> IntervalList
import_path = '': varchar(200) # optional path to previous curated sorting output
"""
We'd like to add
-> SpikeSortingArtifactParameters
as a non primary key, and before we spent time trying to get this to work, we wanted to know if it was possible given that we don't know of a way to assign a default value here.
thanks in advance...
Loren
Unfortunately, foreign key updates are not currently supported with table.alter(). There is a workaround that can be used but there are a few steps and those should be taken carefully. It would be best to file this as a feature request in the issue tracker.
Using Alter
For instance, consider the following:
If you have 2 tables defined as follows:
import datajoint as dj
schema = dj.Schema('rguzman_alter_example')
#schema
class Student(dj.Lookup):
definition = """
student_first_name: varchar(30)
student_last_name: varchar(30)
---
student_location: varchar(30)
"""
contents = [('Joe', 'Schmoe', 'Los Angeles, CA'), ('Suzie', 'Queue', 'Miami, FL')]
#schema
class Assignment (dj.Lookup):
definition = """
assignment_id: int
---
assignment_due_date: date
#-> [nullable] Student # Standard way to define a foreign key on secondary attributes with NULL as default
"""
contents = [dict(assignment_id=100, assignment_due_date='2021-04-21')]
Now suppose that you'd like to have a foreign key on secondary attributes with NULL as the default. You can pass options to foreign keys in secondary attributes (see the comment above where we allow it to default to NULL). Initializing a table from scratch in this way works just fine. For the case where we want to add a foreign key on a secondary attribute after a table has been initialized with existing data, Assignment.alter() would be the best means to achieve this so long as we establish a default value to fill existing records with. Let's see what happens when we uncomment the foreign key on secondary attributes, redefine the Assignment table class, and try to alter.
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
<ipython-input-23-09997168281c> in <module>
----> 1 Assignment.alter()
~/.local/lib/python3.7/site-packages/datajoint/table.py in alter(self, prompt, context)
84 del frame
85 old_definition = self.describe(context=context, printout=False)
---> 86 sql, external_stores = alter(self.definition, old_definition, context)
87 if not sql:
88 if prompt:
~/.local/lib/python3.7/site-packages/datajoint/declare.py in alter(definition, old_definition, context)
367 raise NotImplementedError('table.alter cannot alter the primary key (yet).')
368 if foreign_key_sql != foreign_key_sql_:
--> 369 raise NotImplementedError('table.alter cannot alter foreign keys (yet).')
370 if index_sql != index_sql_:
371 raise NotImplementedError('table.alter cannot alter indexes (yet)')
NotImplementedError: table.alter cannot alter foreign keys (yet).
Oh, there's an exception... So it turns out that it is not implemented yet for this use case. However, there is a manual workaround that can be leveraged so let me detail those steps until there is support.
Workaround
Instead of defining the foreign key on secondary attributes as above, define it in this way:
#schema
class Assignment (dj.Lookup):
definition = f"""
assignment_id: int
---
assignment_due_date: date
{newline.join(['' + a.name + '=null: ' + a.type for a in Student.heading.attributes.values() if a.in_key])}
"""
contents = [dict(assignment_id=100, assignment_due_date='2021-04-21')]
This 'copies' over the primary attributes of the parent table into the secondary attributes of your child table.
Perform alter as normal: Assignment.alter()
Manually add the foreign key using a SQL query directly. Like this:
q = """
ALTER TABLE {table}
ADD FOREIGN KEY ({fk})
REFERENCES {ref} ({pk})
ON UPDATE CASCADE
ON DELETE RESTRICT
""".format(table=Assignment.full_table_name,
fk=','.join([f'`{k}`' for k in Student.primary_key]),
ref=f'`{Student.table_name}`',
pk=','.join([f'`{k}`' for k in Student.primary_key]))
dj.conn().query(q)
Make sure to remove the portion that was added in step 1 and replace it with the proper specification i.e. -> [nullable] Student
Restart your kernel
To verify it has been properly set, check Assignment.describe(). If everything worked properly, the result should be:
assignment_id : int
---
assignment_due_date : date
-> [nullable] Student
Additionally, any pre-existing records should now be prefilled with NULL.
I have a versionable table in my schema. I want it not to be versioned when i change status for example, but versioned when i change shippingPrice.
MyOrder:
actAs:
Timestampable:
Versionable:
versionColumn: version
className: %CLASS%Version
auditLog: true
columns:
userId: { type: integer, notnull: true }
status: {type: enum, values: ["status1", "status2"]}
shippingPrice: { type: float, notnull: true }
#more columns
How can i do that ?
This article might be of some interest:
http://blog.solutionset.com/wpmu/2009/08/26/doctrine-with-nested-i18n-versionable/
The author wants to nest I18N functionality with Versionable. The problem is slightly different; you can't even build the database when you nest I18N and Versionable, but the solution he came up with might be useful.
In essence, he rolled his own Versionable. Not the most pleasant prospect, but looking at how he implemented it might save you some time on your own spike.
This is a bit hacky but should do what is required I think.
I haven't tested it but my understanding is that if you do a dql update() Versionable is not triggered.
Like this
$result = $this->createQuery()
->update('MyOrder m')
->set('m.status', $var)
->execute();
But if you retrieve the object, change it and save thus:
$m = MyOrderTable::getInstance()->findOneById($id);
$m->setShippingPrice($price);
$m->save();
Then Versionable will be triggered so you should get a new version.
So you could use this to solve the problem.
I'm repeatedly getting confused between Language & Culture in Symfony.
- I'm setting culture as (en_US) which I guess is correct
- but translation files are created for a language (en)
- also, when using translation in the database, the lang=en
I have a model whose definition is as follows:
Option:
package: Options
tableName: Com_Options
actAs:
I18n:
fields: [name, tooltip]
columns:
id:
type: integer(2)
primary: true
notnull: true
unsigned: true
# autoincrement: true
name:
type: string(50)
notnull: true
notblank: true
tooltip:
type: string(100)
sequence:
type: integer(1)
unsigned: true
range: [0,255]
This class is referred by several other classes.
When I try to print the name as $refObj->Option->Name I get nothing. When I check the queries, I see that 3 queries are fired in all.
1) to get refObj
2) to get Option
3) to get Translation
But the real problem is that for 3, there is no language parameter in the query.
I wonder how it will get the translated name? Current value of sf_culture: en_US
Is there another way to access the 'name' according to user's language?
Or do I need to write custom queries on every model?
Is the problem because autoincrement is OFF, or because Im using a package?
Thanks a lot!
Found this: a very tedious & costly method, but works:
$class->relation->Translation[$lang]->property
If you wish to read directly from database
$q = Table::getInstance()->createQuery('a')
->select('a.id, t.name')
->leftJoin('a.Translation t')
->where('t.lang = ?', $lang);
return $q->execute(array(), Doctrine::HYDRATE_NONE);
If you use XLIFF files, you need not pass culture/language
__('text which is translated in the XLIFF for user\'s culture');