Rails how to version the models? - ruby-on-rails

I have created rails application using rails 5 and ruby 2.3. I want to add few changes in some model files and save it as new application. I want two run both applications in production as two similar applications. I know how to version the controller by using namespace but I didn't get solution for version rails models.

Are you saying you want to run two copies of the application in production under different namespaces (e.g., /v1/ and /v2/), both sharing the same database?
There's no easy way, because it's not a good idea. Each time you change to one application, you'll have to remember to change both - and worse if you add more versions in the future.
If possible, you should share one codebase and put any versioning logic in the controller that accesses the model. Your controller can inspect the route that was used to hit it (/v1/ or /v2/) and respond accordingly.
In order to share one database between two versions of your code, you'll need to ensure that any changes you make to the database schema are backwards- and forwards-compatible, meaning you can only add new tables or columns (never rename or remove).
If you don't need the two versions of your app to share the same database, you could give the new version its own copy of the database (database: my_schema_v2 in config/database.yml).
Or you could give the v2 of your model its own table name:
class Product < ApplicationRecord
self.table_name = "products_v2"
end
But again, that means products would not be shared between the old and new versions of your code.

Related

How to share a database, migrations, and models between Rails projects?

I know there are some questions to this effect already on StackOverflow, but they tend to be pretty outdated and don't adequately address how migrations are supposed to work in the following scenario, which should be fairly common:
You have some kind of application, implemented in Rails.
You have some kind of admin application for your data, and it is a separate application implemented in Rails.
Both applications operate on the same database and models.
My question is: what is the best way to factor our models such that both of these applications don't have to duplicate model code?
We are concerned with the following:
For the shared models, where should database migrations live?
What if each individual application wishes to add additional models on top of shared models? Where do these migrations live?
What is the best way to move existing migrations into the proposed shared migration scheme?
Thanks.
I don't know if this is THE approach, and would love to see other ideas, but what we do in one of our products that matches this model:
For the shared models, where should database migrations live?
We keep all of our migrations under the admin system. You don't need them to exist twice, so that's where they go.
What if each individual application wishes to add additional models on top of shared models? Where do these migrations live?
We share all models. It might only be relevant to one application at the moment, say - a favourited_items concept might only matter to the end user. But at a later date the admin might want to know what items are most frequently favourited.
Secondly, if you want to investigate anything via console, it's really quite helpful if you don't need to visit separate applications because they don't both have models for every table.
Functionality in shared models that differs per application detects the rails environment variable, which we have extended to include more context. E.g.: if Rails.env == 'admin_production'
What is the best way to move existing migrations into the proposed shared migration scheme?
Again, migrations should only ever exist once, and the shared database knows which have already been run, so unless you're renaming the migrates you just need to pick a location and move the files.

Can a Drupal based website's schema be imported to Rails?

I'm working on a web site that needs to be re-written in Rails. The website was before in Drupal, and there are almost 100,000 records in the database. Now, in Drupal there are tables that do not make any place in Rails in my opinion. For example,
Table name: node_type
It stores information regarding modules in Drupal.
Table name: node
It stores information for node(s) in Drupal.
Table name: semaphore # I've no idea what it is!
Table name: rdf_mapping # No idea
I've not been working with Drupal, so all I want to ask: Is it possible to have a schema for Rails, in which the existing 100,000 records can be imported from Drupal? If so, how? If not so, what are the other options that I'm left with? Or I have to design an entirely new database schema?
Drupal's database schema is not extensively documented for a reason... it's considered implementation details, is not a public API and should not be accessed directly, especially by outside application.
It is also very hard to document because for a given site, any enabled module can add its own tables and alter existing ones (usually adding columns). Plus you have module like Fields (part of Drupal core) that create tables dynamically depending on defined content types.
For a RoR developer, the Drupal schema will probably look weird and be uncomfortable to work with. I would follow suggestion from others, create a new schema for your new application and create a migration script to get the data from the old Drupal database to your new database. I don't knwon about RoR, but try to find a good data migration that allows replay, updates and rollback, etc. You will probably have to migrate the data multiple times to fixes bugs in the process.
Well, I don't have straight forward answers, but I have some ideas what I would do simply to not make so much changes in the database, or as per the comment you can write down an sql script to migrate the data according to the rails schema like types for each tables. Now, I am just intended here to share my thoughts, but I believe there might be more explicit solutions and this is do-able in many ways, may be you need some customizations(?) overriding the default conventions. According to my thoughts, you can try the following things.
Generated Related model skipping migrations
Define tables explicitly to each models like the following snippets:
class Semaphore < ActiveRecord::Base
self.table_name = "semaphore"
end
You have to define foreign keys and primary keys explicitly for both record id and associations.
You have generate time stamp or you can explicitly avoid that like the following ways
ActiveRecord::Base.record_timestamps = false
These are basic things I can see is important.

How to manage migrations when multiple apps share the same database in Ruby?

