Rails: Adding new column to certain entries of database - ruby-on-rails

I'm trying to make an online marketplace Rails App and I wanted to add a new column to my database conditional on another column.
I have a rails model "listings", which contains fields: "name, price, description, category." There are several categories: e.g., "Apartments, Books, Electronics,..." I want to add "Lat" and "Lon" geolocation columns only for Apartment listings. Would this be possible? How would I go about it?
I'm new to Ruby, so I apologize if this is a really easy question.
Thanks!

#Saraf answer nails it pretty much. Well, this is the case that you consider you have a SQL database. If you want to use a NoSQL database, such as MongoDB, you can store whatever you want inside collections (think about it as storing JSON objects).
Edit: clarification
You use SQL DB and you need to think about your relational schema and how you will handle different data (inheritance, for instance).
You use NoSQL DB and you can store "JSON objects" freely in your collections.

Since a model is a table, all the records will have the same attributes.
You can let them nil for other categories than apartments (and keep only one model), or you can create an herited model Apartments from Listings (http://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html).

Related

Database structure for big collection of fields in rails app

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.

Pseudo Table entries

I'm a learning developer building a Product & Inventory tracking platform for the company I work at and my Rails application has a Products table. Within the Products table are a bunch of basic entries, such as SKU, Description, UPC, Manufacturer, etc.
What I want to do is have an option within the Create page to insert custom parameters into something like a text_area to create Product specific entries, for example if I have only a small set of products that would benefit from a Voltage column and don't want to flood my migration with a bunch of lesser used options. What I'm picturing:
'Voltage|120 Volts'
'Housing Material|Steel'
'Duct Size|4"'
and then these could be their own rows in the Product's Show page.
Is anybody aware of a Gem or template that already accomplishes this, or would I need to dive in the deep end myself? I fear something like this is out of my skillset currently.
You can have one hstore column in the migration which will allow you to store multiple dynamic values in the single column as a hash.
You can read more about hstore from here.
I used hstore to store dynamic variants of product in the table.

better approach to load referential data

I have entities related to cities in my Neo4j graph. I've created a form in which a user can create an entity, let's say a shop. In this form, I would like the user to choose the city of the shop from a combo box. I'm wondering what is the best approach : get all the cities from the graph with a cypher query or have all the cities (and other referential data) in another database (relational or nosql or whatever), and then populate my comboboxes ? Or is there a better approach ?
Thanks for your time,
Didier
I've just heard of polyglot persistence and read some articles. Should it be, in my case, the best approach to store cities and shops in a document database and then use my graph database to add relationships with customers, shops and cities?

Ruby on Rails: Saving multiple values in a single database cell

How do I save multiple values in a single cell record in Ruby on Rails applications?
If I have a table named Exp with columns named: Education, Experience, and Skill, what is the best practice if I want users to store multiple values such as: education institutions or skills in a single row?
I'd like to have users use multiple text fields, but should go into same cell record.
For instance if user has multiple skills, those skills should be in one cell? Would this be best or would it be better if I created a new table for just skills?
Please advise,
Thanks
I would not recommend storing multiple values in the same database column. It would make querying very difficult. For example, if you wanted to look for all the users with a particular skill set, the query would clumsy both on readability and performance.
However, there are still certain cases where it makes sense.
When you want to allow for variable list of data points
You are not going to query the data based on one of the values in the list
ActiveRecord has built-in support for this. You can store Hash or Array in a database column.
Just mark the columns as Text
rails g model Exp experience:text education:text skill:text
Next, serialize the columns in your Model code
class Exp < ActiveRecord::Base
serialize :experience, :education, :skill
# other model code
end
Now, you can just save the Hash or Array in the database field!
Exp.new(:skill => ['Cooking', 'Singing', 'Dancing'])
You can do it using a serialized list in a single column (comma-separated), but a really bad idea, read these answers for reasoning:
Is storing a delimited list in a database column really that bad?
How to store a list in a column of a database table
I suggest changing your schema to have a one to many relationship between users and skills.
Rails 4 and PostgreSQL comes with hstore support out of the box, more info here In rails 3 you can use gem to enable it.
It depends on what kind of functionality you want. If you want to bind the Exp model attributes with a form (for new and update operations) and put some validations on them, it is always better to keep it in a separate table. On the other hand, if these are just attributes, which you just need in database keep them in a single column. There is way by which you can keep the serialized object like arrays and hashes in database columns. Make them a array/hash as per your need and save it like this.
http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html#method-i-serialize
Serialized attributes, automatically deserializes when they are pulled out of tables and serialized automatically when saved.

rails create table in db dynamically

Normally to create/alter a table in database I use migrations (manually run rake db:migrate) and then in my code I use ActiveRecord. This is very cool as I don't have to worry about representation of the data in db and about a specific kind of db (sqlserver, pg or other).
But now a customer wants to be able to create "things" on-fly himself like, say, he starts selling computers, so he wants to an interface where he can dynamically create an object "computer" with properties like "Name, RAM, HD, ...". It seems to be quite natural to create a separate table in db with all these fields. But how can I do that in RoR and keep all these nice things about ActiveRecord?
Please suggest.
The usual way is to do exactly the opposite:
Have a table for object types
Have a table for field names for each object type
Have a very big table with all the custom attributes for each object of any type
This is called EAV (Entity-attribute-value model, see http://en.wikipedia.org/wiki/Entity-attribute-value_model). And it scales pretty bad.
Alternatively, you can use a store text column instead of the big EAV table (see http://api.rubyonrails.org/classes/ActiveRecord/Store.html) so you don't have to make those difficult attribute retrievals, typical of EAV. You still need to store somewhere the "object types" definitions, so the expected fields etc are available when building forms and tables.
The problem with this approach is that you are not able to query (where/join/select) on those attributes because they are not columns. There are a number of solutions to that:
Don't do filtering on those attributes (meh...)
Have an external search server that's able to do faceted search
(as #Amar correctly says) Use a document database
Use postgreSQL and use hstore instead of a simple serialized column.
NoSQL database(Document Database Mongodb,CouchDB) can be best fit for this or use redis. As per my thoughts you can use Vertical Table concept Try to run Rails 2.x Demo of application for MySQL.
You can try with Mongodb, check if this is needed.

Resources