Flexible requests to database in Rails - mysql

I have the following problem in Rails which I am not sure how to solve. I build a test web application,a bulletin board with ads about real estate, like simple version of http://www.trulia.com/ and obviously users can add advertisements to the site which they can then find in their "office", and thats where the problem appears. I have 8 types of advertisements, like flats, offices, garages and etc, and so I need to be able to retrieve ads that belong to some particular user and I dont want to make sql requests to all 8 tables to show this user's advertisements, if user has , for example, just 1 ad about selling a flat.
So I need something instead of
#garages = Garage.where("user_id = #{current_user.id}")
#flats = Flat.where("user_id = #{current_user.id}")
#offices = Office.where("user_id = #{current_user.id}")
..... and so on
I have User model so all ads belong to some user and I am thinking of creating a polymorphic table which would belong to user and contained information about all ads the user invited
it would be named, for example,"Advertisement",it would have 3 columns, user_id, advertisable_id, advertiseble_type, and it would be very easy to get all rows that belong to some particular user, but I have no idea if its possible to make Rails get ads only from those tables that are in "advertisable_type" and with those ids from "advertisable_id", I hope you understand what I mean. So, any advices for a newbie? :)

If Your existing models Garage, Flat, Office are really advertisements, share a lot of same logic and columns, then obviously You need a data redesign.
If it's 99% the same thing why not just have Advertisement table and a column advertisement_type ? If You want a classifier for Advertisement type, simply use a separate table/model AdvertisementTypes and reference those by advertisement_type_id in Your advertisements table.
If You feel like there are/will be a lot of things in common, but there will be also a lots of distinct logic, it might be an ideal case for STI (Single table inheritance).
When using a STI You have different model classes which inherit from the same parent class and are stored in the same table.
class Advertisement < ActiveRecord::Base
def ad_text
"We are selling property: #{read_attribute(:ad_text)}"
end
end
class GarageAdvertisement < Advertisement
def ad_text
"We are selling garage: #{read_attribute(:ad_text)}"
end
end

Related

Tips to structure this database

I want to make a database for a plugin I am making for Minecraft.
I've been trying to figure the best way to structure this but I have failed many times, could anyone give me some tips?
The idea is:
There will be a active_shops table => this represents individual shops, saving the information about each shop.
I need a table called player_shops => this table will have an AI ID and store things like, members and the name of the shop.
Here is where the problem is,
when adding the active shop I would need to include the ID from the player_shops as a secondary key.
But a player without a player shop can also make an active shop so instead of that ID I would need to store the player's UUID, which is a string of characters.
Please help to figure this out.
The information provided is scarce so it might not apply to your context, but...
Your original DB structure looks like:
Besides the problem you stated, you will not be able to normalize this structure.
I propose something like this:
The relation Shop - Player is to designate the "owner" of the shop.
The Member link table is to link the players members of the shop.
Since I do not know the difference between an active shop, and a player shop, I isolated that characteristic into a ShopType table, allowing you to choose one or the other.
Doing it like this allows a player to have any type of shop he wants. A shop is a shop, from your description I do not understand why you need to have 2 tables for your 2 shop types. A shop is a shop, being Active or Player type.
This is not a complete, add the different missing fields for each table, this illustrates only the structure.
The other possibility is if you need a shop to be 1) player 2) active 3) both. Then the shop table should be modified like so:
the type concept is removed, and boolean attributes define the type of the shop.
This is obviously a work in progress, hopefully it helps enough to get you started thinking of your solution another way.

Database schema for chat: private and group

