I have customers and invoices. The users can delete customers, but not invoices.
The problem is when a customer is deleted I can no longer do
invoice.customer.name
Because customer is nil.
I have some solutions on the drawing board
Save some info about the customer on the invoice instance when the
invoice is made.
Not deleting the customer, but hide it from the user with a boolean
field. That way the customer instance is still around.
I know this question might be closed because the answers might be opinionated. Rails is very opinionated on almost everything. On this problem, I have never seen a opinion, so:
What is the rails best practice in this case?
(If you have a better solution I'd like to see it)
If you'd like to set up a deleted_at flag, I'd recommend using the paranoia gem.
https://github.com/radar/paranoia
It is exactly what your second option is and implements all the scopes that you might need.
Your second solution seems to best IMO.
Rather than deleting the customer, introduce a DELETED flag on the customer database (then add it as a default_scope to ignore customers with DELETED = true)
this way you can leave the relationships intact. if you have loads and loads of customers, you might need to think about an archiving mechansim, but I wouldn't worry about that.
Related
been kicking this one about for a while now, and would like to get someone who knows rails to test my theory (I'm new to Rails).
In my (simplified) scenario, I want to manage a list of Users, some of which are, for example, "paid" users, some are "free" users etc, and there is a straight "isa" relationship. i.e. a paid user isa user, a free user isa user etc
To reduce redundancy and to keep it semantically correct, I want to manage all the users in one table and use a foreign-key back to the correct "type" of user, so I can create a role of the correct type. e.g. I would instantiate a User, get the id and store this in the user of correct type e.g. "PaidUser" in the "user_id" foreign-key. This gives me the ability to store specific metadata I want to store against them, and I don't have to have one table ("users") with every field for every type of user.
This sort of feels like a confusion of roles and types of users. My question is, is using the approach above going to make life difficult? Is there an accepted approach to this in Rails that I'm missing? I'm using Devise and have removed all routes except for /users/ thinking I would pass a "type" as an argument, and use that type to create the corresponding "real" type of record at the same time as the user. Is this bad practice too?
Thanks in advance
What you're doing sounds fine, but to be honest unless you have a lot of these different properties between user types I would just put them all in the same table. It's not really a big deal to have a couple of blank columns here and there, especially when it saves you from having to do a whole load of difficult stuff. If this starts to seem unwieldy then you can worry about what to do then - it would still be easy to change. You could even then potentially use Single Table Inheritance to give all the different user types their own class that inherits from the base User class, which is where you take care of all the authentication etc.
If you immediately go with something more complex then it will be much harder to unravel if it turns out to be wrong than if you start with something simple. If you go with the multi-table approach then make sure you name them sensibly. I would go with PaidUserProfile etc.
Guys I am becoming completely nut on this...and can't figure out at all how come out of all this troubles.
I really need an holy help, or at least some suggestions about tutorial and guides about this problematic.
I believe that this is a very common task in many app, but I can't find nothing that help in this sense, not on stackoverflow, not on google, not on other rails forums that I know...I start to feel like a dumb!!!
Problem
(1) Models (the models that are involved)
User.rb
Item.rb (is nested in user: e.g. user/3/item/5)
(2) What I'd like to do
The current_user (the user that is logged in) can create an Item, and in the same form can decide to share it or no with many other users.
In this way, the item will be visible and accessible also for this users that we shared it with.
I understand that what is going to be involved here is:
(a) has_many :through relationship between item and user
(b) a joint table that we can call sharing (with item_id and user_id)
(c) eventually using different name for the user and use a :class_name to point to user
This is not hard to implement (and there are plenty of examples around).
What is really a mess, instead, is how build the controller (item controller), in order to perform in one shot, the creation of a new item, and the sharing operation (this means setting up the parameter in the joint table, and eventually create as many records as many users we are sharing with - array?)
And the other problem, that obviously is related with the controller, will be the view...how put all this in a single form, and allow the current_user to just click the button, and perform the item creation + the sharing operation?
Last thing, but not the least, how I need to deal with the fact that User is the same model of current_user??
I really don't know what I need to read or look up in order to let this work, I would love to see some example code,but at the same time I'd love to really understand the logic in all this, in order to be able to replicate it in other scenarios.
Please someone help me...I can't really move on in my app development without doing this, and this is also a crucial part of all the project.
Thanks so much for every small bit of help that I will receive.
Ok I have solved all my problems...that was not an hard task at the end (it's always easy saying that when you solved the issue:))
The only doubt that I still have is with the rails name convention:
Can be possible that using a name like sharing, for the joint model, that the final -ing is not very well handled by rails?
After many tentativeness performed to try to fix my problem, I discovered that everything was set up properly, and that just changing the joint table name from sharing to share, let the magic works!!!
We're building an application for product support. The idea is to have multiple subdomains, each for supporting other organizations products. We call this Account - each account is tied to exactly one subdomain.
Users also have roles - but, user can have one role on account1, and other role on account2.
Basically, there are two problems:
1) many validations are based on the role current user has. Since it depends on current_account (which is session data), I cannot do these kinds of validations in the model. This leads me to some ugly controller code (ugly, in the sense that it really feels out of place). I thought of storing current_account after in the model class variable, but I read that this is not thread safe. Any recommendations?
2) almost every database record is specific to the current account; so, almost every table should have an account_id column and the model should have a belongs_to account association. I want to avoid that. The first (obvious) thing is to have a seperate database for every account, but
a) there are shared tables
b) the boss says this solution is unacceptable (there will be many accounts, with relatively low number of users). Is there a third way?
If anyone runs into similar problem:
The problem described is called multitenancy; understanding default_scope should help. Also, there is the multitenant gem which worked for me nicely.
I'd like to build a simple survey/questionnaire app in Ruby on Rails and wanted to make sure I have the "general" structure correct. The application should allow an administrator to create a new survey and populate it with questions. The answers should pre-populate from a list in the database (e.g. none, a little, somewhat, often, frequently, etc.). Users should then be able to login, select a survey, and complete the questions/answers with their results being stored in a DB.
I've worked out the following scaffolded structure which I will later refactor:
-User
-Survey (has_many Questions)
--Question (belongs_to Survey, has_many Answers)
--Answer_Option (belongs_to Survey)
---Answer (belongs_to Question)
Is that general format correct? I feel like I'm missing something -- perhaps a join table to generate the results? Any thoughts from someone smarter than me? Thanks :)
One thing to consider is, if you really want to re-enter the Answer_Options for every survey. I'd go with a general Answer_Option (or Question_Type) that can be re-used, maybe adding the possibility to create user-generated answer options on the fly.
Ok the scenario is simple(?). I have say Articles, Reviews and Comments, three different models that a user can update. I was wondering what is the best design to follow if I want the updated records (from the user) to become available only to an administrator (and not in a public view) but at the same time the old ones remain as is until the admin reviews them.
First thought was that would be best to have self-referential joins, making a new record on the update action of the user and referencing the old one so that the admin when finishing the review the old record, the latter gets deleted and the reviewed one gets published. I seriously think that if there are many updates from users, then the table holding the data will grow BIG in a very short time. Do you have any other suggestion?
Thank a lot for the help :)
P.S. I am using Ruby on Rails framework, if that makes any different at all..
This kinda reminds me of Wordpress draft system and to be sincere, i think it's probably one of the few ways to do it. That is, have a column with post_type like [draft,published etc..]. Alternatively, you could have a drafts model alone and a published model that are polymorphic of the Article model. I think that you are right in your concerns about a table getting too big. Thus, i think that you would better choose a strategy of removing old drafts or archiving them in another table, so that they just occupy space and not mess with your search time for them (also, remember to use indexes for better performance).
Maybe act-as-state-machine can help as well ( http://www.practicalecommerce.com/blogs/post/122-Rails-Acts-As-State-Machine-Plugin )
One thing to keep in mind is that unless you're trying to create a detailed revision history, there are really only two versions of a given article, view or comment that you need to keep around: The current approved public version of the item and the current edited version of the item. So you can probably just story two copies, and copy the draft version into published and delete the draft when it's approved, or update it if the user makes additional changes before it's approved.