Friend circle by sqlalchemy - sqlalchemy

Say i have the following Users model-
class Users(Base):
__tablename__='users'
id=Column(Integer, primary=True)
friends=relationship(
'Users',
secondary='friend_associations',
primaryjoin='and_(FriendAssociations.user_id==Users.id,'
'FriendAssociations.pending==False)',
secondaryjoin='and_(FriendAssociations.friend_id==Users.id,'
'FriendAssociations.pending==False)',
uselist=True,
)
And the FriendAssociations model is-
class FriendAssociations(Base):
__tablename__='friend_associations'
id=Column(Integer, primary=True)
user_id=Column(ForeignKey('Users.id'), nullable=False)
friend_id=Column(ForeignKey('Users.id'), nullable=False)
pending=Column(Boolean, default=True)
__table_args__ = (UniqueConstraint(
'user_id','friend_id', name='uq_user_friend_id_pair'
),)
The target was, user A sends a friend request to user B. Until user B accepts the request, the request stays as pending. When B accepts the request, pending is False and one more friend_associations entry
is created on user B to state that user A is friend of user B and vice versa. The problem is, i can do these things, but when i want to remove a user entry, the database(i am using PostgreSQL) throws up error saying friend_associations depends on the user(because the association entry isn't deleted). As a result i can't delete any user entry.
So -
Is my solution to the problem correct?
If not, what should i do to correct it?
Please give basic query examples like adding, deleting friends and user entries with such solution or mine.
Thanks in advance.

Ok, I found the solution reading the docs a little more. combining cascade, single_parent and passive_deletes i could achieve 3 relationships -
friends - who have accepted friend request
sent_friend_requests - who are sent a request from the user and yet havent accepted
awaiting_friend_requests - who have sent request to the user and yet not accepted
Thumbs up for SQLAlchemy documentations.

Related

PHP PDO/MySQL query not working properly

So I have this website where people can report some tracks. People can do so even tho they're not member of said website and if they're not members, the system will assign them a random "pseudo member number" (pmn from here on) in the style of "not_a_member_XXXX".
$query_claimed = "SELECT * FROM claims_archive WHERE t20pctID=:t20pctID AND member_name=:member_name AND member_email=:member_email AND (member_number=:member_number OR member_number LIKE '%not_a_member_%')";
$stmt = $con->prepare($query_claimed);
$stmt->bindParam(':t20pctID', $t20pctID);
$stmt->bindParam(':member_name', $member_name);
$stmt->bindParam(':member_number', $member_number);
$stmt->bindParam(':member_email', $member_email);
$stmt->execute();
In the testing period we have had some songs have been reported by the same person with a pseudo-number and some with a member number. My problem is that if I make a query with a pmn and the song exists with the same member name and e-mail but with another member number, the code will insert it instead of displaying a message in the style of "You have already claimed this song".
But if I do the query with the member number, then it will display the above message even if the record has it reported with a pmn.
I thought there was something wrong with my logic, but running the above query on phpMyAdmin, it does show the record if there is any matches. I have read about precedence, in case it applies here, and in case there's some operator order I should know about. What am I doing wrong?
Thanks in advance and I hope I made myself understood (English isn't my first or second language).
EDIT to add some info: although I haven't been able to identify a specific pattern for this issue, I have identified that it happens with this particular record.

Not like on Array field

here is the problem I'm stuck with:
I'm using Rails 4 & MySQL
I've Message which have one sender and one recipient.
I want to be able to archive messages but if sender archive a message, the recipient still can access to the message until he archive it too.
I've serialize a field :
serialize :archived_by, Array
which contains which user archived the message
but I can't figure out how to query with it.
Message.where("archived_by like ?", [1].to_yaml)
works well, returning messages archived by User '1'
Message.where.not("archived_by like ?", [1].to_yaml)
won't work, returning nothing
I would like to find something else than using a classic many to many ...
Thanks!
UPDATE
I finally decided to add 2 fields, one for the sender & one for the recipient to know which archived the message. If someone has the proper way to do this, tell us :)
If you are using postgresql you could query the informations.
As in answer Searching serialized data, using active record described, the downsize of serializer at least under mysql is, that you byepass native db abstraction.

Cakephp 3.0 - Validating Input against data in another model

I'm a pretty new to Cakephp 3.0 and I'm quite stuck on data validation, or rather Application Rules.
I have a simple user registration form to create a new user in the table 'users'. In the user registration form, there is a field for "ticket_number" where the user has to enter a ticket number which must exist in the table tickets.ticket_number, and also tickets.registration_status must be false (that ticket had not had a user registered with it yet).
My tables look like this (simplified:)
users:
id | username | password
tickets:
id | ticket_number | user_id | registration_status
In my users model, I have defined (user can have many tickets):
$this->hasMany('Tickets', [
'foreignKey' => 'user_id'
]);
In my Tickets model, I have defined (a ticket belongs to a user):
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
In the users model, I added a rule to attempt to check whether the entered ticket_number exists in the tickets.ticket_number column:
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->isUnique(['username']));
$rules->add($rules->isUnique(['email']));
$rules->add($rules->existsIn
(['ticket_number'], 'Tickets.ticket_number'));
return $rules;
}
This gives me the error:
Error: Call to a member function primaryKey() on a non-object
I'm very stuck here. Can anyone advise on the right approach implementing this check? And then, how to also implement the check to see whether the associated registration_status is 0 (that ticket has not been registered yet).
Thanks in advance for any advice!
--D.
The existsIn rule will not solve your problem, as it will not take your additional condition into account (registration-status).
You will need to provide a custom rule to accomplish the problem you described.
Regarding your update: The rule will return true - so passing the rule, if your tables are not setup correctly or it cannot find the field you are referencing or your field is nullable, check the source here: http://api.cakephp.org/3.0/source-class-Cake.ORM.Rule.ExistsIn.html#74-91
OK, after considerable tinkering, I solved the first issue (On the user add form, the user must enter a ticket number which must exist in the table tickets.ticket_number.)
The only way I could get this to work using an existsIn rule in the UsersTable model, was to declare the ticket_number field as the primary key in the initialize method of the TicketsTable model:
$this->primaryKey('ticket_number');
Then the associations and existsIn rule in the UsersTable model worked. However, this isn't good as I don't want the primary key in tickets permanently set to ticket_number. It also doesn't solve my second problem (checking tickets.registration_status is false.)
So I took a different approach and instead used $this->loadModel('Tickets'); in the add method of my users controller. Then, I could easily perform the required checks:
//Look for this particular ticket
$ticketCount = $this->Tickets->find()->where(['Tickets.ticket_number' => $ticket_number])->count();
$this->set(compact('ticketCount'));
$this->set('_serialize', ['ticketCount']);
//If the ticket isn't found, then return with the Flash error
if (!$ticketCount > 0) {
$this->Flash->error(__('Sorry, but a Ticket with this number could not be found. Please, try again.'));
return;
} //otherwise move on...
I then similarly query the registration status of the ticket, and flash a different error back if it is already registered.
After the checks are passed, it goes on to the normal Add User checks and saving.
While this solution isn't as elegant as what I was hoping to do in the Users model with a custom association and rule, it works.
I'm also not convinced it can't be done in the model with a rule. But for now, this solution works.
Anyway thanks hmic for a response.
DBZ

