New Discussion

Notifications

You’re not receiving notifications from this thread.

Multitenancy with the Apartment gem Discussion

79
General

Hi, Chris video is not loading!

Great job Chris.

Kohl Kohlbrenner Kohl Kohlbrenner

@ChrisOliver is self.matches? called automatically?

Yep! Rails knows to delegate that appropriately behind the scenes.

Jonathan Denney Jonathan Denney

Thanks Chris. Is there any way to do this where it's URL based, rather than subdomain? For example myapp.com/company1/posts instead of company1.myapp.com/posts

I'm sure you could. You probably need to switch the tenants manually in this case. If you didn't need the company in the URL, you could also have it switch tenants in a before_action on every request based upon the user that is signed in and the tenant they are associated with.

Hey Chris, I've started adding this to an existing application. So far I've got four "accounts" at the global level that are already created and have users for each account. I've had these on one DB up until this point. I was able to add the subdomain attribute to the account and it's stored in the db. i ran rake db:migrate and got the following: see screen shot. I've checked in the rails console and it's storing the subdomain for each account but for some reason apartment isn't finding the tenant. Any ideas?

EDIT: It is working if I create a new school from scratch..

Are you able to go back and retroactively create those tenants for records that already exist?

Wow This just great I was looking for something like this ill be your new member on gorails. :)

Thanks! :)

Can I do this with company. So when I create a company the company gets the subdomain. and do something like User.company.subdomain to look for the tenant ??? as my app is goin to have User model and Admin model. Admin will create the Companies and User for the companies

Yes you can! Just add that attribute to the company and you can use that.

Antonio Marcos Silva Junior Antonio Marcos Silva Junior

Thanks Chris. This is great information. Do you know if Apartment allows different databases to be hosted in different database servers? E.g. if I need to scale out, can I move a database to a new DB server and somehow tell Apartment that that DB/tenant is hosted in another server?

I would imagine so, but you'd probably want to ask on their Github issues to be sure. This is probably just more of a database configuration thing than anything with apartment or Rails.

Thanks so much for this! I've got this up and running, but I don't know how to edit/create records in the rails console once the tenants and schemas are created.

With no tenants, you can do Post.create(name: "test post), but how do you find, edit, create posts by schema from within the rails console?

Thanks to Chris, the answer, for anyone else wondering, is simply to specify your tenant in the console by using Apartment::Tenant.switch!('tenant_name') first.

So, rails c, Apartment::Tenant.switch!('tenant_name'), then Post.first will be the first post for that tenant, etc.

Great info, thanks a lot for putting this up! One suggestion tho: when you create SubdomainConstraint and check if the subdomain is present _and_ not in the list... you don't have to check if it's present, because the list won't contain blank, nil, etc. :-)

Yes indeed! :) Mistakes in video are forever... ;)

Thanks Chris for the awesome video! Would Apartment allow you to do something like Heroku where you can create projects with their own subdomain such as mysite.herokuapp.com but then point your site name so that you can navigate to the page by the actual name such as mysite.com? What i would like to do is allow users to create their own sites and not necessarily subdomains or allow them to point their site names to their own subdomain. Any help or tips would be great.

