Aggregating Data in Rails 3 - ruby-on-rails

I want to aggregate data from different sources, Twitter lastfm and that sort. I just can't figure out how to store the data. Clearly in a database but I can't figure out how abstract to make the table to hold all this data without compromising the logical understanding of the data in each column.
I was wondering if anybody else had experience with this and now they tackled it in rails.

One option, if you want to stick with SQL, would be to have a Model/Table which contains fields common to every data source (title, url, summary) which is associated to other Models/Tables which contain the fields specific to individual data sources. The associations could be regular or polymorphic. And if you wanted to get in to some metaprogramming you could use method_missing to delegate method calls for fields not present in the 'common' Model to the associated models. This would work best with a polymorphic join. Psudeo-code:
class DataSource
belongs_to :data_source_extension, :polymorphic => true
def method_missing(method)
if data_source_extension.responds_to? method
data_source_extension.send(method)
else
super
end
end
end
The other option would be STI, so one table with all fields and a 'type' field which tells Rails which model the record should be wrapped in. This depends on how many different sources you have and how different they are from each other.
If the fields don't need to be searchable storing a Hash in a Text field works well. See Serialize and the attr_bucket gem.
Or if you want to trendy a NoSQL type database allows on-the-fly fields to be generated.

What you need is a document-oriented database (I recommend you MongoDB), and then having a set of adapters, one for each type of provider.
Document oriented database

Related

Managing polymorphic data in Rails

I have an application where a User can create many Links, and each Link can store different type of data, depending on what type of Link it is. For example, a TelephoneLinkData stores a telephone number, an EmailLinkData stores an email address, a subject and a body. Each Link also has some fields in common, such as a reference to the user and a name.
I've tried to map this into ActiveRecord as cleanly as I can. Currently, I have a polymorphic relationship from Link to its data-type:
class Link < ApplicationRecord
belongs_to :user
belongs_to :link_data, polymorphic: true
...
class EmailLinkData < ApplicationRecord
has_one :link, as: :link_data
accepts_nested_attributes_for :links
...
Technically, I think this would be described as a reverse polymorphic relationship as instead of a class having possibly different parent classes, what I'm trying to model is a class having multiple possible different child classes. This works fine, and I'm able to create Links through the various *LinkData controllers, but what I'd really want to do is have the Link act as the primary source of interaction for the user, so that the user manages their links through the /links path. For example, I would like the API to allow a User to create a link by posting to /links with the data for the LinkData nested in the link_data field
I've looked around for other ways to model this relationship, and the most common other suggestion seems to be Single-Table Inheritance, but the majority of my columns will differ between LinkData classes, so that feels like the wrong abstraction.
Is there a more idiomatic way to model this data structure?
As is always the case, the best choice depends on the business or application needs, so it's difficult to provide a recommendation without knowing more about what you're trying to do.
It sounds like you prefer the MTI approach, essentially using actual foreign keys and an XOR constraint to the Link table instead of a type column. That's a totally reasonable (although not as common) alternative to a polymorphic association.
However, I think there was a bit of a misunderstanding in your question.
Technically, I think this would be described as a reverse polymorphic relationship as instead of a class having possibly different parent classes...
A polymorphic association in Ruby/Rails doesn't have anything to do with class inheritance (e.g. parents and children). You might be thinking of Single table inheritance. A polymorphic association allows one class (e.g. a Link) to be associated a record in any other table (e.g. the various classes of LinkData) via two fields, a association_id and association_type. These associated classes need not be related to each other. For example, a common use case might be the acts_as_commentable gem, that allows you to add a comment to any other object, and the comment would have a polymorphic association with the other classes.
In the second part of your question you mention that you'd like the User to interact with Link's via a single controller.
I would like the API to allow a User to create a link by posting to /links with the data for the LinkData nested in the link_data field
There's nothing stopping you from implementing this using the initially proposed data model. ActiveRecord may not handle this completely for you out of the box, but you can imagine implementing a link_data= method on the Link class that would create the appropriate associated object.
I'd say the pros/cons of using a polymorphic association would be...
Pros:
easy to setup and use
easy to make required (validate presence of / not null)
easy to associate with a new class
Cons:
no referential / database integrity
have to migrate data if you change a class name
And using the MTI approach is basically the opposite. A bit harder to setup and use, harder to add a new association/table, harder to ensure exactly one association exists... but the long term data quality benefits are significant.
I was able to get things to work the way I wanted to using multiple table inheritance, based largely on this chapter: https://danchak99.wordpress.com/enterprise-rails/chapter-10-multiple-table-inheritance/

Designing a Database Schema - Data that is common to all users or custom made