I'm trying to design the database schema with the ability to both private chat and group chat. Here's what I've got so far:
So - the theory is that even if the user is just in a one on one private chat, they are still assigned a 'roomID', and each message they send is to that room.
To find out all the rooms they are involved in, I can SELECT a list from the table participants to find out.
This is okay, However it feels to me that the room table is slightly redundant, in that I don't really need a room name, and I could leave it out and simply use the participants table and SELECT DISTINCT roomID FROM particpants to find out the individual rooms.
Can anyone explain to me a better structure or why I should keep the room table at all?
Your schema looks perfectly fine, you might see the others (including myself today) came with more or less the same structure before (Storing messages of different chats in a single database table, Database schema for one-to-one and group chat, Creating a threaded private messaging system like facebook and gmail). I'd really like to note that your visual representation is the best of all, it's so easy to understand and follow :)
In general, I think having "room" ("chat", "conversation") makes sense even if you have no specific properties at the moment (as it might be name, posting_allowed, type (i.e. if you reuse the similar structure not only for private messages and chats but i.e. to public posts with comments) and so on. Single table with the single index ID should be super fast and have close to zero overhead, however it will allow extension quite easily without need to modify all existing code (i.e. one day you decide to add a name to chats).
Keeping the roomID logic "hidden" inside participants table will not be transparent and neither efficient (i.e. when you need to find next ID of the chat), I wouldn't recommend that.
I think you may need to refine your domain model a little - without that, it's hard to say whether your schema is "right".
Taking Slack as a model (note - I haven't done a huge amount of research on this, so the details may be wrong), you might say that your system has "chats".
A chat can be public - i.e. listed for all users to see and join - or private - i.e. not listed for all users, and only available by invitation.
Public chats must have a "name" attribute. Private chats may or may not have a name attribute.
A chat can have 2..n participants.
All 1-1 chats start as private by default.
It is possible to change a private chat to a public chat.
In that case, you have an inheritance/specialisation relationship - "private" and "public" are subtypes of "chat".
The relational model is notoriously bad at dealing with inheritance; there are lots of related questions on SO.
I know this is a little late in the game but I've made a few of these and I always have an active type bool col in the message table. Just incase someone says something you can hide it but still keep a record of it. As well as user_auth in the users table. Sometimes I put in the room table auth_required -> user.user_auth incase you want leveled conversations like in many discords and always a datetime in the message col. Those are the standards at min because you will regret later if you don't have them..
I would do it more like this for a simple chat system with groups and privat chat (two member).
A other posibility is to create a table only for group message and one for privat chat. (to avoid the n:m between group and message table or you use the n:m like a feature and not as a posible bug / logic error). If you want a more complex chat system look at Neville Kuyt post.
I hope I was able to help you.

Proper way to model user groups

So I have this application that I'm drawing up and I start to think about my users. Well, My initial thought was to create a table for each group type. I've been thinking this over though and I'm not sure that this is the best way.
Example:
// Users
Users [id, name, email, age, etc]
// User Groups
Player [id, years playing, etc]
Ref [id, certified, etc]
Manufacturer Rep [id, years employed, etc]
So everyone would be making an account, but each user would have a different group. They can also be in multiple different groups. Each group has it's own list of different columns. So what is the best way to do this? Lets say I have 5 groups. Do I need 8 tables + a relational table connecting each one to the user table?
I just want to be sure that this is the best way to organize it before I build it.
Edit:
A player would have columns regarding the gear that they use to play, the teams they've played with, events they've gone to.
A ref would have info regarding the certifications they have and the events they've reffed.
Manufacturer reps would have info regarding their position within the company they rep.
A parent would have information regarding how long they've been involved with the sport, perhaps relations with the users they are parent of.
Just as an example.
Edit 2:
**Player Table
id
user id
started date
stopped date
rank
**Ref Table
id
user id
started date
stopped date
is certified
certified by
verified
**Photographer / Videographer / News Reporter Table
id
user id
started date
stopped date
worked under name
website / channel link
about
verified
**Tournament / Big Game Rep Table
id
user id
started date
stopped date
position
tourney id
verified
**Store / Field / Manufacturer Rep Table
id
user id
started date
stopped date
position
store / field / man. id
verified
This is what I planned out so far. I'm still new to this so I could be doing it completely wrong. And it's only five groups. It was more until I condensed it some.
Although I find it weird having so many entities which are different from each other, but I will ignore this and get to the question.
It depends on the group criteria you need, in the case you described where each group has its own columns and information I guess your design is a good one, especially if you need the information in a readable form in the database. If you need all groups in a single table you will have to save the group relevant information in a kind of object, either a blob, XML string or any other form, but then you will lose the ability to filter on these criteria using the database.
In a relational Database I would do it using the design you described.
The design of your tables greatly depends on the requirements of your software.
E.g. your description of users led me in a wrong direction, I was at first thinking about a "normal" user of a software. Basically name, login-information and stuff like that. This I would never split over different tables as it really makes tasks like login, session handling, ... really complicated.
Another point which surprised me, was that you want to store the equipment in columns of those user's tables. Usually the relationship between a person and his equipment is not 1 to 1 and in most cases the amount of different equipment varies. Thus you usually have a relationship between users and their equipment (1:n). Thus you would design an equipment table and there refer to the owner's user id.
But after you have an idea of which data you have in your application and which relationships exist between your data, the design of the tables and so on is rather straitforward.
The good news is, that your data model and database design will develop over time. Try to start with a basic model, covering the majority of your use cases. Then slowly add more use cases / aspects.
As long as you are in the stage of planning and early implementation phasis, it is rather easy to change your database design.

Integrated CMS Based Off Model for Rails

I have a site nearing structural completion. Essentially, it's made up of Users and Photos. However, Photos have a LOT of HABTM relationships, most of which are different kinds of tags, and others being categories, collections, etc...
My client would like to be able to have a conditional CMS based off the content being viewed for different promotional purposes or whatnot. For example, if a user is browsing the Category "Leprechauns", he may want to show html content about St. Patrick's Day or something. He may even want to easily include the browing user's name, if available. In which case, it'd be nice to have some sort of templating system. The part that makes this tricky is that these are small blocks of HTML for something like a 300x300 space in the sidebar and is NOT the primary content.
I've looked into refinery, but it seems to be too much of a complete solution. I've also thought about building in from scratch, but I don't know where to begin with treating dynamically generated pages (such as a new Category) as a recognizable object in Rails. I'd like to keep it more global than a slew of HABTM relationships, but it's looking like that might be where I'm heading. Ideally, he'd be able to make some HTML and check off "I'd like this to show on x and y Category page and b and z Collection page and for the tag Foo and for the tag bar as well as on my homepage"
Any suggestions? I'm open to finding a gem or getting a solid start on a homebrew.
UPDATE
I'm thinking of setting up some models Like the following:
cms_contents
============
id:integer
contents:text
timestamps
cms_associations
================
id:integer
cms_content_id:integer
model_id:integer
record_id:integer #optional
secondary_model_id:integer #optional
secondary_record_id:integer #optional
models
======
id:integer
name:string
Where:
cms_content would contain the HTML.
cms_associations would be an ActiveRecord model using has_many, :through
models would contain a the models the CMS content could be associated with
if record_id is not given, it associates with the model index
if record_id is given, it associated with the record of the provided model with that
id
if secondary information is given, a combination is created for other many to many
relationships
eg:
User has_many :photos
Browsing Photos for User(10)
model_id => #User model Id
record_id => 10
secondary_model_id => #Photo model id
So you could customize the content for browsing photos for specific users such as featured users or companies that may pay for advertising.
Any thoughts on this structure?
It's actually not that complicated. This is what you should do:
Introduce new object in the DB, name it htmlchunks
For every object that you'd want to associate with htmlchunks, create a join table and define habtm relationship
Modify your sidebar (for objects that have association with htmlchunks) in a way that they recognize whether there's htmlchunk associated with this particular object. For example, let's say you have a htmlchunk called "April Fools' Day" that contains simple html paragraph. In the sidebar, you'd just ask something like #category.htmlchunk? and output according to the result. You'd ideally place all this in a partial
As for creation of the htmlchunks you'd just offer simple wisiwig editor and ability to select any number of tags, categories, whatever. You'd create habtm entries between them and htmlchunks during the creation process
Let me know if you have further questions in the comments.
It's almost as if the almighty Ryan Bates is looking out for me, but the latest Railscast is on CopyCopter, which does exactly what I'm looking for, and runs as a separate app, so I don't have to worry about bogging down my main app. I suggest anyone who finds this to watch the screencast, as it seems pretty impressive.
http://railscasts.com/episodes/336-copycopter?autoplay=true

MySQL database model for signups with and without addresses

I've been thinking about this all evening (GMT) but I can't seem to figure out a good solution for this one. Here's the case...
I have to create a signup system which distinguishes 4 kinds of "users":
Individual sign ups (require address info)
Group sign ups (don't require address info)
Group contact (require address info)
Application users (don't require address info)
I really cannot come up with a decent way of modeling this into something that makes sense. I'd greatly appreciate it if you could share your ideas.
Thanks in advance!
Sounds like good case for single table inheritance
Requiring certain data is more a function of your application logic than your database. You can definitely define database columns that don't allow NULL values, but they can be set to "" (empty string) without any errors.
As far as how to structure your database, have two separate tables:
User
UserAddress
When you have a new signup that requires contact info, your application will create records in both tables. When a new signup doesn't require address info, your application will only create a record in the User table.
There are a couple considerations here: first, I like to look at User/Group as a case of a Composite pattern. It clearly meets the requirement: you often have to treat the aggregate and individual versions of the entity interchangeably (as you note). Implementing a composite in a database is not that hard. If you are using an ORM, it is pretty simple (inheritance).
On the other part of the question, you always have the ability to create data structures that are mostly empty. Generally, that's a bad idea. So you can say 'well, in the beginning, we don't have any information about the User so we will just leave all the other fields blank.' A better approach is to try and model the phases as if they were part of an FSM. One of the clearest ways to do this in this particular case is to distinguish between Users, Accounts and some other more domain-specific entity, e.g. Subscriber or Customer. Then, I can come and browse using User, sign up and make an Account, then later when you want address and other personal information, become a subscriber. This would also imply inheritance, and you have the added benefit of being able to have a true representation of the population at any time that doesn't require stupid shenanigans like 'SELECT COUNT(*) WHERE _ not null,' etc.
Here's a suggestion from my end after weighing pro's and con's on this model. As I think the ideal setup is to have all users be a user entity that belong to a group without differentiating groups from individuals (except of course flag a group contact person and creating a link with a groups table) we came up with the alternative to copy the group contact user details to the group members when they group is created.
This way all entities that actually are a person will get their own table.
Could this be a good idea? Awaiting your comments :)
I've decided to go with a construction where group members are separated from the user pool anyway. The group members eventually have no relation with a user since they don't require access to mutating their personal data, that's what a group contact person is for. Eventually I could add a possibility for groups to have multiple contact persons, even distinguishing persons that are or are not allowed to edit any member data.
That's my answer on this one.