I'm starting building my first rails app and i already have user model with STI (admin, employee, public and representative all inherits from user model).
but now i want to add specific columns (adress, state, phone) for representative subclass but i cannot apply migration directly for subclass model.
the first solution is to add these columns tu user model but i don't know how th restrict acess to only representant subclass
the second solution is to create a separate contact table and and then use polymorphic association (i want to associate with other model) and add the attributes
my question is what is the best solution for this case? and if there is better solution?
Thanks
Hope you Doing well
I think second option is better then first.
Reason:
1) If this all filed are optional then it will create record with null value but in second case if all filed are optional then record will not be created,there is no need to any entry for that.
2) In future there is requirement of add or use this filed into other model then you can do by easily with polymorphic association .
It sounds like you are abusing the idea of an STI in this case. The general rule, is that you might have different associations for different child models and different behaviour BUT you ALWAYS have all the table columns used by all child models.
The whole Idea for why you would want to use STI is that all models contain the same structure of data, but maybe have different behaviours. In your case, I would suggest using associations (as you suggested yourself) and then add the has_one/has_many in the child model, which would limit the associations scope within the inheritance chain.
It is not possible to restrict columns to only some child models without patching ApplicationRecord. But in any case, even if you manage to make a patch to introduce this kind of behaviour, your database table will still have all the columns for all the tables, thus resulting in bigger database tables due to half empty columns, increased size and reduced performance.
I hope that answers your question.
Related
I encountered against the typical case of a model (Address) and multiple models having this data (Company, Person). Let's work with these models as example, but can be generalized with any others.
Making the correct choice is important, as changing the database schema or making deep changes are not easy later.
Initially it will be one-to-one association, then we have these possibilities:
1) Use the classical normalization and put all the address data into each model requiring it. Then create an address subform for render partial into each one, and put the code behavior into a Module to be called from each model controller using it.
This could looks fine, but it has the problem that is hard to make changes, as any change in the Address data needs to be done on each model using it. Also hard to change it to a one-to-many association, if required.
2) Rails polymorphic feature. Address is a model itself, and belongs_to :addressable, polymorphic: true, then Company and Person have has_one/has_many :address/:addresses, as :addressable. Then add the polymorphic FK to Address table and it's done.
I like this solution, it is clear and with only 2 extra columns we have done it. The only contra I can think about is we rely in a framework feature, so if someday we migrate to another one, it should feature polymorphic too. Well this is not really true because we can always make the SQL manually searching by addressable_type = "type", but I think is not database design standard.
3) Join tables. One for each parent. So we have JT_Company_Address, JT_Person_Address, and we use the Rails has_one/has_many :through associations using those join tables.
I think using join tables is more database design standard, but add some extra tables.
4) Reverse the relationship, making Address the parent and each of the other a child. So each child would have a FK address_id.
I don't like much this one, as I will handle mainly companies and persons, and then look up their address if required, not the opposite, looking addresses and then loop up what it has in it. We can always use the bidiriectional association using the Rails inverse_of, but at database layer Address would be the parent one anycase.
My favorites at this moment are 2 and 3. I will probably use Rails and not move from it, so the polymorphic looks very easy and clean.
Then, what do you think, which one is the best one? Any advice is welcome.
Thanks.
I've read so many Rails books/tutorials, but when it comes time to actually make the app, I keep tripping over myself, so I'm trying this little exercise to help me get it better.
I have an app with 3 classes (Link, Url, Visit) that have associations defined between them, such as has_one, belongs_to etc. This allows me to call methods like Link.url
If I were to convert this into an app with a single model, is it possible to create the convenience methods (such as Link.url) even though there are no relationships between models, because there is only one model.
This might not be the 'Rails way' but if you answer this question it'll help me get it more.
I guess another way to ask this is, do the Rails associations only exist because the tab
Thanks
Models exist to represent tables in a database. If you have 3 different conceptual objects, then you need 3 different models. Keeping those objects separate and in different tables/models is essential to good programming in any language. The relations are there to help you understand the correlation of each object to the others.
If you think all of data from each of the models can be represented in one table sensibly, then combine them in to one model with a name that encompasses all of the data. If you choose this option, you'll use columns for that one table which represent each of the pieces of data you need. Those column names come free in the model when you create the migration. A table with a column named "url" on a model named "Hit" could be used like this:
Hit.first.url
So this is probably a fairly easy question to answer but here goes anyway.
I want to have this view, say media_objects/ that shows a list of media objects. Easy enough, right? However, I want the list of media objects to be a collection of things that are subtypes of MediaObject, CDMediaObject, DVDMediaObject, for example. Each of these subtypes needs to be represented with a db table for specific set of metadata that is not entirely common across the subtypes.
My first pass at this was to create a model for each of the subtypes, alter the MediaObject to be smart enough to join into those tables on it's conceptual 'all' behavior. This seems straightforward enough but I end up doing a lot of little things that feel not so rails-O-rific so I wanted to ask for advice here.
I don't have any concrete code for this example yet, obviously, but if you have questions I'll gladly edit this question to provide that information...
thanks!
Creating a model for each sub-type is the way to go, but what you're talking about is multiple-table inheritance. Rails assumes single-table inheritance and provides really easy support for setting it up. Add a type column to your media_objects table, and add all the columns for each of the specific types of MediaObject to the table. Then make each of your models a sub-class of MediaObject:
class MediaObject < ActiveRecord::Base
end
class CDMediaObject < MediaObject
end
Rails will handle pulling the records out and instantiating the correct subclass, so that when you MediaObject.find(:all) the results will contain a mixture of instances of the various subclasses of MediaObject.
Note this doesn't meet your requirement:
Each of these subtypes needs to be represented with a db table for specific set of metadata that is not entirely common across the subtypes.
Rails is all about convention-over-configuration, and it will make your life very easy if you write your application to it's strengths rather than expecting Rails to adapt to your requirements. Yes, STI will waste space leaving some columns unpopulated for every record. Should you care? Probably not; database storage is cheap, and extra columns won't affect lookup performance if your important columns have indexes on them.
That said, you can setup something very close to multiple-table inheritance, but you probably shouldn't.
I know this question is pretty old but just putting down my thoughts, if somebody lands up here.
In case the DB is postgres, I would suggest use STI along hstore column for storing attributes not common across different objects. This will avoid wasting space in DB yet the attributes can be accessed for different operations.
I would say, it depends on your data: For example, if the differences between the specific media objects do not have to be searchable, you could use a single db table with a TEXT column, say "additional_attributes". With rails, you could then serialize arbitrary data into that column.
If you can't go with that, you could have a general table "media_objects" which "has one :dataset". Within the dataset, you could then store the specifics between CDMediaObject, DVDMediaObject, etc.
A completely different approach would be to go with MongoDB (instead of MySQL) which is a document store. Each document can have a completely different form. The entire document tree is also searchable.
In some of my forms I have to provide a dropdown where users can select some districts. The thing is, there will always be a fixed number of districts ( 31 in this case ). Should I create a model named District having only a string field,populate it with the data and be done with it?
It's content will not modify over time. Is there another way?
You should take a look at jnunemakers scam-gem. It mimics the AR for you and lets you define the models in your Rails app without a backing database/table.
I use this whenever I want something to do psuedo belongs to/has many relationships, but do not want to back a model with a database as the data does not change often, if ever.
Making a table-backed model is the simplest way. Otherwise you're going to end up implementing half of an AR model anyway, because you'll want to use collection_select at some point.
I guess it depends on how you want to store the districts and whether you want to do any querying etc.
For example, you could just have the list of districts as a constant, then store them as a string in your models (not very elegant), or as you say you could create a model and use active record associations - this would allow you to easily query on districts etc.
I have a model "Task" which will HABTM many "TaskTargets".
When it comes to TaskTargets however, I'm writing the base TaskTarget class which is abstract (as much as can be in Rails). TaskTarget will be subclassed by various different conceptualizations of anything that can be the target of a task. So say, software subsystem, customer site, bathroom, etc...
The design of the classes here is fairly straightforward, but where I'm hitting a snag is in how I will relate it all together and how I will have rails manipulate those relationships.
My first thought is that I will have a TaskTarget table which will contain the basic common fields (name, description...). It will then also have a polymorphic relationship out to a table specific to the type of data the implementing class wraps.
This implies that the data for one instance of a class implementing TaskTarget will be found in two tables.
The second approach is to create a polymorphic HABTM relationship between Task and subclasses of TaskTarget which I thought I could reuse the table name TaskTarget for the join table.
Option #2 I suspect is the most robust, but maybe I'm missing something. Thanks for any help and of course I'm really just asking to make sure I get it done right, once!
I think the two approaches (easily) available to you in Rails are:
1) Single Table Inheritance: You create a single TaskTarget table that has every field that every subclass might want. You then also add a "type" field that stores the class name, and Rails will pretty much do the rest for you. See the ActiveRecord api docs for more info, especially the "Single Table Inheritance" section.
2) Concrete Table Inheritance: There is no table for the base TaskTarget class. Instead, simply create a table for each concrete class in your hierarchy with only the fields needed by that class.
The first option makes it easier to do things like "Show me all the TaskTargets, regardless of subclass," and results in fewer tables. It does make it a little harder to tell exactly what one subclass can do, as opposed to another, and if you have a lot of TaskTargets, I suppose eventually having them all in one table could be a performance concern.
The second option makes for a cleaner schema that is somewhat easier to read, and each class will work pretty much just like any normal ActiveRecord model. However, joining across all TaskTarget tables can be cumbersome, especially as you add more subclasses in the future. Implementing any necessary polymorphic associations may also involve some extra complexity.
Which option is better in your situation will depend on what operations you need to implement, and the characteristics of your data set.