Hi I am working on a calendar application using Ruby on Rails. Rails is database agnostic, so in development I'm using SQLite but in production I am looking to use PostgreSQL.The current obstacle that I am facing is with the way I am designing my database schema.
First I have a users table that holds information such as login info and email. Each user has_many plans.
Then I have a plans table that belongs_to users and each plan has an event it references, the date, start time, and end time.
So the plan tables would reference the events table.
Here is my issue:
I would like to have two event tables. One is custom events. The other is default events.
The default events is just a list of common events already defined so the user can already select from a list. The custom events table is a list of events created by a user that references their id.
Here is my solution:
Would it be sufficient to add a new boolean column to the plans table called "custom". And if it is true then the event_id (in plans table) will reference the custom events table, and if it is false then it will reference the default events table. Is this a valid solution and if so, how would I implement it into my Rails application?
Thank you for taking your time to read my question. I am sorry I am an idiot. I am practicing everyday to be better.
Try to not think in terms of tables first, but in terms of classes and the behavior of their instances. What would matter most in the end is not how many tables your design has, but whether the responsibilities have been correctly attributed to the different classes in your model.
In this case it looks like you need two different classes, because some events will belong_to a user and other won't. The former will be created, modified and deleted by that user, and the latter will be managed by an admin. The instances of those classes can be stored in the same table using STI (Single Table Inheritance), with a string column named 'type' to enable Rails to store the class for each instance. The UserEvent class will belong_to :user, and the DefaultEvent won't. Both classes can extend Event, which in turn extends ActiveRecord::Base.
Please let me know if you need additional clarification.

Access Attributes of a "related" model from the first

I have a rails application that has several models. One particular model is the "focus" of the application, and it has several one to many, and several many to many relationships defined.
I have created logic to export the fields to a CSV file, and within the model I have defined a couple methods someone showed me to facilitate this. Here are the two methods:
def self.csv_header
fields = attr_order.*.to_s & content_columns.*.name
fields -= %w{created_at updated_at created_on updated_on deleted_at}
fields.reject! { |f| never_show? f }
fields
end
def to_csv
self.class.csv_header.map { |h| send(h) }
end
However, in my primary model (called patient) I need to include fields from some of the other one-to-many models (e.g. home_address, which contains street, city, state, zip, etc.). Is this possible to keep inside the patient model? I have set up logic in my controller which can add the other model's information, but it seems like it would be much cleaner to let the patient model grab all the additional information it needs from the other models and add it to the export rows.
Most of your work should be done in the models anyways, in my opinion. Keep the controllers thin, and the models fat, vs the other way around.
If you need to then access some attributes - say Patient has a 1-to-1 relationship with Address, then feel free to do so! Just do something like the data something like:
fields += HomeAddress.csv_header
home_address.rb
def self.csv_header
... pretty much the same thing as Patient.csv_header
end
So, you're not keeping the data in the Patient model, but rather, you're keeping the data where it belongs and just being able to access it.

Rails 3 Polymorphic Association between one MongoMapper model and one/many Active Record model/s

I have a Record model (Active Record) that stores some custom logs.
Record is in polymorphic association with all the other model in my app, and I can effectively log what I want hooking my Record methods in the other controllers.
What I need:
To have the logs in a separate database.
So I have to:
Be able to manage two different databases in my apllication (one is Postgres/ActiveRecord and the other one is MongoDB/MongoMapper)
Generate a polymorphic association between my Record model, now with MongoMapper, and the rest of my Active Record models.
That way I can persist my logs to the MongoDB database.
Thanks.
Yes this can be done.
To create a polymorphic association you need both the class and an id. Idiomatically the fields will be named <assoc>_type and <assoc>_id‡. You will need to do some wiring up to make everything work.
Create a MongoMapper::Document Class with the keys <assoc>_type and <assoc>_id with the correct types (I believe MongoMapper allows Class as a key type) along with any other keys you may need.
Define the method <assoc> and <assoc>=
def assoc
assoc_type.find(assoc_id)
end
def assoc=(input)
assoc_type = input.class #STI makes this more complicated we must store the base class
asspc_id = input.id
end
Possibly add a method to your ActiveRecord models allowing them to access you MongoMapper logging class. If there are a lot, you may want to build a module and include it in all the classes that need that kind of functionality.
‡ replace with something meaningful for you application like 'reference' or 'subject'

What is Ruby on Rails ORM in layman's terms? Please explain

