How to make column data unique for each user_id in ruby on rails - database

The problem is that I have a table customers with some customers related columns like customersID.
Also I have a column user_id So that the customers data only relate to one user.
class Customers
belongs_to :user
end
class Users
has_many :customers
end
Now I have the :unique on the customersID. But this makes every customerID unique all over the table.
What i want is that the customerID is unique per user_id.
Any idea or suggestions?
Edit: Question seems bit unclear.
I have a table users
user1
user2
user3
also i have a table customers where each customer get a user_id from the user who created him. The user can input a customerID, which should be unique for each user.
customerID=1 user_id1
customerID=2 user_id1
customerID=1 user_id3
customerID=3 user_id1
customerID=1 user_id2
...
I crud the customers data via #customers = current_user.customers in my CustomersController. The customerID is a simple t.integer "customerID"

It seems as if you want a Customer to have a User, is that correct? Try something like this:
class Customer
has_one :user
end
class User
belongs_to :customer
end
That way you can have a customer tied to one specific user_id. Then you could do something like this:
#customer = Customer.where(name: "company name").first
#user = #customer.user #this will find the customer's unique user

Why not force uniqueness of the pair Customer_id, iser_id via an index on your Customers table ? You could create a migration something like
add_index_to_costumers.rb
class AddIndexToCustomers < ActiveRecord::Migration
def change
add_index :customers, [:customerID,:user_id], unique: true
end
end
It should ensure at the database level that the pair customerID/user_id is unique. If I well understand your question it's what you expect.
Hope this helps
Cheers

Related

Ecto delete many_to_many join whilst keeping joined records in tact

I have two Ecto models: User and Skill, which are joined with a many_to_many association via a users_skills table:
create table(:users_skills, primary_key: false) do
add :user_id, references(:users, on_delete: :nothing)
add :skill_id, references(:skills, on_delete: :nothing)
end
create unique_index(:users_skills, [:user_id, :skill_id])
In the User schema there is:
many_to_many :skills, Skill, join_through: "users_skills"
And in the Skill schema there is:
many_to_many :users, User, join_through: "users_skills"
What I want to do is delete a user’s skills without deleting the User or Skill itself. Currently I’m trying this:
query = Ecto.assoc(current_user, :skills)
Repo.delete_all(query)
However it throws the error:
(foreign_key_violation) update or delete on table "skills" violates foreign key constraint "users_skills_skill_id_fkey" on table "users_skills"
When adding on_delete: :delete_all to the users_skills migration, this has the undesired effect of deleting the associated skills.
How do I approach this so that only the association record is deleted with both User and Skill staying in tact?
I'm sure there're better ways to do this but you can pass on_replace: :delete option to many_to_many macro in your schemas.
defmodule User do
use Ecto.Schema
schema "users" do
field(:name)
many_to_many(:skills, Skill, join_through: "users_skills", on_replace: :delete)
timestamps()
end
end
Now if you run
current_user
|> Repo.preload(:skills)
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:skills, [])
|> Repo.update!()
It deletes from users_skills table and skills table will remain intact.

Laravel: Create tables with variable in name

How can i create and migrate lots of tables in laravel with a variable in their name?
I need to create a table "time-{{user_id}}" every time a new user is added to a table called "users".
How can i realize this and how does the Migrationfile/Controller/whatever has to look like?
Thanks!
"Now i need a table for each user where i can store something like a CV.. Date begin, date end, City etc"
Sounds like you need another table with a 1:1 relationship to the users table
Your new table will look something like
tblFurtherUserInfo
FurtherUserInfoId
CV
DateBegin
DateEnd
City
You should add a new row to this table and set FurtherUserInfoID to be the same as the userID in your user table. You should do this whenever you add a record to your user table
EDIT
Now I know a user can have more than one CV, you need a new table as follows
tblCV
CVId
UserId
CV
DateBegin
DateEnd
City
This is a 1 user : many CVs relationship

How to model M-M relationship with differnce variation

If the user requirement mock-up to something like that :
1-Company (id -name -etc)
and each Company has (Iron,Cement) entered in specific (month-year) .
The Iron has local sales and the Cement has Exporting.
Each Company has (Start balance) for (Iron,Cement) entered only once .
How to model something like that ?
Assuming I understood your domain one could do something like this:
Company(id, name, ...) // PK = id
Material(id, name) // PK = id
Entry(idCompany, idMaterial, month-year, production, localSales, exporting) // PK = idCompany, idMaterial, month-year
Initial(idCompany, idMaterial, date, balanceStart) PK = idCompany, idMaterial, date
If you create your tables this way you can use one table to store data for both cement and iron. You can then write a custom VIEW to display only relevant columns for each material.

SaaS- Tenant Specific Lookup Data in Shared Database

