I have a database in PostgreSQL 9.6.6 already defined, how do I reverse engineer that into Ruby on Rails?
[Please don't flame me if this has already been asked, I couldn't find an answer when I searched.]
Thank you.
Understood, i read your comment. But the thing is, Model with relations and attributes in rails provide by Active Record, in fact you cant export all stuff from random database.
You need to create migrations/models with Active Record Associations and object attributes, and after that Seed new database.
Somebody correct me if I'm wrong:
It would seem to me that since rails determines what columns are in a table by actually looking at the table definition in the database, that we (I) don't have to "reverse engineer" the database.
If rails is interrogating the database for the definitions, then the only thing we would have to do is define the relationships in the ORM classes and that we don't have to create migrations.
I'm a junior Rails developer and at work we faced the following problem:
Needed to update the value of a column only for one record.
What we did is creating a migration like this:
class DisableAccessForUser < ActiveRecord::Migration
def change
User.where(name: "User").first.update_column(:access, false)
end
end
Are migrations only for schema changes?
What other solutions do you suggest?
PS: I can only change it with code. No access to console.
The short version is, since migrations are only for schema changes, you wouldn't want to use them to change actual data in the database.
The main issue is that your data-manipulating migration(s) might be ignored by other developers if they load the DB structuring using either rake db:schema:load or rake db:reset. Both of which merely load the latest version of the structure using the schema.rb file and do not touch the migrations.
As Nikita Singh also noted in the comments, I too would say the best method of changing row data is to implement a simple rake task that can be run as needed, independent of the migration structure. Or, for a first time installation, the seed.rb file is perfect to load initial system data.
Hope that rambling helps.
Update
Found some documentation in some "official" sources:
Rails Guide for Migrations - Using Models in your Migrations. This section gives a description of a scenario in which data-manipulation in the migration files can cause problems for other developers.
Rails Guide for Migrations - Migrations and Seed Data. Same document as above, doesn't really explain why it is bad to put seed or data manipulation in the migration, merely says to put all that in the seed.rd file.
This SO answer. This person basically says the same thing I wrote above, except they provide a quote from the book Agile Web Development with Rails (3rd edition), partially written by David Heinemeier Hansson, creator of Rails. I won't copy the quote, as you can read it in that post, but I believe it gives you a better idea of why seed or data manipulation in migrations might be considered a bad practice.
Migrations are fine for schema changes. But when you work on much collaborated projects like pulling code everyday from lot of developers.
Chances are you might miss some migrations(Value update migrations..No problem for schema changes) Because migrations depends on the timestamps.
So what we do is create a rake task in a single namespace to update some table values( Be careful it does not overwrites)
And invoke all the rake task in that NameSpace whenever we update the code from Git.
Making data changes using classes in migrations is dangerous because it's not terribly future proof. Changes to the class can easily break the migration in the future.
For example, let's imagine you were to add a new column to user (sample_group) and access that column in a Rails lifecycle callback that executes on object load (e.g. after_initialize). That would break this migration. If you weren't skipping callbacks and validations on save (by using update_column) there'd be even more ways to break this migration going forward.
When I want to make data changes in migrations I typically fall back to SQL. One can execute any SQL statement in a migration by using the execute() method. The exact SQL to use depends on the database in use, but you should be able to come up with a db appropriate query. For example in MySQL I believe the following should work:
execute("UPDATE users SET access = 0 WHERE id IN (select id from users order by id limit 1);")
This is far more future proof.
There is nothing wrong with using a migration to migrate the data in your database, in the right situation, if you do it right.
There are two related things you should avoid in your migrations (as many have mentioned), neither of which preclude migrating data:
It's not safe to use your models in your migrations. The code in the User model might change, and nobody is going to update your migration when that happens, so if some co-worker takes a vacation for 3 months, comes back, and tries to run all the migrations that happened while she was gone, but somebody renamed the User model in the mean time, your migration will be broken, and prevent her from catching up. This just means you have to use SQL, or (if you are determined to keep even your migrations implementation-agnostic) include an independent copy of an ActiveRecord model directly in your migration file (nested under the migration class).
It also doesn't make sense to use migrations for seed data, which is, specifically, data that is to be used to populate a new database when someone sets up the app for the first time so the app will run (or will have the data one would expect in a brand new instance of the app). You can't use migrations for this because you don't run migrations when setting up your database for the first time, you run db:schema:load. Hence the special file for maintaining seed data: seeds.rb. This just means that if you do need to add data in a migration (in order to get production and everyone's dev data up to speed), and it qualifies as seed data (necessary for the app to run), you need to add it to seeds.rb too!
Neither of these, however, mean that you shouldn't use migrations to migrate the data in existing databases. That is what they are for. You should use them!
A migrations is simply a structured way to make database changes, both schema and data.
In my opinion there are situations in which using migrations for data changes is legitimate.
For example:
If you are holding data which is mostly constant in your database but changes annually, it is fine to make a migration each year to update it. For example, if you list the teams in a soccer league a migration would be a good way to update the current teams in each year.
If you want to mass-alter an attribute of a large table. For example if you had a slug column in your user and the name "some user" would be translated to the slug "some_user" and now you want to change it to "some.user". This is something I'd do with a migration.
Having said that, I wouldn't use a migration to change a single user attribute. If this is something which happens occasionally you should make a dashboard which will allow you to edit this data in the future. Otherwise a rake task may be a good option.
This question is old and I think rails approach changed over time here. Based on https://edgeguides.rubyonrails.org/active_record_migrations.html#migrations-and-seed-data it's OK to feed new columns with data here. To be more precise your migration code should contain also "down" block:
class DisableAccessForUser < ActiveRecord::Migration
def up
User.where(name: "User").first.update_column(:access, false)
end
def down
User.where(name: "User").first.update_column(:access, true)
end
end
If you use seeds.rb to pre-fill data, don't forget to include new column value there, too:
User.find_or_create_by(id: 0, name: 'User', access: false)
If I remember correctly, changing particular records may work, but I'm not sure about that.
In any case, it isn't a good practice, migrations should be user for schema changes only.
For updating one record I would use console. Just type 'rails console' in terminal and input code to change attributes.
I have a need for a certain model to contain a reference to a document. Most of the model could be stored in postgres. The model is for a "level" in a game. I'd like to store the level data itself inside of a document, which makes more sense than making a complex tree in sql.
I am able to use postgres with mongoid installed; however, after installing the mongoid gem I seem to only be able to scaffold mongoid (non active record) documents.
The problem is that I have references to other tables, and I don't neccesarily know how to link that up within a mongoid model.
Questions:
How can I force scaffolding to occur with active record instead of mongoid or vice versa. Edit: partly answered here: Using Active Record generators after Mongoid installation? (2nd answer works, but I don't know how to go back and forth easily)
Is there an easy way to reference a document from an active record model (I know the documentation said don't mix them, but it is ideal for what I am trying to do).
If it is not possible to mix them, then how should I make a document be referenced from a postgres/active record table. In other words how can I get both pieces of data at the same time?
Thanks!
Regarding your first question, the ideal solution would be something along the lines of the first answer in the referenced post. However, instead of a generating a migration, generate a model instead. So when you want an Active Record model simply run:
rails g active_record:model
As for your second and third questions, to associate an Active Record model with a Mongoid document simply store the ObjectId as a string in the model. Then, when you get retrieve a record make a new ObjectId out of the string and use that to query for the related document.
You can create object ids out of the strings like this:
BSON::ObjectId.from_string("object_id_string")
There isn't really an easy way to easily follow intra-orm relations when mixing and matching between ActiveRecord and Mongoid though so I'm afraid that will have to be done via Ruby code.
The models you define in rails either extend one ORM's base class or the other and they don't know about one another. There may be projects out there that act as a layer on top of these ORMs but I am not familiar with any that exist at the moment.
in the application i am currently creating in ruby on rails. I am trying to do some tests in rails console where i have to destroy data in the database and the database is connected to a server. I am importing an XML and parsing it and putting it into a database with scaffolding.
Now what i need: Basically what i am attempting to do is to destroy the data and replace it with a new one every week..but the problem i am getting, the userid is gone up to 700+ and there are only 50 records :S cause it doesnt reset...
To delete all records i am currently using "whatever.destroy_all" does the trick
Any help?
Btw i am using SQLITE
The ID column created in the table usually is set as unique and to increment by 1 for each new record, which is why each time you destroy and add new data the ID keeps getting higher.
The fact that the ID # is getting larger and larger is not an issue at all.
If you really want to start back at zero, I would think you could drop the table and recreate it, but that seems like overkill for a trivial issue.
Regarding the connection to the other scaffold, how are you connecting the two and what do they both represent?
Ideally the data population for testing should be done through fixtures (or easy tools such as factorygirl etc..)
The main advantage of having a fix data set is you can run your tests in any environment. But as per your requirement you can do something like this,
When you populate the date through the active records pass the id parameter as well
Ex: User.new(:id => 1, :name => "sameera").create
By this way you can have constant id's But make sure you increment the id accordingly.
I am creating an application where I need to categorize one of my models. There are five categories and they will not change, at least not for now. The object can only have one category at once. My two ideas are:
Create a whole table for adding the categories and add them in the migration file. I would then store the category id in the db for my object. Read about this causing problems with testing so I'm not sure. And, it seems a bit overkill.
Add a constant hash in my model for hosting the categories. I would then store the int key in my object.
Is there any better way I have not thought about? Are there any plugins for creating enums in rails?
Thanks
I have used this plugin https://github.com/adzap/active_enum some time ago and I think it works OK. You should definitely try it.