Ruby on Rails3 and MySQL query best practices - mysql

I'm trying to transition from PHP to Rails and was wondering what the best practices are. I have all the data I need in MySQL and would like to make simple queries and display them using the kinds of niceties afforded by ActiveRecords. I'm familiar with the MVC paradigm and am trying not to rely on my knowledge of PHP, but how, for example, would I be able to do the kinds of things I used to do with:
$query = mysql_query("Select * from table where name = 'blah');
if I already have that data (I can see generating a scaffold if I didn't have pre-existing data). Do I create a scaffold and then import my data into it? or do I write raw MySQL queries in Ruby?
Thanks!

First, remember that Rails is a web dev framework, not a scripting language like PHP. Ruby is the scripting language. PHP has frameworks as well, but just wanted to make sure you realize the difference between the one and the other.
Most basic and medium-complexity queries in Rails are handled via the ActiveRecord methods and helpers. You'll find that you'll be writing much less actual SQL, as that is generally abstracted away into the framework.
For instance, assuming the name of your model is City, the equivalent of your query in Rails would be:
City.find_all_by_name('blah')
How does this work? When you create a model in Rails you usually subclass ActiveRecord::Base. Built into that class is a plethora of functionality that, for one thing, examines your data table and builds dynamic finders for each of the fields and combination of fields on the table.
Since you already have all the data, you're going to be overriding some of the conventional functionality of Rails in order to get everything working. For instance, Rails assumes by convention that there is a primary key field named "id". Also, Rails assumes that the table is named as the plural form of whatever the model class definition is. All of these things are defaulted by convention, but can be overridden. If you were building from scratch and following conventions, all this would sort of happen as a matter of course.
Based on your question, I think you need to spend some time with some basic Rails reading material and some specific info about ActiveRecord and Rails models, so that you can come up to speed on these major differences between Rails and standard PHP application. If you don't get that straight from the beginning, then you are going to build a lot of PHP-style Rails stuff and you won't be taking full advantage of what Rails and Ruby have to offer. In the end, you'll say "what did I do all that for, it's all the same."
If, instead, you try to start from the Rails Way of doing things, you'll find that Ruby and Rails offer a lot.

If you are working with an existing database then you are going to have a hard time forcing Rails to play nicely with it. Rails power (some might call it a weakness) is that it favors convention over configuration. In other words, it really expects you database columns to be structured a certain way. Stray from the convention and you lose all the reasons for using Rails in the first place.
When you start a new rails project and use the migrations rails makes sure that the structure is as it expects.
If you are moving an old project to rails then I would strongly suggest writing a function to import that data into a rails-created DB. This will save you a lot of heartache in the long run and will allow you to take full advantage of Rails' strengths.

Related

Database versioning tool for Node and MySQL

Is there a solution that helps you manage database schema patches, preferably that runs in Node. I am looking at node-db-migrate which has support for MySQL but I want to be able to run plain vanilla SQL on it instead of using wrapper functions offered by this package.
Is there a solution that offers the same functionality but also lets you have plain SQL in patches?
I'm personally a fan of Sequelize, which has a (poorly named) sister project called Umzug designed to handle migrations. You can absolutely run vanilla SQL in a package like this, but be very careful doing so. Running raw SQL can be an easy way to do something like populate a new column with data (perhaps a new summary column that needs to be filled with the results of a more complex query you've been running until now). However, it can also make it very easy to make mistakes if you do this for things like ALTER TABLE. Whenever you can, it's best to use provided constructs for things like that.

Doing SQL queries in Rails with Variables - Converting a PHP/Codeigniter Application

I'm converting a PHP app written in CodeIgniter to Rails.
Due to the size of the application and the inability to makes change to the schema, I'm not interested in making models for each entity.
I want to be able to do CodeIgniter style queries like this (Supply a pre-written query and associated variables):
query("SELECT * FROM posts WHERE id = ?", id)
and get a result back.
I know that it's highly suggested to use models and do it "the rails way", and I definitely plan to for my next application that I write from scratch in Rails, but for this project I want to avoid the ORM and just have the ability to do direct queries using the database connection.
What would be the best way to do this?
I hate myself for not having the willpower to not answer this question, so just quickly:
Use ActiveRecord#find_by_sql

Running arbitrary SQL queries in Ruby

I've just been tasked with automating a reporting task at work. Previously, someone would run large, arbitrary SELECTs on a MySQL database using a GUI tool, then use that same tool to export the results to CSV. Now I want to write a Ruby script to do this.
I know about FasterCSV in Ruby, but as far as SQL queries, I've only used ActiveRecord, where you're generally not writing the queries but using models and associations. The last time I wrote out complete SQL in code was when I coded PHP.
What's the most straightforward way to do this sort of thing in Ruby? Should I use ActiveRecord?
If you are writing a complex application, there is absolutely nothing wrong with using ActiveRecord. Especially since you are already comfortable with it.
If you are writing a quick script and don't want to bother with ActiveRecord, you should also check out the mysql and mysql2 gems.
I highly recommend Sequel. It has great documentation, active development, a thriving and helpful community, and it is (IMHO) simpler and better than ActiveRecord, especially for simple use cases like you appear to have.
You might want to start by reading the README, Cheat Sheet and Sequel for SQL Users.
I often find that in reporting engines you end up with complex queries processing large amounts of data and ORMs like ActiveRecord just don't cut it. Unless your reports are really simple, I think you'll want to use raw SQL (with a tool like Sequel) or call stored procedures.

Putting Rails over top of an existing database

I have an application written in PHP/MySQL (symfony, to be specific) that I'd (potentially) like to rewrite in Rails. I know how to create scaffolding for tables that don't exist yet, but how do I get Rails to read my existing table structure and create scaffolding based on that?
Update: it turns out I can run the following command to get Rails to generate models for me:
rails generate scaffold Bank --no-migration
But it doesn't give me forms. I would prefer something that gives me forms.
The answer is db:schema:dump.
http://guides.rubyonrails.org/migrations.html
The easiest route is to pretend that you are writing a fresh app with a similar database schema - you can then create your models and migrations with the old schema in mind, but without being restricted by it. At a later stage, you can create a database migration script to copy all the old data into the new schema.
I'm doing this right now. The benefit of this approach is that you can take advantage of all of the rapid development tools and techniques provided by Rails (including scaffolds) without being slowed by trying to retrofit to the exact same schema.
However, if you do decide that you don't like this approach, and you do need to map your new models to existing tables, there are a number of configuration options provided by active record where you can override the convention over configuration naming patterns and map model names to tables names, set oddly named ID fields etc. For example:
class Mammals < ActiveRecord::Base
set_table_name "tbl_Squirrels"
set_primary_key :squirrel_id
end
The above will help Rails attempt to read your existing table, but success will depend upon how well the existing table structures matches Rails conventions. You may have to supply more configuration information to get it to work, and even then it might not work.
Finally, it may be worth considering the use of DataMapper which I believe is more suited to existing brownfield databases than ActiveRecord, because it allows you to map everything, but of course you will need to learn that API if you don't already know it.

What is the best way to build a data layer across multiple databases?

First a bit about the environment:
We use a program called Clearview to manage service relationships with our customers, including call center and field service work. In order to better support clients and our field technicians we also developed a web site to provide access to the service records in Clearview and reporting. Over time our need to customize the behavior and add new features led to more and more things being tied to this website and it's database.
At this point we're dealing with things like a Company being defined partly in the Clearview database and partly in the website database. For good measure we're also starting to tie the scripting for our phone system into the same website, which will require talking to the phone system's own database as well.
All of this is set up and working... BUT we don't have a good data layer to work with it all. We moved to Linq to SQL and now have two DBMLs that we can use, along with some custom classes I wrote before I'd ever heard of Linq, along with some of the old style ADO datasets. So yeah, basically things are a mess.
What I want is a data layer that provides a single front end for our applications, and on the back end manages everything into the correct database.
I had heard something about Entity Framework allowing classes to be built from multiple sources, but it turns out there can only be one database. So the question is, how could I proceed with this?
I'm currently thinking of getting the Linq To SQL classes all set for each database, then manually writing Linq compatible front ends that tie those together. Seems like a lot of work, and given Linq's limitations (such as not being able to refresh) I'm not sure it's a good idea.
Could I do something with Entity Framework that would turn out better? Should I look into another tool? Am I crazy?
The Entity Framework does give a certain measure of database independence, insofar as you can build an entity model from one database, and then connect it to a different database by using a different entity connect string. However, as you say, it's still just one database, and, moreover, it's limited to databases which support the Entity Framework. Many do, but not all of them. You could use multiple entity models within a single application in order to combine multiple databases using the Entity Framework. There is some information on this on the ADO.NET team blog. However, the Entity Framework support for doing this is, at best, in an early stage.
My approach to this problem is to abstract my use of the Entity Framework behind the Repository pattern. The most immediate benefit of this, for me, is to make unit testing very simple; instead of trying to mock my Entity model, I simply substitute a mock repository which returns IQueryables. But the same pattern is also really good for combining multiple data sources, or data sources for which there is no Entity Framework provider, such as a non-data-services-aware Web service.
So I'm not going to say, "Don't use the Entity Framework." I like it, and use it, myself. In view of recent news from Microsoft, I believe it is a better choice than LINQ to SQL. But it will not, by itself, solve the problem you describe. Use the Repository pattern.
if you want to use tools like Linq2SQl or EF and don't want to have to manage multiple DBMLS (or whaetever its called in EF or other tools), you could create views in your website database, that reference back to the ClearView or Phone system's DB.
This allows you to decouple your web site from their database structure. I believe Linq2Sql and EF can use a view as the source for an Entity. If they can't look at nHibernate.
This will also let you have composite entities that are pulled from the various data sources. There are some limitations updating views in SQL Server; however, you can define your own Instead of trigger(s) on the view which can then do the actual insert update delete statements.
L2S works with views, perfectly, in my project. You only need to make a small trick:
1. Add a secondary DB table to the current DB as a view.
2. In Designer, add a primary key attribute to a id field on the view.
3. Only now, add an association to whatever other table you want in the original DB.
Now, you might see the view available for the navigation.