I’m looking for the most elegant way to handle a self referential relationship in my rails model. I have an “answer” which could be used as a basis for another “answer.” There aren’t necessarily versions of each other since a significant amount of information could change from “answer” to the other. I’m looking to maintain a sort of multi level parent child relationship so I can trace back the authors, content, etc.. I’ve looked at a couple of gems, but I’m hesitant to introduce something like that, as it may be overkill. Is there a preferred “rails way” of doing this?
Thanks in advance
It sounds like you're wanting to create a tree structure where each answer has a reference to its "parent" answer. This is a common use-case, and there's a whole slew of gems that help solve this problem.
At it's most basic, you'll need some sort of parent_id column on your answers that references the parent. At that point it's really easy to create methods and scopes that grab the parent, children, siblings, etc.
Since your use-case seems pretty simple, writing your own code to manage the tree is probably fine. However, there is something to be said for using existing code that's been well tested and had the kinks worked out. If nothing else, it can save you time in writing your own unit tests. ActsAsTree is about as basic as they come. It shipped with earlier versions of Rails, so if you find your needs growing for some reason, just about every other gem in this space has an upgrade path you can follow.
Related
Sorry if the question is awkwardly phrased -- still a Mongo/Mongoid/Rails newbie here.
What I'm trying to ask:
In my development, I've been changing around the design of my Models as I go, adding some fields here, removing some fields there (one of the great things about MongoDB/Mongoid is that you can do this very quickly and easily!)
Everything is working, but in browsing through the development database, I've got some "detritus" -- documents with the old fields (and data) that aren't being used. It's no big deal other than to my garbage-collective sensibilities. I could, in theory, drop the DB and start from scratch, but that's messy.
Is there a utility / gem / etc. that will, essentially, look at the current document design and drop any fields in the live DB that don't match up to the data model?
I know this can be done manually, and I know about the mongoid migrations gems that are out there -- those are both good and, ultimately, more thorough solutions (which I'll look at).
For now, though, I'm wondering if there's a simple "quick shot" type of utility to simply sync up the DB and drop any fields that aren't explicitly specified in my models.
Thanks!
I don't know of any tools that do this for you. It's not a common ask because most people see this flexibility as a useful feature.
For your development database, you should probably clear it out and start over.
In production you have a couple choices:
Write your code to be robust against fields being missing and the database documents not matching your mongoid model. In other words, be prepared for the two to get out of sync.
Get in the habit of migrating your data every time you change the model. It's a bit of hassle and not strictly necessary if you follow the first, but if the untidiness bothers you, this is a fine idea. See Managing mongoid migrations for strategies.
Is there a Rails 3 model versioning plugin that supports point-in-time queries (not just recovery) in an SQL database?
To be concrete: I have a table, documents. I want to be able to say, "as of 9/17/2010, which documents contained the text 'foo'?". This requirement seems to rule out all of the single-table versioning solutions like vestal_versions, and none of the other ones seem to have this feature either. All of the plugins I've looked at are documented as black boxes, so perhaps they store enough data internally to do this sort of query but you would never know it from the docs. In terms of Slowly Changing Dimensions, Type 2 is probably the sort of solution I'm looking for, although ultimately I'll use whatever works.
I also need to keep track of which user made changes, although that's probably possible to do outside of the versioning system too.
Is there one that I'm missing? Or am I using the wrong search term? Or do I get to roll my own?
I think you get to roll your own. If you really need to be able to perform queries on the versions, then the versions should probably be their own model, and making a versioning gem bend to fit your needs will be more painful than doing it yourself.
Sorry, and have fun :/
I'm starting out with Ruby on Rails and I know of a few stuff already, but I was wondering if there was a "right" way of going about developing a project. Right now, I would create my models first using [script/generate model MyModel] then modifying them until I feel they are complete enough. Then I'd go for [script/generate scaffold MyModel] so I don't need to do as much coding for the views. Lastly I modify the views and add more models then scaffold some more for other features I might need.
Would there be a better way of doing this? Especially in the context of working with a team in developing a project? Thanks!
I'm sure everyone has their own workflow, but I think a typical one is this:
Specify the "domain" your project. This probably sounds silly, but before you get started you should really think about what exactly your website is going to offer. It doesn't need to be specific down to the last detail, but should have an idea so that you can perform the next step...
Design your database schema. I usually just plan this out on paper. There's a real art to creating a normalized database. Think of everything that needs to be "permanent" in your app, because it will have to be in the database and accounted for, with as little duplication as possible.
After this I usually do as you say: create my models (and migration scripts along the way). The main thing you want to get down in your models first is the associations with other models.
The next part depends on how comfortable you are as a developer in Rails. A lot of people enjoy the test driven development approach (TDD), and will write Unit tests (Rails provides excellent facilities for writing these, and rake tasks to run them). However, since you're just learning, you may want to write your tests after you implement your model business logic.
The road after this is pretty much up to you. You can work on your views/controllers/models as you need to. That's one of the beauties of Rails and agile development, you don't need a lot of boiler plate code to get started.
I'm probably weird in this, but I usually design my front page and get some basic CSS going, as I find I am more productive if my results are semi-nice looking.
I would probably avoid generating scaffolds though...I think you'll learn a lot more about the framework and spend less time removing unwanted code if you generate the individual pieces themselves.
In the context of developing with a team, things will probably be different. If you have a lot of complex business logic, some people may spend most of their time writing model code, while people more on the design side will be implementing view code. But you will have to meet in the middle of course, which will get easier as your project grows and becomes more modular. Just remember to use a version control system! Subversion if you want something easy to use and learn, Git if you're up for a challenge.
Or, put differently, is there any reason not to use it on all of my models?
Some background: is_paranoid is a gem that makes calls to destroy set a deleted_at timestamp rather than deleting the row (and calls to find exclude rows with non-null deleted_ats).
I've found this feature so useful that I'm starting to include it in every model -- hard deleting records is just too scary. Is there any reason this is a bad thing? Should this feature be turned on by default in Rails?
Ruby is not for cowards who are scared of their own code!
In most cases you really want to delete the record completely. Consider a table that contains relationships between two other models. This is an obvious case when you would not like to use deleted_at.
Another thing is that your approach to database design is kinda rubyish. You will suffer of necessity to handle all this deleted_At stuff, when you have to write more complex queries to your tables than mere finds. And you surely will, when your application's DB takes lots of space so you'll have to replace nice and shiny ruby code with hacky SQL queries. You may want then to discard this column, but--oops--you have already utilized deleted_at logic somewhere and you'll have to rewrite larger pieces of your app. Gotcha.
And at the last place, actually it seems natural when things disappear upon deletion. And the whole point of the modelling is that the models try to express in machine-readable terms what's going on there. By default you delete record and it passes forever. And only reason deleted_at may be natural is when a record is to be later restored or should prevent similar record to be confused with the original one (table for Users is most likely the place you want to use it). But in most models it's just paranoia.
What I'm trying to say is that the plausibility to restore deleted records should be an explicitly expressed intent, because it's not what people normally expect and because there are cases where implicit use of it is error prone and not just adds a small overhead (unlike maintaining a created_at column).
Of course, there is a number of cases where you would like to revert deletion of records (especially when accidental deletion of valuable data leads to an unnecessary expenditure). But to utilize it you'll have to modify your application, add forms an so on, so it won't be a problem to add just another line to your model class. And there certainly are other ways you may implement storing deleted data.
So IMHO that's an unnecessary feature for every model and should be only turned on when needed and when this way to add safety to models is applicable to a particular model. And that means not by default.
(This past was influenced by railsninja's valuable remarks).
#Pavel Shved
I'm sorry but what? Ruby is not for cowards scared of code? This could be one of the most ridiculous things I have ever heard. Sure in a join table you want to delete records, but what about the join model of a has many through, maybe not.
In Business applications it often makes good sense to not hard delete things, Users make mistakes, A LOT.
A lot of your response, Pavel, is kind of dribble. There is no shame in using SQL where you need to, and how does using deleted_at cause this massive refactor, I'm at a loss about that.
#Horace I don't think is_paranoid should be in core, not everyone needs it. It's a fantastic gem though, I use it in my work apps and it works great. I am also fairly certain it hasn't forced me to resort to sql when I wouldn't need to, and I can't see a big refactor in my future due to it's presence. Use it when you need it, but it should be a gem.
I am stuck in a weird Design problem,
I am working on a two type of profiles Models,
User profile (belongs to User)
others that are maintain in-site as "bots" (doesn't belong to anybody)
The typical OO behaviour of these two types of Profiles is same but only the important attributes/properties are common ( the very important ones 5-6 in number), others properties like "interests etc"(almost 10-15 properties) are not there for bot profiles
The coder who worked on this earlier created separate models/Controllers for bot profiles / User profiles which creates a lot of redundancy everywhere and also as expected hard to maintain, write tests etc.I wanted to DRY this up, atleast to solve some/all of these redundancy problems.
Somebody suggested Single Table Inheritance as a solution
Somebody suggested Use Polymorphic Associations instead.
what is the better approach. When do we actually use STI?
My own thought was STI is used best when attributes are same for Models and they differ in behaviour.
Thoughts about what can I do?
Characterising STI as mostly useful when attributes are the same but behaviour differs is "about right", but possibly a little limiting. I like to use STI when there is, as the name suggests, a clear OO-style inheritance relationship, rather than the database-style relationship between objects of different types.
If there is common code between bots and users, I'd say STI sounds like a winner. If there's just some common attributes, it's probably less applicable but still worth having a go at.
I'm a pretty experimental person, so my recommendation is to give it a go. Branch your code and refactor the models into an STI relationship. See if it really does dry things up, or just swaps one set of headaches for some other problem.
One thing I think you won't see much benefit from is drying up your controllers. In my experience, STI models don't often translate into similarly related controllers. But that would be something else to experiment with. Sometimes there's a win, sometimes there isn't.
I've written an article on this very topic, including some tips for working with STI:
Single Table Inheritance in Rails
In short: there needs to be a clear OO-style inheritance relationship among objects (as eloquently stated by womble), not just some shared data. If there isn't a natural and obvious class hierarchy, a STI design may become difficult to maintain as your application evolves.
Secondly, you should consider if it's important to have all the data in one table. With polymorphic associations, your database queries will become more complex, and probably slower. If you're planning on listing all the objects together on the site (eg, in a table) then STI may be the way to go.
Thirdly, make sure your child classes don't have too many unique attributes. With all the data in one table, you don't want a lot of non-global columns. Not only do these take up space (not a major concern), but they make the data structure confusing. If you do have "special" columns you should explain them explicitly in your code.
Lastly, if you do use STI, I strongly recommend using a single controller for all of your child models. The main function of a controller is to provide access to objects, and if the objects need to be accessed in very different ways, then STI may not have been the correct design choice to begin with.
Check out my article (link above) for some more useful tips.
I would probably use either STI or no special features at all. You might be able to call everything a Profile and you'd know if it was a "bot" if its user was nil. You could also store a "type" field without using STI.
Certain things would affect my decision to use STI:
Whether there is bot-specific logic
How many bots there are versus users profiles (small number of bots means STI is OK - lots of bots and I might store them somewhere else)
The reason to avoid STI is sometimes it can get in your way. For instance it can be fairly annoying to change an object from one type to another (a Bot to a Profile in this case). Sometimes a simple "type" field is better.
Its worth noting that you'll probably want a common base class if you use STI. So you may want Profile, BotProfile, and UserProfile. The names are up to you. :)
One gotcha of Rails STI - most plugins (and so forth) don't support it fully. You will find yourself patching many of the common ones.