I am writing a RoR app. I would like to allow multiple clients of mine use it as a cloud based application. I don't want to have to duplicate the code for each customer.
I assume this means using a subdomain for each of my customers, and have a table for Customers. The Customers table would have a field for the domain.
In other words -- I want each customer to only see their records.
My questions are:
Has someone documented how to do this in Rails? Where is it?
Would every table have to have a customer_id in it? Or if you have a Project table with the Customer_id, and then have tasks for the Project, you wouldn't need the customer_id in the Task record - right?
Would you have to start each view with Customer. ??
Any thoughts would help!
Thanks!
There's a railscast about handling subdomains in Rails 3 here: http://railscasts.com/episodes/221-subdomains-in-rails-3
Regarding point 2, you'd just need the customer_id on Project, you wouldn't need it on Task as well.
I'm not sure what you mean about starting each view with Customer., but I'm guessing not. Maybe going through the railscast will answer your question here.
You also need to think about authorisation, ie does the current user have the permission to view/update these records? I personally recommend the cancan gem for this purpose https://github.com/ryanb/cancan, you define a single model/abilities.rb file in your app that contains all the permissions for your user. I've found it works really well.
Has someone documented how to do this in Rails? Where is it?
The whole thing? Not that I am aware of.
For the subdomain? Yes, and it is called catch-all A record, catch-all subdomain, ... etc.
Simply, add a wildcard (*) A record to the domain and then use request.subdomain in RoR to extract the subdomain requested.
#cheeseweasal answered the rest.
Related
I'm a bit of a Rails beginner, so I'm sorry if this question is easy. I'm wondering how I am supposed to modify the Rails database as a developer without letting users of the site modify data.
More information:
Let's say I am trying to create a website that lists books along with their information. I want users to be able to see these books, but not add/delete them. As a developer, I want a way to add books without using the command line (hard to edit mistakes). What's the easiest way for me to do this? Would there be any differences between the development database and a live hosted one?
I think there are a few approaches to do this.
different user roles. This technically breaks the rule of without letting users of the site modify data, but being able to differentiate between normal and admin users means you can limit who actually can add data into the database. I used cancancan as a way to authorize requests but I know there are others.
I agree doing it using the command line isn't ideal, but rails do support rake tasks. You can create a task that will handle most of the logic and all you need to do is something like
rake create_book["name here"]
This will make the process less error-prone.
Create data using rails migrations. Rails can generate the skeleton file for you, and you just ran any ActiveRecord methods. However, the main purpose of migration is to update the database schema, but they can seed the database as well. here's the example from the dcos
Would there be any differences between the development database and a live-hosted one?
Yea, they should be totally separate database instances. You don't want to have your development database be the same as the live one. This would cause major problems. Rails have a concept of environments where you can use different configurations, so you can pick and choose what database URL to use.
like #davidhu said here The best approach really is the use of authorization. If only admin can see a page to CRUD the books then you don't have to worry about normal users doing same plus it makes it easy for you as the admin to make changes or add to the collection. Add the gem (or reinvent the wheel) then Rails will take care of the rest for you.
I have Rails Admin installed which is working great. However I have a problem. Only admins can sign into Rails Admin and there are two types of admins. The first type of admin can have access to everything, delete anything they want, etc. The second type should only have access to certain tables.
I don't see any configuration with Rails Admin to get what I want so I was thinking of using a callback in my models. But then I would have to somehow pass through the user's credentials to verify what type of admin they are, and even then there would have to be a lot of hacking. My question is, can this be done, and if so, whats the best way to do this?
I have used CanCan in the past to accomplish exactly what you're looking for. It worked well with Rails Admin.
https://github.com/sferik/rails_admin/wiki/CanCan
As an aside: I would recommend using a single role per user as that seems to make things easier.
I'm building a rails3 application and at the moment I have the following line in my routes.rb file:
get "/:id" => 'tapes#show'
In other words, you can show a Tape using website.com/tapes/1 and also by using website.com/1
(I am also using friendly_id gem so the user sees in fact a friendly URL in the form of website.com/tapename)
Now, what I would like to achieve is to do the same thing for Users pages. So instead of showing a User page using website.com/users/alex I want to be able to also use website.com/alex.
Is there a way to implement this 'users' logic in routes.rb together with the existing 'tapes' rule and somehow set a priority?
So if someone accesses website.com/alex my app would search if there is a User record with id 'alex' and if none is found then look for a Tape with id 'alex'.
Could I use some kind of Advanced Constraints in routes?
Any ideas?
Many thanks for the help,
Alex
Rails would have no way to determine which controller you were trying to access. The only way that this would be possible, is if either:
you could determine which model it would resolve to based upon some regular expression on the name.
or
You knew that user names and tape names never conflicted, and were willing to suffer the cost of hitting the database to resolve the correct controller.
This is probably a bad idea for a number of reasons, it would have performance implications, it also doesn't conform to RESTful principles, and it would probably be confusing to users.
I have brands and products, and there is a nightly load that replaces them. A brand may end up with a new id, and a product will always end up with a new id. But I have customers that want static links to these dynamic ids.
I would like a link that now looks like:
.mysite.com/brands/17/products/168390
to look like:
.mysite.com/products/ABC123
where "ABC123" is an alphanumeric identifier not associated with the id. Think of it like a model number.
I don't need anyone to give me the answer, I am happy to do the work. But any pointers to where I can get started would help, as I apparently don't have the right terminology to do a successful Google search.
Thanks!
I would suggest watching the screencasts done by Ryan Bates at RailsCasts.
For your question on how to change the products URL away from id, the specific ones would be Model Name in URL or Semi-Static Pages (just the information on how the routing is accomplished). For your question on the shortening the nested URLS, what you want would be his cast on Nested Resources.
Those are the ones that have to do with your specific problems, however I would suggest watching all of them in order to learn more about the framework. One thing to note is that since those are fairly old, things may have changed some in Rails 3, however I imagine that once you get something to Google, you will be able to find how to do it in Rails 3 fairly easily.
Do it using rails routes. Something like:
match 'products/code/:product_code' => 'products#code'
There are lots of things you can do with routes - my suggestion would be to familiarize yourself with them.
I am building a new Rails-based application that will have Basecamp-like accounts for each subdomain. Each account (client/customer) should be allowed to store different settings such as a color scheme, their subdomain, their preferred authentication mechanism and so forth.
So, how should I handle the settings for each account such that I can easily add new settings later that apply to all accounts? Examples or ideas of how to build the objects and relationships (i.e. many-to-many) would be great. Additionally, if you have any good articles, I would greatly appreciate a link to those. This app needs to be highly professional and I want to make sure that I get some of these basic things right before I jump into the remainder of the project.
Thanks very much!
This question addresses a similar situation. It's worded a little differently. But if you map the question's description of a product to one of your subdomain it still feels pretty relevant. You're not explicit but with the comparison to basecamp I'm assuming that each subdomain will have it's own set of users who also have their own settings. Settings that might not be global to your application. The linked question address that too.
I see this working best as a single table for subdomain settings.
With an index on a column linking it to a customer/client/userid, another one linking it to a subdomanin.
Each option that effects subdomain design gets a column in this table. On page load just look up the row for the subdomain in the table in a before filter and things should go relatively smoothly. Adding new global options are simple. Just graft another column onto this table with an appropriate default value.