I am attempting to create a journal where a logged in user's journal_entries are listed when the index view is called.
I have installed the Devise gem for the user sign up, log in/out authentication.
I have created a model, JournalEntries, which includes a date, string and text fields.
After creating the database, rake db:create and then migrating, rake db:migrate - I attempted to list a users journal entries in the journal_entries/index view. The default view that was derived via scaffolding lists ALL USERS journal_entries. This doesn't make for a great journal - where you can see the entries of all other users.
In my research I've come to realize that I didn't have a field in the journal_entries table which referenced the users table.
I create a migration show below:
class AddForeignKeyToJournalEntries < ActiveRecord::Migration
def up
change_table :journal_entries do |t|
t.references :user
end
#add a foreign key
execute <<-SQL
ALTER TABLE journal_entries
ADD CONSTRAINT fk_journal_entries_users
FOREIGN KEY (user_id)
REFERENCES users(id)
SQL
end
def down
execute <<-SQL
ALTER TABLE journal_entries
DROP FOREIGN KEY fk_journal_entries_users
SQL
end
end
(I also changed the users.rb and journal_entries.rb models to include belongs_to and has_many association - at first I thought this is all I had to do, and somehow the database would pick this up, but it didn't...)
This successfully added foreign key - user_id to the journal_entries table, and I thought I was in the clear.
What is happening now is when a journal_entry is created - the user_id column is blank - no info is being populated there....? I have verified this by logging into Postgres on my local machine.
Any help would be greatly appreciated!
The reason the user_id column is blank in the journal_entry table is because you need to add the current user's id when a new journal entry is created.
In your JournalEntries Controller you'll need to add this to your create action:
#journal_entry.user_id = current_user.id
or, #journal_entry.user = current_user
Then, in your JournalEntries Controller index action:
Instead of #journal_entries = JournalEntry.all you can display only the current logged in user's entries with #journal_entries = current_user.journal_entries.
Hope that helps!
You need to make sure that when you build a new instance of the JournalEntry that it has knowledge of the association with the current user:
# app/controllers/journal_entries_controller.rb
...
def create
#journal_entry = current_user.build_journal_entry(params[:journal_entry])
...
See the relevant part of the Rails Guide for Active Record Associations.
Related
More of a sanity check question.
I'm using a DB relation similar to this, which seems a popular pattern:
Such schema makes a registration and login process quite sophisticated. Say I want to register a user and give them a 'USER' role by default.
For registration:
Create a user and insert to the users table
Get the ID of the USER role from the roles table
Insert newly created user's ID and the fetched ID of the USER role to the users_roles table
For login (I want to fetch the user with their roles):
Authenticate user and get the user ID from users table
Get Role IDs for that user from the user_roles table (user may have more than one)
Get role names from the roles table
I'm guessing that you could probably do some clever JOINs and nested SELECTs to avoid multiple statements (I'm using an SDK though, with no raw SQL option - and that means three separate DB calls) but is there a better way to do this while preserving such DB design?
Problem: When a user is deleted the associated record is not deleted from the database. Instead, I set user.delete column to true. Now I need to put a unique constraint on user.email but only for active users (not deleted).
How can I do this?
databaseChangeLog:
- changeSet:
id: add-user-unique-constraint
author: me
changes:
- addUniqueConstraint:
columnNames: email, delete
constraintName: unique-email-not-deleted
tableName: users
The above naive approach puts a composite constraint on (email, delete) columns, but it doesn't work because in the following flow user is blocked from deleting and creating an account:
register a new user with email "E"
delete the user with email "E"
register again new user with email "E"
delete the user with email "E" -> error: constraint violation
register new user with email "E" -> error: constraint violation
ps. databases are H2 and PostgreSQL
This feature is DB-specific and currently liquibase doesn't support it.
For PostgreSQL you may use direct SQL:
databaseChangeLog:
- changeSet:
id: add-user-unique-constraint
author: me
changes:
- sql:
"sql": "CREATE UNIQUE INDEX user_email_idx ON user (email) WHERE delete = 'false'"
however this will NOT work in H2.
Possible options for H2:
if it's used in tests then you may migrate to PostgreSQL using testcontainers technology (but your build environment will depend on docker)
have custom changesets for PostgreSQL and H2 - you may use preconditions
I have a Rails 3.2 app backed by MS SQL 2008. All its models are by default created in dbo schema. Now I want to have a model which DB table has limited access to it so I want to put it to a different DB schema. How do I do that?
Turns out you can just define it together with table name:
def change
create_table "schema_name.table_name" do |t|
#init table
end
end
Don't forget to add schema_search_path: 'schema1,schema2' to the database.yml.
I am doing a condominium database under Postgres with these three tables (among others)
The tables are listed only with the PK and the FK involved in my problem to simplify the code
TableName: Administrator
PK: admin_id
TableName: Condo
PK: condo_id
FK: admin_id (Connects with Administrator of this condo)
TableName: Property
PK: property_id
FK: condo_id (Connects with parent condo)
Now, imagine there is a administrator with admin_id = 1 and I create a SQL user for him, for example:
CREATE ROLE "john_smith"
LOGIN PASSWORD '123456'
VALID UNTIL 'infinity';
So now I want him to only update the Properties related to a Condo that has him as administrator (admin_id = 1)
How could I do something like
GRANT SELECT, INSERT, UPDATE, DELETE
ON Property
WHERE "The Properties of a Condo with admin_id = 1"
TO "john_smith"
That's the question, thanks!
It is possible to do it on Postgress and this is called Row Security Policies
But you have not posted enough information about your DB to have a clear answer.
The idea is that you have to create specific ROLES that are GROUPS of USERS
In your example you created only a user role. You should add an Administrators usergroup and add your admin users to it.
Then you do something like
ALTER TABLE Property ENABLE ROW LEVEL SECURITY;
CREATE POLICY Property_Administrator ON property TO Administrators
USING (SELEcT true FROM condo WHERE condo.condo_id=property.condo_id AND condo.admin_id= current_user);
Just read the doc I linked and you'll achieve it pretty simply
Hi Experts
How I can prevent database user deleting any data in tables using triggers?
I want just Admin delete Data from tables
Thanks
Umm take away that users permission? If you don't want them doing something, 'disallow' them that right... thats why we have permissions.
Here are details on how to revoke permissions:
http://msdn.microsoft.com/en-us/library/ms186308.aspx
Any particular reason you want to use triggers?
You could simply remove the DELETE permission from the users you want to restrict. Have a look at the "Permissions" section here: http://msdn.microsoft.com/en-us/library/ms189835.aspx
EDIT: Since you say you do want to use triggers (but I really think you should reconsider) you can create a table such as:
CREATE TABLE Restricted_Users
(
user_name VARCHAR(40) PRIMARY_KEY -- Use a size appropriate to your requirements
)
Create INSTEAD OF DELETE triggers on all your tables (that's going to be a chore) which checks for the USER_NAME() in the Restricted_Users table and if they EXIST you can call RAISERROR to cause the transaction to be rolled back and display a message to the user.
Remember you will have to maintain these triggers on all new tables added to the database as well as maintaining the list of users in the Restricted_Users table whenever you add/remove users from the database.
It would be a lot simpler to use the permission system available in SQL Server (it's what it's designed for) using roles with appropriate permissions set for the tables. Then, when adding new users you only have to assign them to the appropriate role and the delete permissions are handled for you.