'Connect' a rails app to an already existing MySQL DB? - mysql

So in my company we are slowly moving to Rails instead of PHP(Code Igniter to be precise).
So, our actual PHP App is using a Mysql DB and I'd like to connect a new Rails app to this DB but meanwhile our PHP is still running, so I can't change the DB.
I don't really know where I should start to use all the rails features (Or at least as much as possible).

There shouldn't be any harm in connecting your rails app to an existing database. You will need to watch for anything that goes against rails conventions (table names are plurals of models, for example) and either change the database (and your php app) or program around the problem in rails.
But the first step is simply to connect to the database and make models for the existing tables and see what works and what doesn't.
After that, post here with any specific problems.
As a suggestion, take a backup of your database and start out programming against that to build your application and be sure everything works safely.

Well, first of all you should setup the connection in config/database.yml and then start to generate the scaffolding (models, views and controllers) table by table (check the Rails generate command). I am not really sure if you have already generated the app though. Anyway, the generator will also generate a migration script that you obviously dont want to run as the db is already there.
Hope this helps a bit.
Anyway, some resources:
http://guides.rubyonrails.org/
http://railsapps.github.io/

There are two aspects of a Rails app to consider for this scenario:
1: the database connection
Simply put the credentials for this database into database.yml.
A model like "User" will by default attempt to find records and attribute definitions in a table called "users". ActiveRecord will assume there's an auto-incrementing integer primary key on each table. When saving records, it will attempt to write to columns called created_at and updated_at. Those are a few things to be mindful of when making and using the connection.
2: the database migrations
Rails uses migration files to manage a sequence of changes to the database structure. Under normal conditions, someone building a Rails app will be starting with an empty database.
In the case of an existing database, I would recommend making a migration something like:
class BuildLegacyDbStructure < ActiveRecord::Migration
def up
Mysql2.connection.execute_some_sql_file( # made-up function
Rails.root.join('path', 'to', 'file')
)
end
def down
# reverse those changes; bring DB down to blank state
end
end
Another option would be to disable Rails/ActiveRecord's migration-based management of the database entirely. For example Rails will generate a migration when you generate a new model. So if you have an existing users table in your PHP app, and you'd like to make a rails model to use this table, you'd run something like rails generate model User --no-migration.

Related

Default content of DB tables in Laravel

I'm learning Laravel and have got a question I can't quite figure out myself.
So for instance I have DB tables like cities or car_models and migrations for them. But I don't want to manually populate those tables each time I migrate:refresh or deploy the project on testing/production server, so they must have some default content.
Is it okay to populate them right in the migration? Or is this what seeders are for? (as far as I understood they are for populating tables with some fake data for testing needs)
Both answers are correct. But they're missing something important.
In my opinion, the most important value using Seeder classes is that you decouple your migrations from your population logic.
Why is this important? You have many answers for this:
Code quality.
Support of a couple SOLID principles.
Good practices.
Better understanding of your code.
Cleaner API.
But for me, the top one is that this lets you to have different results for distinct porpuses using the same code. This is an example:
You write your seeders/population logic inside migration files. What happen if you want to deploy your app in a production environment? Well, you'll need to modify your migrations to avoid incluiding the functions of dummy data, then commit those changes and upload them to the server. If you need to deploy it in a different environment (staging for example) you'll need to change this again.
Instead, if you create specific classes to populate your database (Seeders) you have the flexibility to use the same code and include (or the opposite) them with a command flag:
// The following won't include your seeders
php artisan migrate
// This will include your seeder classes
php artisan migrate --seed
You can be even more granular, specifying a specific seeder:
php artisan migrate
php artisan db:seed --class=UsersTableSeeder
This is helpful when you want to populate just a few tables in your environments (like roles, types, cities and so on) instead of running all of your seeders (users, orders, reservations, ...).
I hope this helps.
migration is used to create table while seeder is used to insert dummy data to table in database. You can populate them in migration but it's not a good practice and can lead to confusion.

is it ok to change the database table schemas created from rails using mysql?

I created some tables using rails. Now I want to modify the structure of a few of them. I know it can be done using rails migration. But i was wondering if it would cause any anomaly in the rails app if I modify the schemas using mysql rdbms?
Doing such changes through a migration has the advantage of not losing the changes if you decide to recreate/remigrate the database.
Also it serves as documentation. Imagine if your coworker altered some tables sneakily (and then you both forgot about it).
Technically, updating schemas directly in the database should work, but don't do it.
To add to Sergio's point, you're missing a simple fact - Rails' migrations create the famous db/schema.rb file - from which your migrations pull all their data.
The importance of schema.rb is overlooked - it is one of the most crucial aspects of your application.
db/schema.rb
The schema gives all your migrations a version of your DB to change / add to. Each time you perform a migration, Rails changes the schema file to ensure it has a "blueprint" of your db stored on file.
The schema is then able to rebuild the database using such methods as rake db:schema:load (ONLY RECOMMENDED FOR NEW INSTALLS -- DELETES PREVIOUS DATA)
So whilst there's no problem setting up the db using the db's own native tools, I recommend against it. You need to keep your migrations up to speed so that Rails can build the appropriate tables from its schema.

Django update models.py when database changes

I know this might be a sill question but I've been half an hour trying to figure this out and couldn't find anything :S
I have a django app and I significantly changed my database tables. I want to update my models.py file, but I tried the following commands and nothing happens.
syncdb, migrate, makemigrations...
I want to delete my previous models file and create a new one.
Thank you!
You got the workflow the wrong way around.
Django has an ORM that manages your database. If you want to make a change, you edit your models.py file. The migrations will automatically alter the database table to match your new model. It doesn't work the other way around: Django does not use database introspection to pick up manual changes in the database and edit your models file.
Now, there is a workaround, but it's not a long-term solution. In time you'll want to add custom functionality to your models, and you don't want to rewrite that functionality after each change. The introspection Django provides isn't perfect either, it's only meant as a tool to quickly start developing your application on top of a legacy database.
You can use manage.py inspectdb to generate the Django code for all existing tables. You can then copy the code for your specific model over to your models.py file. You should then delete the managed = False and db_table = ... options, remove any migrations, double-check the fields, and rerun makemigrations and migrate --fake-initial. This will get the database, your models, and your migrations back in sync, and then you'll be able to use the migrations framework for any additional changes.
Be sure to read the docs on migrations. That should leave you with a good understanding of how Django manages the database, and what the workflow is to make changes to your database.

Connecting to external database the idiomatic way in RoR?

I am creating a RoR app, and need to connect to my company's MySQL database (which has nothing to do with this app in itself) to gather some data and report it through the RoR app. What is the idiomatic way to connect to this database? I'll just be running some fairly lite select queries off of it, however they often involve table joins. Should I just connect as through this were not a RoR app?
If your queries are mostly bound to single tables or utilize only a few joins, you can actually define models for them. It would seem that allowing ActiveRecord to operate on them may be the most idiomatic method to do it inside Rails.
First, define the company database in your database.yml
class ExternalDbTable
# Connect to the db
establish_connection :connx_from_database_yml
# Define table if this query is bound to a single table
set_table_name 'ext_db_table'
set_primary_key 'pk_column'
end
From there, you can define named_scopes as you would with a Rails model and basically enjoy all ActiveRecord's benefits. If you don't have to access more than a handful of tables on the external db, you can create models for each and define has_many/belongs_to relationships as you normally would in ActiveRecord. However if it is a large number of tables and you have the ability to create a view on the external database, you can create a model pointed to the view which performs the joins for you. Then define named_scopes against the view as necessary.

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.