Thanks Chris, great material.
Could you give me adivce?
I'm creating application for dietician as a project on my studies. There will be a database with about 15 tables(like products, meals, tags, diets etc.). I'm going to create users with accounts. Each user should have access only to his tables (products which he added etc.). Do you think apartment gem is best approach for this problem(I don't want to use subdomains)? Or maybe could you recommend me another aproach? I wonder about add user_id column to every table, but it would generate so many records in database. What do you think?

You can just associate all the records with the user_id. The only time you need Apartment is if the data should be kept private in their own databases for security reasons. You should be fine associating them to the user and making sure you don't load the other users's records.

Anyone got this working with Active Admin?

I would really like to know the answer to this! It would be great to offer ActiveAdmin functionality to each Company in a subdomain. If I figure it out I will post here.

Jordano Moscoso Jordano Moscoso

Does it work only on production mode? Because a have created a host on my hosts file but when i create the tenant and go for it, no server respond. (I'm using puma.)

It works everywhere. You might need to make sure you have Puma running on the correct IP (I think in this case you'd want 0.0.0.0) and that you're accessing the host with the correct port as well.

Jordano Moscoso Jordano Moscoso

Chris, i have a important question. Can it work with subdomains of a subdomain? How would be that?

Yep, I'm sure it can. You may have to build a custom handler for it based on their Subdomain one, but definitely could work. Check their docs / Github issues for more on it as I haven't done that before so I don't know the details of what you'll need.

Thanks Chris, is it possible to transfer a record from one tenant to another while using apartment/multitenancy? how wd you go about that. Thanks. Gret Article.

That's a good question. Aside from a brute force approach, I'm not sure. What I would probably do is just query for the record, make a copy of the object with .dup, switch the tenant to the new one, save the duplicate in the new tenant, verify it exists, switch back to the old tenant and delete the old record (if necessary).

Hi Chris, great videos. I have a question , is it possible to use this gem without subdomain. So every tenant will have same domain but inside the logic there is scheme segregation. I already tried to config in domain many times but looks not works. Do you have an idea / sample ? Any help or tips would be great

Yeah, you can use anything you want to switch the tenant. I'd ask this question on the Github repo though. They're the ones that know it really in-depth and can get you the best answer!

I was able to create a multi-tenant app based on this tutorial. But now any user can login from any subdomain and the data will be shown based on subdomain e.g. if 'user1' login from user2.example.com it will login fine but it will show records of 'user2'. Ideally, user1 should not be allowed to login from any subdomain other than user1.example.com and if it is logged in it should be redirected to correct subdomain url and never be allowed to see other users record.

You'll want to modify your authentication code to lookup the current tenant and then scope the User lookup query to only ones for that domain that way only users of that tenant can access that tenant.

check this out 

https://github.com/plataformatec/devise/wiki/How-to:-Scope-login-to-subdomain

Chris - how does this work if the rails app is just an API?

Nothing different. An API just doesn't have HTML, JS, or CSS to serve up, but everything else is the same. Any multi-tenancy is on the database level, not the UI level.

Ratna Vanapalli Ratna Vanapalli

Hi Chris , I am using rolify and I want to exclude roles , how to do it ? I did the following

config.excluded_models = %w{ User Role}

But I want to exclude users_roles table too, How can I do this ?

Okay, so I have Apartment working wonderfully in an app. The issue that I'm having is that Google Apps / Mail isn't able to send or receive. I'm guessing the app is intercepting traffic meant for "mail.appblah.com". I've been unable to find a recommendation as to how this should be handled, ideas?

Jeremy Christopher Bray Jeremy Christopher Bray

Hi joe, how did you go? Are you using devise for authentication? if so this might help

config.action_mailer.delivery_method = :smtp
config.action_mailer.default_url_options = { :host => "localhost:3000" }
config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false

ActionMailer::Base.smtp_settings = {
:address => 'smtp.gmail.com',
:domain => 'mail.google.com',
:port => 587,
:user_name => 'your_email@gmail.com',
:password => 'your_password',
:authentication => :plain,
:enable_starttls_auto => true
}

Hello Chris Oliver,
Its a great video. I need some help regarding the same so I have the scenario with user and company. User has one company and that company has many orientations. And there are only 6 orientations possible. So i need to generate 6 sub domains with specific company. So can you please give me some brief in this scenario. 
Hi @Chris Oliver,
it's a great video as usual, but i have one question which is how to handle one-to-many or many-to-many relations between the general aka public schema and the other schemes ? 



Hi Chris,
Thanks for the wonderful video. It is really great to have this kind of detailed explanations. I have a requirement for different user set for different databases. Can you please guide me, how can I achieve that. I am using MySQL.

I apreciate your valuable time.

Thanks.

Hi @chris Oliver, just wondering if you think the Apartment Gem is still a good solution for multi tenancy?

Also if you don't necessarily require the subdomain functionality but just looking for a way to setup Account with users funcitonality is there another gem or just do it manually?

Cheers
Josh

Hey Josh,

We use Apartment for AthleteProgress. It is a great tool IF you want to have your accounts separated by subdomain with certain models scoped to the subdomain. If as you note, Accounts do not need to be on subdomains, I would just scope the user to the account and skip the complexity that Apartment can add.

Hey @joe, thanks for the response much appreciated.

Yeah I was thinking that as well so thanks for reaffirming. I think i'll head down the simpler method. :)

Cheers
Josh

checkout the acts_as_tenant gem.. Ive used it in apps where i dont need the full power of apartment or subdomains..

Extremly easy to implement aswell!

Great video, thanks Chris!

What do you think about the performance issues highlighted in the gem author's blog?

https://influitive.io/our-multi-tenancy-journey-with-postgres-schemas-and-apartment-6ecda151a21f

I think there is a note that relates to the way rails was analysing the schemea for each tennant causing bloat in the readme, so maybe that is fixed now. But what about the postgres issues that they / heroku had issues with. Is apartment gem ok to use for > 50 users?

Looks like the gem currently has no active maintainers

https://github.com/influitive/apartment/issues/591#issuecomment-478746238

Nice find! Thanks for pointing it out. It's probably enough to sway me against using apartment.

Hi all

WARNING RE: Multiple schemas

For those implementing a multiple schema approach - where each customer / client / project etc. has their own schema, it is not without its problems. Consider this warning here - if you plan on using Heroku: https://devcenter.heroku.com/articles/heroku-postgresql#multiple-schemas . Granted, this is a problem that you will likely WANT to have (i.e. this means that your SAAS will have taken off into the stratosphere, if you have 50+ or more customer accounts), but it is a warning that is worth giving some pause for consideration.

Memory Bloat, Migration Problems
Tenancy by schema might be very good and quick for a small number of clients, but it seems like once you start scaling, you may run into troubles. Brad Robertson suggests are saying you may run into client memory bloat (because active record caches all tables in all schemas), so you'd get 500 mb memory bloat right off the bat. Robertson also cites anecdotal opinions that it's costing a lot more to house a database using the schema approach.

Source: https://influitive.io/our-multi-tenancy-journey-with-postgres-schemas-and-apartment-6ecda151a21f

This is something that I have not looked at, at details - i don't have concrete numbers, or reasons: wondering if anyone has any thoughts on this?

(btw Chris -- thank you for your generous tutorials / time.)

Citus which is a Postgres company designed around supporting multi-tenancy always recommends using row based segregation. They've built this gem which I would highly recommend. https://github.com/citusdata/activerecord-multi-tenant

that looks great. will you be using that with jumpstarts multitennancy features?

I am seriously considering switching now. When the developers of Apartmment say don't use Apartment that is a sign lol

I just made the switch to the Citus gem.. super simple and easy to use!

Question - how are you setting the tenant? Just saving a simple session variable with the tenant name?

You can do something like this. In application_controller.rb

set_current_tenant_through_filter
before_action :set_tenant

def set_tenant
   account_id = user_signed_in? ? current_user.account_id : false
   set_current_tenant(account_id)
end

I guess I should have been clearer - I have a SSO type system with an 'enrollment' between the tenant and the user (the same user can access multiple tenants with a single login). The enrollment holds the tenant information.

My thought is to just store the tenant name in a session variable. Then I can switch the enrollment and then the app controller can switch the tenant based on the stored session.

heyheyheyheychrisheyheyheyheychristryusingthecommentsystemfromamobile

Hahaha, I noticed that the other day. It won't capitalize, I couldn't paste. SimpleMDE is not very good on mobile it seems. Might have to replace it with Trix, but we lose Markdown support. :(

Haha this is what I was talking about a while back. Can't respond on mobile.

How in the world do I create the tenant and after creation it redirects the user/account to said subdomain

Great video! I'm working on my little MVP and wondering if multitenancy is the way to go.

Is it possible to query ALL records of all tenants? Like if I had a post model, and wanted the home page to have the 'Most Liked Post'. If I don't need subdomains, is multitenancy even the best option? Could I get by on only using Devise?

Not with Apartment since they're in separate schemas. If you do row-based multitenancy you can. Check out acts_as_tenant. That's what we use for JumpstartRails.com and it's a lot more flexible and scales better.

George,

I would recommend roe based with something like acts as tenant! Apartment has its purposes but if your going to scale at any point apartment will for sure bite ya! I used to want to use apartment until I found go rails and heard horror stories lol

Hello, do you intend to do a very detailed tutorial of actes_as_tenant ?
Tank's :)

+1 to this

+1 to this too <3

its possible to use this gem without subdomain. So every tenant will have same domain but inside the logic there is scheme segregation ?

Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 88,697+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.