I am working on a Rails project with act_as_tenant. At the moment, I have a model that looks like this:
class Portfolio < ApplicationRecord
acts_as_tenant :organization
has_many :holdings
end
Additionally, I have this Holding model:
class Holding < ApplicationRecord
belongs_to :portfolio
end
act_as_tenant is working correctly for the Portfolio model. That is, if I am logged in as an organization that does not match the Portfolio's organization, that Portfolio won't exist in the database.
However, as I am logged in as a different organization, I can still access the Holding. But when I try to do holding.portfolio, I get nil.
Is there a way to extend this sort of act_as_tenant logic so that all child models of a parent model will automatically be scoped by tenant as well?
Reading the documentation for acts_as_tenant:
Row-level multitenancy each model must have a tenant ID column on it. This makes it easy to filter records for each tenant using your standard database columns and indexes. ActsAsTenant uses row-level multitenancy.
What this implies that also the holding model should have acts_as_tenant :organization and have a foreign key to organization. This should be the case also for other records you plan to add that are dependent on acts_as_tenant
Related
I have a single users table through Devise. Branching off this table are 3 other models (author.rb, seller.rb and buyer.rb) with each having a one to one relationship with the main Users table.
The reason for this is each have some unique attributes and I want to keep the main Users table tidy. I am using active admin and want to avoid redundant fields when registering a new user.
Currently I am using enums to assign user roles:
enum role: [:author, :sellers, :buyers]
The problem is when I set a role it works in the sense that I can restrict what a user sees based on that role however there is a big issue I have below.
The problem:
I want to be able to register an Author. Everything good so far. But I also want to be able to register a Buyer and then associate that buyer with the author as two different users. At the moment a user is becoming both at the same time through nested forms in active admin I used which is not what I want. I want a user to be a buyer and the other user to be an author.
Maybe I don't have my relationships set up correctly for this? Or it could be a problem in active admin?
class Author < ActiveRecord::Base
belongs_to :user
end
class Buyer < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :author
has_one :buyer
end
Basically I want to be able to register two different users and after that associate them and I don't know how to do this. Any advice much appreciated.
I have a relationship between two models that is currently a many to many. I'd like to move it to a one to one relationship, because that's what all of the data has turned out to be.
Is there a seamless way to do this? Via a migration and model change combo? My models would be simple to just change as shown below:
Now
class App < ActiveRecord::Base
has_and_belongs_to_many :owners
end
class Owner < ActiveRecord::Base
has_and_belongs_to_many :apps
end
Changing to
class App < ActiveRecord::Base
belongs_to :owner
end
class Owner < ActiveRecord::Base
has_one :app
end
But how do I update the database to reflect these changes without losing any of the data I currently have?
Add an owner_id field to your apps table and then iterate through your apps_owners table and set the owner_id field in apps to the owner_id field in apps_owners for the apps record whose id is equal to app_id.
Assuming you're correct and there aren't multiple apps_owners entries for the same app_id following SQL should do it (not tested), although I'm not familiar with how to incorporate raw SQL into migrations:
update apps set owner_id=(select owner_id from apps_owners where apps.id = apps_owners.app_id)
You won't be able to do this simply. The main problem is that has_and_belongs_to_many relationships use a tertiary database table (apps_owners in your case) to hold the relationship information.
After you create the appropriate migration to add owner_id to your App model, you'll need to create a rake task that reads the app_owner table and re-creates the relationships.
Let's say I have a User model and I want to have different user roles. In a single application, you can simple store the role a string, or as another model and that's fine.
But what if you want to store more associations for the individual models? For example, let's say Admins contain links to collections and belongs to many collections that regular users should not be associated to? In fact, other users will be linked to a whole other set of models that Admins do not have.
Do we put all of the associations in the User object and just ignore them based on the type of the user? Or do we start subclassing User (like in Hibernate) to only contain the associations and model logic for that user type?
What is the way to do this in rails? Thanks!
I would suggest using Rails Single Table Inheritance. Essentially, you'll have a users table in your database, and a root User model. Multiple models (one for each "role") can inherit from User, and have their own associations:
# Regular users have no associations
class User < ActiveRecord::Base
end
# Admins have collections and notes
class Admin < User
has_many :collections
has_many :notes
end
# Editors only have notes
class Editor < User
has_many :notes
end
I have some problem trying to understand when building a rails app with several models and relation ships between them...
If I take a basic example like a model Group, a model User and a model Car
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
has_many :cars
end
class Car < ActiveRecord::Base
belongs_to :user
end
Will those relation ship statements automatically create the following functions:
group.users
user.group
user.cars
car.user
It seems that we sometimes need to have to create "references" in migration (like adding a reference toward User in Car table) but is this always required ?
In this case, what is the difference of creating the migration and of adding the relationship statement in the models ? I sometimes have the feeling this is used for the same purpose.
Thanks a lot for your help,
Regards,
Luc
The association declarations are there for Rails only. You have to define the foreign keys (references) in the database, so that Rails can properly save the data.
Remember, despite all the magic, it's still backed by a relational database, so good practices there will pay off in the long run.
I have a base table called users which holds all common information about a user such as name, address, phone number...etc
I have another table called clients which holds specific information about a client (such as the client's company name and their url) and inherits user information from the users table. A client has a foreign key user_id which maps back to the information about a user.
I have another table called client_admins which hold specific information about client_admins and also has a user_id field AND a client_id field (which links to the clients table).
I have another table called super_admins which links to the users table and has specific information about a Super admin.
I know I could probably get away with Single Table Inheritance as there is not a lot of different data between each of the types, just different functionality and privileges.
What is the best way to model this in Rails 3?
Inside your user model:
has_one :client
has_one :client_admin
has_one :super_admin
Inside your client model:
belongs_to :user
has_one :client_admin
Inside your client_admin model:
belongs_to :user
belongs_to :client
Inside your super_admin model:
belongs_to :user
I am unsure of whether this is exactly what you were aiming for, but with my citier gem you could do this:
class User < ActiveRecord::Base
acts_as_citier
# User methods and validation, inherited by all children (so client & super admins)
# Useful for things like validating user permissions etc
end
class Admin < User
acts_as_citier
# Admin specific methods and validation, inherited by all children
end
class Client < ActiveRecord::Base
end
class ClientAdmin < Admin
acts_as_citier
belongs_to :client
# Client admin specific methods and validation
end
class SuperAdmin < Admin
acts_as_citier
# Super admin specific methods and validation
end
Allows each model to have unique fields so better than STI, but also shares methods and properties like normal inheritance.
Check it out - http://peterhamilton.github.com/citier/