I have a Rails app and a Sinatra app, sharing the same database. The Sinatra app uses ActiveRecord.
Can I run migrations from within each app, as if they were in the same app? Will this cause any problems?
The schema.rb file in the Rails app tracks the current migration via
ActiveRecord::Schema.define(:version => 20121108154656) do
but, how does the Sinatra app know the current version the database?
Rails 3.2.2, Ruby 1.9.3.
The version column in the schema_migrations table equate to the time stamp on the front of the ruby migration file example: 20130322151805_create_customers.rb So if two ore more applications are contributing to the schema_migrations table roll backs will not be possible if rails can't find the down() method (because it will not find a migration file contained in another app ie db/migrate/...)
I have a current situation that is exactly this and I have opted to have a master ActiveRecord app that manages migration and data conversions as our database evolves. Keep in mind that part of the deal is to keep models up to date as well. This has been time consuming so we are considering breaking apart the DB in to business domains and providing APIs (JSON) to query support data for another application. This way each application manages it domain and is responsible for exposing data via API.
regards.
If you connect both applications to the same database you should be able to run migrations on it but I strongly suggest you use another option since you will almost surely hit a wall at one time or another:
split the database in two if possible with each application responsible for its own database /migrations.
have one application considered the "master" database and use another database for the data specific to the second application but make it connects to both database (each application still only apply migrations to one database)
If you need to share data between multiple applications another option is to implement a REST service in one and use it on the other, you can have a look at the grape gem for a simple way of doing so.
Edit: I realize I forgot to speak about the activerecord migration, there is no longer any "version" of the schema, what activerecord does is that it read all your migration filename, extract their identifier (the starting part) and check if they have already been applied so in theory you can run migrations from two applications on the same database provided they don't interfere.
But if both migrations act on the same tables you will almost certainly run into big troubles at one point.
I disagree with Schmurfy, even if his presented options are valid, its a bit of an overkill to share data through REST (granted, its pretty easy to implement with ruby / rails).
If your case is simple you could just use one database from both apps, and since you use AR in both of them you have no problems with versioning, AR takes care of that.
Also i dont know what happens if you run db:migrate from both apps simultaniously if you use a inferior dbms like mysql which does not allow DDL in a transaction, certainly nothing good..
Also it would bother me to look which app needs what column and not have the migrations in one place. You could use a shared repository to manage the migrations from both apps.
Rails migrations store current database version in schema_migrations table in the database. So both of your apps will be able to check the current version.
The version numbers are timestamps, so there shouldn't be any problem with duplicate values, as it'll be almost impossible to generate two migrations at the exact same millisecond. So you should be fine here.
The only problem I see is that when you rollback a migration in one app, it'll set the db to the previous known version and I'm not sure if it will pick the previous one from the db (which could be from the other app), or the number from the previous migration file. You may want to test that scenario to make sure.
I decided to put all migrations in the Rails app because:
Since there is only one database
Rails manages migrations
This has worked well.
This simplifies the system because all migrations are stored in one place. And, the Sinatra app doesn't need to know about them anyway.

Generate new models and schema at runtime

Let's say your app enables users to create their own tables in the database to hold their own, custom data. Each table would have it's own schema. What are some good approaches?
My first stab involved dynamically creating migration files and model files bu I'd like to run this on heroku where you can't write to the filesystem.
I'm thinking eval may be the way to go to create and run the migration class and the model class. But I want to make sure the model class exists when a new process of the app is spawned. Can probably do this by storing these class definition with each user as they create new tables and then run through them all at startup. But now it's convulted enough that I may be missing something obvious.
It's probably a better idea not to generate new classes on runtime. Besides all of the security risks, each thread's startup time will be abominable if you ever get a significant number of users.
I would suggest rethinking your app design and aim at generic tables to hold the user's custom data. If you have examples of data structures that users can create we might be able to help.
Have you thought about a non-sql database for those tables? Look at CouchDB - there are several plugins on Github that integrate it with rails. Records in the database are JSON documents, with arbitrary key-value structure. May be perfect for a user-defined schema.
There is (was?) a cool Wiki project, called Informl. It was a Wiki, not just for web pages but for web applications. (Get it? It's informal because it's a Wiki, it's got forms because it is an application, and it's user-generated, thus Web 2.0, which means that according to an official UN resolution it is legally required to have a name which is missing a vwl.)
So, in other words, it was not just about user-generated content, but also user-generated structured data.
They did this by generating PostgreSQL-specific SQL at runtime to create new tables and then have ActiveRecord reload the schemas.
The code is up on RubyForge. It's based on Rails 1.2.3. I guess you could do much better than that today, especially with the upcoming extensibility interfaces in Rails 3.

Rails 2.1 and Rails 2.3 sharing the same database

We have an admin application used to manage member data and it was built in 2.1, has been running for about a year. Now that all inputs and data massage is done, our client wants to start building member site, members will have access to data the administrators have been inputting.
Here's the question, should we start a new Rails app hooked to the same admin database or should we create a new Rails app in different db with master-slave settings? The good thing about creating a new Rails app is obviously taking advantage of the new version, which we like. Or ..maybe just build the member site in the same admin app?
THanks,
Why don't you want to build the member site in the same admin app? Too much legacy?
You can use the same database but the problem is you will have to enforce any conditions you have in your models directly in your database (mandatory fields, model relationship and so on).
And I can see a lot of duplication code happening between the two apps. At least for the models. Which is really wrong :(
I don't recommend making two separate applications but It is hard to answer without looking at your app and without knowing more details.
Or build a new app using a copy of the existing database?
There's no reason the two applications cannot share the same database.
However, there's probably a number of reasons why they shouldn't. But, the only way you're going to figure those out are by going through the changelog of ActiveRecord's database adaptors.

Resources