Let's say we have predefined form that has 3 fields : FirstName, LastName, Email and this form is mapped to table users with : ID, FirstName, LastName, Email
Let's say a user want to add a new field for instance BirthDate. the user will pick the type of the field, here DateTime texbox and the text beside the field like Birth Date but how to add this column in the users Table?
Any help would be highly appreciated
Joseph
There is no realistic way for a user to dynamically add a field to the actual database table, not so that you have a new field like 'DateOfBirth' or 'ShoeSize'.
You can however, capture dynamic data from users by changing the core design of your application. Instead of storing your data in a fixed 'horizontal' table what you need to do is abstract your database and store each value as a seperate record - kind of like a 'vertical' table.
So you would have a table like
Field, Data, Type
---------------------------
"FirstName", "John", string
"LastName", "Smith", string
"DateOfBirth", "01/01/1950", datetime
"ShoeSize", "4", int
Its a issue of architecture not of technology.
There is a really good article here that discusses it in much greater depth.
It is important to understand that this does make your application quite a bit more abstract, less type safe and as such far more complex. I would not suggest trying to do this unless you fully understand the extra work involved.
Related
I'm busy with a rails 4/postgres project that is structured in such a way that requires dozens of fields for a specific object, this being company. Each company would include fields for eg name, location, header_bg, logo, contact name, contact cell etc so the fields very well could grow in the future. What is the best way to structure this DB.
The way I see it I have 3 options:
1) company table with all these fields in the same table
pros: simple, data all in one place and easy to query
cons: table could get very messy and requires manually editing table structure every time a new field is required
~~~~~~
2) company table with an additional company_options table a foreign key company_id. This table will also hold multiple fields
pros and cons are same as above except this will be more neater structure. Crucial data such as company name will go in company table, other data like location, theme, header_bg etc would go in company_options
~~~~~~
3) company table and a company_meta table. This will follow the Wordpress structure of the post_meta table. So it would have the fields: company_id, meta_key, meta_value. each field would go in its own row
pros: flexible, able to dynamically add options/fields without editing table structure
cons: not a simplistic approach with same data in same columns. would need to custom build this functionality for inserting, updating, validation displaying of data. Unless Rails has such a gem which I can't find?
~~~~~~
Any suggestions or additional options would be appreciated. Are there any rules of thumb for determining the kind of structure needed? I started out with the 1st option out of a matter of simplicity but then started to build the 3rd and the amount of code just didn't seem right for what seems like such a common need.
Thanks!
Plan your database schema for the future:
Will a company be able to have several phones?
For repeating information, use a new table:
rails g model phone number:string type:string
rails g migration add_company_id_to_phones company:references
This way you can add several phones and navigate your database to get each phone.
Will your field only have one of a kind?
For example, you might only need one name field for each company. If this is the case, add it directly to the companies table:
rails g migration add_fields_to_companies name:string
Is your data completely optional? Is it unstructured?
Add a JSONB field to your table, assuming you are using Postgresql:
rails g migration add_details_to_companies details:jsonb
With JSONB data type you can use unstructured data like this:
Company.create({
name: "AwesomeCompanyCorp",
details: {
"main phone": "000-0000-0000",
"secondary phone": "000-0000-0000",
"support email": "support email",
"location": "Main Avenue 165",
"latitude": "22.330213123",
"longitude": "60.000012312"
}
})
With JSONB you are able to have unstructured data, but be able to query the field like this:
Company.where("details->>'main phone' = ?", "000-0000-0000")
With this on mind, choose the best approach that fits your case.
I'm trying to create my models for storing users and different contact information fields.
The idea is to allow a user to have 0 or more registered contact info (eg. 2 telephone numbers, 1 Skype account, personal and work email addresses), so I understand I cannot add said fields to the users model, nor is a good idea in my case to model phone, skype, email, etc as individual tables. This makes me consider using a generic contact info table, with a column for the type of contact info (eg. phone, im, email) and the contact info itself.
My doubt, due to my lack of experience on this matter, is this: Should I use an integer for the contact info type and handle it on the controller/view side (either through an array or case-like fashion)? Or would it be better to just use a string (gaining clarity in the db data, but with the added penalty in storage, validation and normalization times of said strings)? Is there any best practice regarding this?
I tried searching in multiple ways, but after reading or skimming through 20+ articles I couldn't find anything even close to what I'm trying to ask.
Thank you in advance!
there's rails' built in enum, which you can use in such a case. it maps integer to string values. e.g.
class Contact < Activerecord::Base
enum contact_type: {email: 0, phone: 1}
#enum contact_type: [:email, :phone]
end
i would not use it without explicitly stating the name to integer mapping. if somebody changed the order of values in the array at some later point, the meaning of the contact_type would suddenly change all over your application, because the already stored integers in the database wouldn't automagically change as well.
I'll try to be short and clear with this question.
We have an asp.net mvc app that uses entity framework 4.
Our business model is relatively straightforward:
We have an object (which corresponds to a table) called Photo(s).
That photos table has a handful of columns that match up to properties on the object.
Description,Title,Date etc.
It also has a number columns that reference foreign keys for other tables:
AuthorId,LicenseId etc...
The author and license tables are complex in their own right, with multiple fields (Title,Summary,Date etc.)
I have multiple clients using this application to view their photos. I would like each client to dictate what fields they see when viewing the photos, as well as what fields they see when editing those fields.
My thought is to have tables setup saying client-a should see Field1,Field2 and Field3 when viewing their photos - and client-b should see Field1,Field4 and Field5. But some of these fields are not simply columns in the main photos table, they may be fields in a child table. so Field1 might be: Table.Photos.Title -> which corresponds to an object as: Objects.Photo.title...
but Field3 might be: Table.Licenses.LicenseSummary -> which corresponds to an object as: Objects.Photo.License.LicenseSummary
I'm trying to figure out the methodology that we would use to have a very data driven environment so in the DB I can say, display this object/property (for viewing or editing) and then it would know how to map to whatever table it needs to pull that information. also, during editing... give it some way to pull a list of available values if it is that type of property, and not just a text field.
I'm looking for an example of what this might involve, our model is actually more complex than this, but this is just an idea of what we are trying to accomplish. I don't know if what I'm trying to do is normal, perhaps it involves reflection? This is a new area for me.
If the clients are defining their own custom fields, I would simply give them a Key/Value pairs table.
PhotoID FK
Key string
Value string
Display bool
Note that this essentially amounts to EAV, which comes with its own set of difficulties.
If it's just about permissions on existing fields, you need to capture that information:
PhotoID FK
ClientID FK
FieldName string
Display Bool
You can use this information to inhibit the display of fields in the View. The easiest way to do that would be to use a loop in the View itself, writing the field to the output only if Display is set to true.
I'm looking for some feedback on my current plan of implementing custom fields in rails. I'm new to rails and app development in general and would appreciate any comments from more experienced individuals.
Background
The app: Keep track of food and beverage tastings.
What I'm trying to model:
User creates a new sample type.
They call it: "Wine"
They decide for their company, they'd like to keep track of the following attributes: Origin, Grape Type, Company, Elevation,Temperature Kept, and more.
The only assumptions about a sample type that my database has made is that it has a Name. (eg. coffee, wine, etc.) the rest are all custom fields specified by the user.
Now that a sample type has been created.
The user begins to create samples of sample type wine.
They choose create sample, choose of type Wine.
The fields they must fill in are the ones they specified earlier.
In Origin they put: France, in Grape type: they put chardonnay, etc..
--
My plan of approach is as follows:
When a user creates the sample type, store the custom fields as an array or in some string format and keep it under a column called data.
SampleType
name
wine
data
[origin, grape_type, company, ...]
When a user wants to create a sample of type Wine:
I look up the sample type wine, for each key in the data column, it creates form fields.
When the user submits the data, I create a hash of all the custom fields names and their corresponding data. I serialize it and store it in a hash in a data column like such:
Sample
type
wine
data
{ origin: "France", grape_type: "Pinot Grigio, ... }
My plan at the moment is to use PostgreSQL's hstore to implement the hashing in the data column.
My questions are:
Is this a valid solution for what I'm trying to do?
Will I run into trouble when users change what custom fields they want?
Any other concerns I should take into account?
Is mongodb and other such db's a better choice for this type of model?
I've been using the following links as a reference:
http://schneems.com/post/19298469372/you-got-nosql-in-my-postgres-using-hstore-in-rails
http://blog.artlogic.com/2012/09/13/custom-fields-in-rails/
As well as many other stack overflow posts, however none seem to be using it in the way I mention above.
Any comments are appreciated.
jtgi, having done something like this more times than I want to remember, my first response was, "run away!" In my experience, the whole user-defined field thing is an ugly, hacky, nightmare. Soon, someone will ask, "can I search on grape?" or "I want to be able to input multiple values for grape." And on and on, and you will hate yourself for ever stepping down this path. :-)
That said, I think your approach is pretty decent. To answer your questions directly:
Yes, this is a valid approach.
Yes, you will run into trouble when users change the custom fields they want. (see above)
See some notes below.
Might be. I went there even before I read your 4th question. With your field => value hash, you're kind of implementing a noSQL solution anyhow, but it'll be non-trivial to implement lookups, searches, etc.
Some thoughts:
I think I would marshal the data into a db column, rather than using a db function. That way, it's pure Ruby and not dependent on the db type. See http://www.ruby-doc.org/core-1.9.3/Marshal.html. I'm doing this to cache some data in an app right now, and it's pretty slick. You may need to marshal(l) the data anyhow, if you want to wind up storing Ruby objects more complex than strings.
You'll probably get there soon anyhow, so I would plan on storing some "metadata" about the attributes while you're at it. E.g., "grape" is a String, max length 20, "rating" is an integer between 0 and 100. That way you can make your form a little prettier and do some rudimentary validation.
When you come to hate this feature, you can remember me. :-)
As a paranoid entry-level developer I was wondering if it is possible for a user to use some kind of query to insert data into a database through a form with a select field.
More specifically lets say in my db I have a Gender column (data type text) and in my form I am using the select tag and passing in 2 options Male and Female. Although in the html the user only has 2 options to select from but the db doesn't know that. The gender column will pretty much accept anything. I just wanted to know if a nuisance user can disregard the select options and somehow insert a silly answer into the Gender column? If so, how can I protect from that.
The thing you are talking about here is the validations need to be done before entering data to the database. Invalid data can come from anywhere ( directly from controller or from GUI) and its the responsibility of the model to validate the data before it commits to the database.
Go through these links.
http://api.rubyonrails.org/classes/ActiveRecord/Validations.html
http://guides.rubyonrails.org/active_record_validations_callbacks.html