I am having trouble understanding ORM in Ruby on Rails. From what I understand there is a 1:1 relationship between tables/columns and objects/attributes. So every record is an object.
Also what exactly is a Model? I know it maps to a table.
What I'm really after is a deeper understanding of the above. Thank you in advance for your help
I'm a Web developer going from PHP to Ruby on Rails.
"From what I understand there is a 1:1 relationship between tables/columns and objects/attributes. So every record is an object."
That is not exactly correct, unless you use the term "object" very loosely. Tables are modelled by classes, while table records are modeled by instances of those classes.
Let's say you have a clients table, with columns id (autonum) and name (varchar). Let's say that it has only one record, id=1 and a name="Ford". Then:
The DB table clients will map to the model class Client.
The record will map to a model instance, meaning that you have to create the object and assign it to a variable in order to work with the record. The most common way would be to do ford = Client.find(1)
The two columns of the table will map to methods on the ford variable. You can do ford.id and you will get 1. You can do ford.name and you will get the string "Ford". You can also change the name of the client by doing ford.name = "Chevrolet", and then commit the changes on the database by doing ford.save.
"Also what exactly is a Model? I know it maps to a table"
Models are just classes with lots of very useful methods for manipulating your database. Here are some examples:
Validations: Besides the typical db-driven validations ("this field can't be null") you can implement much complex validations in ruby ("this field must be a valid email" is the most typical one). Validations are run just before you invoke "save" on a model instance.
Relationships: The foreign keys can also be mapped onto models. For example, if you had a brands table (with its corresponding Brand model) associated via a foreign key to your ford client, you could do ford.brands and you would get an array of objects representing all the records on the brands table that have a client_id = 1.
Queries: Models allow you to create queries in ruby, and translate them to SQL themselves. Most people like this feature.
These are just some examples. Active record provides much more functionalities such as translations, scoping in queries, or support for single table inheritance.
Last but not least, you can add your own methods to these classes.
Models are a great way of not writing "spaguetti code", since you are kind of forced to separate your code by functionality.
Models handle database interaction, and business logic
Views handle html rendering and user interaction
Controllers connect Models with Views
ORM in Rails is an implementation of the Active Record pattern from Martin Fowler's Patterns of Enterprise Application Architecture book. Accordingly, the Rails ORM framework is named ActiveRecord.
The basic idea is that a database table is wrapped into a class and an instance of an object corresponds to a single row in that table. So creating a new instance adds a row to the table, updating the object updates the row etc. The wrapper class implements properties for each column in the table. In Rails' ActiveRecord, these properties are made available automatically using Ruby metaprogramming based on the database schema. You can override these properties if required if you need to introduce additional logic. You can also add so-called virtual attributes, which have no corresponding column in the underlying database table.
Rails is a Model-View-Controller (MVC) framework, so a Rails model is the M in MVC. As well as being the ActiveRecord wrapper class described above it contains business logic, including validation logic implemented by ActiveRecord's Validation module.
Further Reading
Rails Database Migrations guide
Rails Active Record Validations and Callbacks guide
Active Record Associations guide
Active Record Query Interface guide
Active Record API documentation
Models: Domain objects such like User, Account or Status. Models are not necessarily supported by a database backend, as for example Status can be just a simple statically-typed enumeration.
ActiveRecord:
Provides dynamic methods for quering database tables. A database table is defined as a class which inherits ActiveRecord class (pseudo-PHP example):
class User extends ActiveRecord {}
//find a record by name, and returns an instance of `User`
$record = User::find_by_name("Imran");
echo $record->name; //prints "Imran"
//there are a lot more dynamic methods for quering
New records are created by creating new instances of ActiveRecord-inherited classes:
class Account extends ActiveRecord {}
$account = new Account();
$account->name = "Bank Account";
$account->save();
There are two pieces here: the ORM and Rails's MVC pattern. ORM is short for "object-relational mapping", and it does pretty much what it says: it maps tables in your database to objects you can work with.
MVC is short for "model-view-controller", the pattern that describes how Rails turns your domain behavior and object representations into useful pages. The MVC pattern breaks down into three chunks:
Models contain a definition of what an object in your domain represents, and how it is related to other models. It also describes how fields and relationships represented in the object map to backing stores (such as a database). Note that, per se, there's nothing about a model which prescribes that you have to use a particular ORM (or even an ORM at all).
Controllers specify how models should interact with each other to produce useful results in response to a user request.
Views take the results created by controllers and render them in the desired way. (By the time you get to your view, you should mostly know what's being rendered, and there should be very little behavior happening.)
The definition from Wikipedia:
Object-relational mapping (ORM, O/RM,
and O/R mapping) in computer software
is a programming technique for
converting data between incompatible
type systems in relational databases
and object-oriented programming
languages. This creates, in effect, a
"virtual object database" that can be
used from within the programming
language.
From a PHP view it will be in the following way(via example)
Connect to the database and get some row from posts table.
Turn that row to an object with attributes like those in the table columns.
If the posts has comments in comments table, you can also do post.comments and you get the comments also as an array of objects as well.
You can define relationships between tables like saying: Posts has_many Comments, a Comment belongs to a post and so.
So basically you are not working with database rows, instead you turn those rows and their relationships to objects with composition or inheritance relationships.
In layman's terms.
A Rails Model is proxy to a table in the database. These models happens to be Ruby classes.
The objects of these classes are proxies to rows in the table of which this model is a proxy.
Finally the attributes of these objects are proxies to the column data for that particular row.
Above is actually the Rails ActiveRecord ORM.
1:1 is not quite correct, since there is object-relation impedance mismatch.

Resources