I am developing multitenant SaaS based application and going with Shared Database for storing all the tenant records with help of TenantId column.
Now the problem is i have some list of lookup records that needs to be shared for all the tenants. For example list of games.
GamesTable
Id
GameName
Also have another table used for storing only tenant specific records
TenantGames
Id
TenantId
GameName
The basic need is i want to use both table data and get the necessary details (Game_Name) while joining with another transaction table like UserGames. How can i achive this with this design? Here Game_Name can be either referred from Games Shared table or TenantSpecificGames table
Is there any other DB design which allows me to do mix both common master data and tenant master data with JOIN?
Basic requirement is keep common data and allow customization for the tenants if they want to add any new items.
This is the design I would then use.
Games
Id
GameName
IsTenantSpecific
SomeGameSpecificColumn
TenantGames
GameId
TenantId
SomeTenantSpecificColumn
AnotherTenantSpecificColumn
Then you can query that table in a Join with:
...
FROM
Games
INNER JOIN UserGames ON
UserGames.GameId = Games.Id
LEFT JOIN TenantGames ON
TenantGames.GameId = Games.Id
WHERE
TenantGames.TenantId = #tenantId OR
(
TenantGames.TenantId IS NULL AND
IsTenantSpecific = 0
)
Game specific fields can be put in the Games table. Tenant specific fields can be added to the TenantGames table, and those fields will be NULL if it is not a tenant specific customization.
We have a saas based database and we keep common data and tenant data in the same table.
Concept
GamesTable
Id NOT NULL
TenantId NULL
GameName NOT NULL
Add a unique key for TenantId and GameName
if TenantId is NULL you know it is common data
if TenantId is NOT NULL you know it belongs to a specific tenant and who exactly.
"Is there any other DB design which allows me to do mix both common
master data and tenant master data with JOIN?"
Yes
SELECT *
FROM GamesTable where TenantId = 'your tenant id'
UNION
SELECT *
FROM GamesTable where TenantId IS NULL -- common
This is a classic example of "many to many".
Table: Games
------------
GameID
GameName
IsMasterGame
TennantGames
------------------
GameID
TennantID
Tennants
------------
TennantID
...
To get the games for a given tennant, you would run a query like:
select *
from Games
where isMasterGame = true
union
select *
from Games g,
TennantGames tg
where g.GameID = tg.GameID
and isMasterGame = false
and tg.TennantID = $currentTennant
(Apologies for archaic join syntax)
The union allows you to ask two questions: which games apply to everyone (isMasterGame = true), and secondly which games apply to the current tennant (tg.TennantID = $currentTennant). Logically, tennant games cannot also be master games.
You can merge the tables leaving TenantId as NULL for records you wish to not be Tenant specific.
Games
Id
TenantId
GameName
The you can query that table in a Join with:
...
FROM
Games
INNER JOIN UserGames ON
UserGames.GameId = Games.Id
WHERE
Games.TenantId = #tenantId OR
Games.TenantId IS NULL
This will save you the trouble of ensuring that the Id is unique between the tables, unless you are using a UNIQUEIDENTIFIER for the Id.

Creating relationships in Microsoft Access

I'm creating a database to track my students' participation in classes. This is what I've set up so far. I'm working in Access 2007.
Participant Master table - name, contact info, enrolled class, enrolled semester. Enrolled class (Class A, Class B, Class C) and enrolled semester (Semester 1, Semester 2) are defined in tables. Primary key is an autoincrement number but students all get a school ID number (ParticipantID).
Query1 pulls name & address for students enrolled in class A, semester 2
(SELECT name, address FROM ParticipantMaster WHERE EnrClass = "Class A" and EnrSem = "Semester 2"). The query works.
DailySessionLog is a table to represent each daily class. Includes fields for date, instructor name (check from list), discusssion topic (check from list).
Now I want to link DailySessionLog to Query1 -- letting me check off every day whether a student was there for None, Partial, Half, or Full session that day. I'm having trouble linking these and creating a subform. Any help?
I tried having a ParticipantID field in DailySessionLog which I linked to ParticipantID in Query1. It doesn't recognize if it's a one:one or :many relationship. If I go ahead and create a subform using the Access wizard it treats the Participant data as the "higher" form and the DailySessionLog data as the "sub" form. I want it to be the other way around.
Thanks for helping!
To create a one-to-one or one-to-many relationship, you should link DailySessionLog to ParticipantMaster rather than to Query1. You would then create a query to show the daily session logs of a given class for a given semester. Example:
SELECT {field list} FROM ParticipantMaster INNER JOIN DailySessionLog ON {join expression} WHERE ParticipantMaster.EnrClass = "Class A" AND ParticipantMaster.EnrSem = "Semester 2"
However, it would be better to use variable parameters rather than hard-coded strings. Example:
SELECT {field list} FROM ParticipantMaster INNER JOIN DailySessionLog ON {join expression} WHERE ParticipantMaster.EnrClass = [ClassName] AND ParticipantMaster.EnrSem = [SemesterName]
Or, to use a value from a control on an open form:
SELECT {field list} FROM ParticipantMaster INNER JOIN DailySessionLog ON {join expression} WHERE ParticipantMaster.EnrClass = [Forms]![FormName]![ClassControlName] AND ParticipantMaster.EnrSem = [Forms]![FormName]![SemesterControlName]
EDIT
Actually, you want to use this AND xQbert's idea, so, with table names like this for brevity:
Participants (a.k.a. ParticipantMaster)
Sessions (a.k.a DailySessionLog)
ParticipantSession (a.k.a. Participant_daily_session_log)
the first query would be more like this:
SELECT {field list}
FROM
Participants
INNER JOIN ParticipantSession ON Participant.ID = ParticipantSession.ParticipantID
INNER JOIN Sessions ON ParticipantSession.SessionID = Session.ID
Where do you intend the database to "Store" the participation?
I think the problem is you need another table: a Particpiant_Daily_sessioN_log which would store the results of your daily log for each student participation.
Think about the table dailysessionlog you don't want instructor name, topic and date listed for EACH student do you?
So what you have is a many students may attend class and a class may have many students. This means you have a many to many which needs to be resolved before access can figure out what you want to do.
Think of the following tables:
Participant (ParticipantID)
Class (ClassID)
Session (SessionID, ClassID)
ClassParticipants (ClassId, ParticipantID, Semester, year
SessionParticipants (SessionID, ClassID, ParticipantID)

Resources