delete message for one user but not for the other

hello I have a database with 3 tables.
USERS('user_id','name','surname')
MESSAGE_GROUP('user_one','user_two', 'hash')
MESSAGES('from_id','group_hash', 'messages')
My php code enables me to send messages between users. My question is how to enable a user to delete a message from its mailbox but the other user still watching the message. The messages must be full deleted only if both users delete the message. I am not interesting about the code, I am interesting only in finding the logic behind this. Any proposals that includes mysql code are welcome. thanks
I think you should follow this. :)
You can keep an extra field in message_group table something like 'deleted_from' which will be initially 0
If user one deletes it make the value of 'deleted_from'=1, if user two deletes it, make the value of 'deleted_from' = 2.
When you go to delete the message for a user, and you find the value 'deleted_from' other than 0, delete the message completely, else mark the value of 'deleted_from' as '1' or '2'.
You will need to either:
Make a new table that specifies the mailboxes the message resides in, so that you can connect it to both users mailboxes
Or duplicate the message so that each user has their own copy that can be deleted
Add flags to the message table (not recommended) indicating whether the sender or recipient has deleted it. This I would avoid as it will not scale well if you have (or intend to add) group messaging.
add to MESSAGE_GROUP a status field with values :
0 no owner and should be deleted
1 only the sender owns the message
2 only the reciever owns the message
3 both sender and recievers own it
I would change the fields from the table in between like this (example that every user only can send a message to one person at a time):
USERS('user_id','name','surname')
MESSAGE_GROUP('user_id','message_id')
MESSAGES('from_id', 'to_id', 'messages')
So every user that has a message, will have a row in the MESSAGE_GROUP. When one user deletes the post, delete that row in MESSAGE_GROUP

Get a random, unvoted-on post in Rails

So I have a Rails app with three base models: Entry, User and Vote. I need a helper method that will give me a random post for a user to vote on:
def next_entry
Entry.where(:receiving_challenge_id => current_voting_challenge.id).offset(rand(Entry.where(receiving_challenge_id: current_voting_challenge.id).count)).first
end
This works, it'll grab a random post every time.
A vote is owned by a user and an entry and they're related through IDs in the database.
But I don't want to give the user a post they've voted on.
How can I accomplish this?
-Get all the id's of entries
-Get all the id's of entries on which the user voted
-Substract the second one from the first one
-Take any number from that array with the sample method and pull the entry with that id from the DB:
Entry.find((Entry.all.collect(&:id) - current_user.votes.collect(&:entry_id)).sample)
First, get the entries they have voted on.
Then fetch all different entries
voted_entries = user.votes.includes(:entry).collect(&:entry)
unvoted_entries = Entry.where('id NOT IN (?)', voted_entries.collect(&:id))
Then you can call sample on unvoted_entries to get a random one.