How can i specify a hasOne relationship while there are many record in Phalcon - phalcon

there are two tables,Task and Report
Task(id,name,latest_report_id);
Report(id,content,feedback,task_id);
one task has many report but it only has one latest report.I wanna how can I get this hasOne relationship in Phalcon 4.0
Thanks.

I've never done this, but according to the documentation, you can use conditional relationships. When you set up your relationships in Task:
$this->hasMany("report_id", Report::class, "id");// This is the standard one-to-many
$this->hasMany(
"report_id",
Report::class,
"id",
"params" => [
"order"=>"date_entered DESC",
"limit"=>1
],
"alias" => "LatestReport"
);
This assumes date_entered is the field in the report table you can use to determine which report is the "latest".
https://docs.phalcon.io/4.0/en/db-models-relationships#conditionals

you didn't mention the database engine but in case its mysql, you might in the future set up the relations before making the models and use the Phalcon's cli tool (Devtools) and will setup the relationship in the models for you
to get the latest report from the Task model add this relation in Task model file
$this->belongsTo('latest_report_id', 'Report', 'id', ['alias' => 'latestReport']);
this would lookup Report table using findFirst with id = latest_report_id condition
if this is not the case please update the question with more details

Related

Is it possible to create a relation in Typeorm with just an id?

I'm using Nodejs, Typescript, TypeORM, PostgreSQL
I have my relation OneToMany with on one side the most important :
#ManyToOne(() => Group, (groupe) => group.listMember, { eager: true })
readonly group: Group;
Right now my use-case to create a member ask for an ID of the entity Group. When I extract the ID from the request, I have to make a findOneByID to get the entire Group corresponding to the ID I received.
Then I pass it to my Member class to build it from the constructor and then store it in the database with .save() method.
My issue is that I would like to NOT have to retrieve the entire Group object from the database : Since in the end, we just store an ID in the Member table why wouldn't we be able to create the OneToMany or ManyToMany relation just from an ID ?
Do TypeORM offer a way to do it ?
I hope I could translate my issue. Thanks in advance for your help !

Mass/bulk update in rails without using update_all with a single query?

I want to update multiple rows using single query of active record. I don't have to use update_all because it skips validation. Is there any way to do this in rails active record.?
Mass update without using update_all can be achievable using activerecord-import gem.
Please refer to this gem for more information.
Methods with detail.
Example:
Lets say there is a table named "Services" having a "booked" column. We want to update its value using the gem outside the loop.
services.each do |service|
service.booked = false
service.updated_at = DateTime.current if service.changed?
end
ProvidedService.import services.to_ary, on_duplicate_key_update: { columns: %i[booked updated_at] }
active-record import by default does not update the "updated_at" column. So we've to explicitly update it.
If you want to update multiple records without instantiating the models, update_all method should do the trick:
Updates all records in the current relation with details given. This method constructs a single SQL UPDATE statement and sends it straight to the database. It does not instantiate the involved models and it does not trigger Active Record callbacks or validations. However, values passed to #update_all will still go through Active Record’s normal type casting and serialization.
E.g:
# Update all books with 'Rails' in their title
Book.where('title LIKE ?', '%Rails%').update_all(author: 'David')
As I understood, it even accepts an array as a parameter, allowing us to provide different hashes to update different records in their corresponding order, like in SQL UPDATE statement. Correct me, somebody, if I'm wrong.
It sounds like you are looking for Update records - from the documentation Updating multiple records; different col with different data
You can do like this Example:
people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
Person.update(people.keys, people.values)

Rails, check database if uploading data in CSV already exists

I'm new to Rails and I would like to know if I can check if data already exists in my database while uploading new data from CSV. So far I haven't found this on the net.
I use a Postgres database. I don't know if I have to check it in Rails or in Postgres. In my database there are some columns like id, personal_id, cost_center. So I will check if one (or more) of my new data has the same personal_id with the the same cost_center while uploading.
How can I do this?
UPDATE
I've tried the solution of #huan son, it works but not the way I need it. So I tried different things and I think a SQL query is in my case the best choice.
DELETE FROM bookings WHERE id NOT IN (SELECT MIN(id) FROM bookings GROUP BY personal_id, wbs, date, hours, cost_center)
Booking.delete_all.where('id NOT IN (?)', Booking.select('MIN(id)').group(:personal_id, :wbs, :date, :hours, :cost_center).map(&:id))
My SQL query works like the way I want it but I don't know the right "translation" into rails because with the second code above my whole bookings table gets deleted
Solution
The solution for my problem is:
Booking.delete_all(['id NOT IN (?)', Booking.group(:personal_id, :wbs, :date, :hours, :cost_center).pluck('MIN(id)')])
Those are unique scopes.
You need to define those first in your database migration so postgres is making sure there is no double-value wie [key, key1, key2...]
add_index :table, [:personal_id, :cost_center_id], :unique => true
then you need to go into your rails-model and catch that uniqueness at validations.
validates_uniqueness_of :personal_id, :scope => :cost_center_id
with that, rails is querying every time before creating a object, the database and check if something with the unique-pair-values already exists. if so, its adding it to the #errors of the model, so the model can't be saved
You can use uniqueness validation, but in my experience when importing data from CSV, the problem is that if the item already exists, all the validation does is stop the record being saved. In most examples, you usually want to do something with the matched record. Therefore, I'd suggest you also look at find_or_initialize_by. This allows you to also update existing records from imported data.
So if you have Thing model with a name and cost for example, you may want to identify existing things by name, and update their costs. And create new things where no matching name exists. The following code would do that:
name, price = some_method_that_gets_name_and_price_from_csv
thing = Thing.find_or_initialize_by name: name
thing.price = price
thing.save
Also have a look at find_or_create_by which can be more suitable in some situations. I'd also still keep the validation of uniqueness in the model. I just wouldn't use validation to handle how the data was imported.

How to join more than one table rails

I've got a bit of code that I'm looking at the moment :
User.includes([:profile => :schedule]).where('...')
This loads all profiles and their schedules. So the query produced by this is select * user fields, select * profile fields, select * schedule fields
I'm filtering out users based on one field from profile and based on one field from profiles schedule but this above statement is selecting all the fields from all of these.
So I tried to do it with joins :
User.joins(:profile).joins('profiles.schedule').where('....').select('....')
This is throwing out error. I'm a former Java developer, still learning the rails stuff.
This should work:
User.joins(profile: :schedule).where('....').select('....')
If you've set your Profile model to have the association Schedule using the has_many through association then you can just use this:
User.joins(:schedule).where('...')
Try this:
User.joins(profile: [:schedule]).where('...')
or
User.joins(profile: :schedule).where('...')

Django queries: how to annotate with a filtered count?

Suppose I have a Book model with a language field and a foreign key to a Publisher model.
Currently I use a Count annotation in a custom Publisher manager to allow me to add to the admin a sortable column with the number of books by each publisher. (see How to add a sortable count column to the Django admin of a model with a many-to-one relation? )
My problem now is that I need to have a different column count for the books published in each language.
Is there any way to make the annotation subject to a filter of the related model?
You can use the double underscore __ for this purpose. Something like this (snippet taken from question linked to by OP):
class PublisherManager(models.Manager):
def get_query_set(self):
return super(PublisherManager,self).get_query_set().annotate(lang_count=Count('book__language'))