How to rename a database using MongoMapper in ruby? - ruby-on-rails

I am trying to rename a database using MongoMapper in ruby.
Is it possible to do the same?
any alternative hack to accomplish the same?

As noted in the other stack overflow question mentioned above, MongoDB doesn't actually have the ability to rename a database. You can however, copy then delete but be aware this will cause indexes to be rebuilt. You wouldn't want to do this for a large data set.
The mongo-ruby-driver (as well as most 10gen drivers) has the ability to execute any MongoDB command through a call to the DB#command method on any DB object instance.
In the Ruby driver you would do the following:
require 'mongo'
client = Mongo::MongoClient.new
db = client.db('admin')
db.command({:copydb => 1, :fromdb => oldname, :todb => newname})
client.drop_database(oldname)
Update: In newer versions of MongoDB there is a JS shell helper for db.rename() which does exactly what the ruby code above does.
function (newName) {
if(newName == this.getName() || newName.length === 0)
return;
this.copyDatabase(this.getName(), newName, "localhost");
this.dropDatabase();
db = this.getSiblingDB(newName);
}
In addition to that, there is the following feature request ticket for making db.rename() a first class command. Please feel free to upvote this feature.
https://jira.mongodb.org/browse/SERVER-701

Related

How can I verify that an ActiveStorage blob is actually present?

I've got an application that's been running in production for many months now, with tens of thousands of attachments. This morning, I tried to do an operation on one of these attachments, and got the following error:
Azure::Core::Http::HTTPError: BlobNotFound (404): The specified blob does not exist.
I can easily recreate this blob, but this situation makes me want to write a script to check the integrity of all of my attachments, and verify that no others have gone missing. (I expect that this was a transitory network error, and I expect to find very few, but I need the peace of mind.)
I can see that there is a method to call that seems to do exactly what I need: exist?(key), which is documented here:
https://github.com/rails/rails/blob/master/activestorage/lib/active_storage/service/disk_service.rb
However, I can't figure out how I'm supposed to call it. According to this, it's implemented as an instance method. So how do I reference my Rails application's active ActiveStorage instance (depending on environment) to use this method?
I wondered if it were possible to backtrack to get the instance of ActiveStorage::Service::AzureStorageService (in production), and found this answer on finding each instance of a class.
From there, I found that I could:
asass = ObjectSpace.each_object(ActiveStorage::Service::AzureStorageService).first
Which then allowed me to:
2.5.5 :015 > asass.exist?(c.json.blob.key)
AzureStorage Storage (313.3ms) Checked if file exists at key: ....PTLWNbEFLgeB8Y5x.... (yes)
=> true
Further digging around in the bowels of Rails' GitHub issues led me to see that the reference to the ActiveStorage service instance can be reached through an instance of a stored object, and that I could always be using the send() method to call one of its methods:
2.5.5 :045 > c.json.blob.service.send(:exist?, c.json.blob.key)
AzureStorage Storage (372.4ms) Checked if file exists at key: ....PTLWNbEFLgeB8Y5x.... (yes)
=> true
I'm sure both approaches are lighting up the same code paths, but I'm not sure which one I prefer at the moment. I still think there must exist some way to traverse the Rails instance through app. or Rails.application. to get to the ActiveStorage instance, but I haven't been able to suss that out.

How can I edit existing activerecord objects in a sql database using ruby scripts?

How can activerecord objects be edited externally with scripts? I'm currently using the activerecord-import gem to insert objects into the database. Is it possible to edit existing records using this gem or using another tool or gem?
That's a bit unspecific. There are quite a few methods. Here's the best:
You can run rails on the console. Try irb in your project's directory, and you're on a REPL that allows you to run code live. Just try something like:
that_guy = User.find(4)
that_guy.name = "John"
that_guy.save!
(Replace User, 4 and name with a model you have, a record's id and some string attribute).
And of course you can also just run a file of ruby against your project: rails runner your_script.rb
And, if I misunderstood you: you can of course access the database through any other means/languages/libraries.

Accessing a database through Rails model from a seperate Ruby script

I have a Rails application with a database (PostgreSQL using ActiveRecord)
In a separate directory on the same server I have a Ruby script.
How can I, from the Ruby script, reach the Rails database through one of my Rails models?
I have seen that it is possible to require ActiveRecord and pass in the database details, but from what I understand I would need to rebuild the model, which means a lot of repetition of validations, methods, etc. Instead I'd like to somehow use the model that's already in place.
I found a solution that has the behaviour I was looking for, and am posting it as an answer for anyone who comes across this question at a later date.
Setting ENV['RAILS_ENV'] = "production" and then simply requiring the environment.rb file (with the appropriate path) in the Ruby script solves the issue very nicely.
This is similar to the answer provided by #MurifoX, but saves you having to re-declare the DB connection.
Try using rails runner. According to: http://guides.rubyonrails.org/command_line.html#rails-runner
runner runs Ruby code in the context of Rails non-interactively. For
instance:
bin/rails runner "Model.long_running_method"
In my experience this works nicely to run scripts that rely on Active Record and more.
Add the -e switch to the command to force the use of your production database connection:
bin/rails runner -e staging "Model.long_running_method"
Add any other environment variables that may be required to complete the database connection. If you use the Devise gem, you will also need to pass in a secret to allow the Devise initializations to complete. Other gems may equally need some assistance to get started.
You can use require to pass the relative path to your model, and then instatiate it a use.
require '/path/to/your/model/inside/your/app'
model = Model.new
For the connection, if you are using postgresql, you can use the PGconn class from the pg gem like this:
#connection = PGconn.open(
:user => 'postgres',
:password => 'password',
:host => 'host',
:dbname => 'dbname')

How to query MongoDB directly from Ruby instead of using Mongoid?

I am writing a migration for a Rails application that uses MongoDB and Mongoid. My migration currently uses my models that use Mongoid to query and update records, but the performance is sub-par. I am essentially updating all records in a large collection and making n+20 queries. I killed the migration after taking an hour to run locally (and didn't finish). I would like to be able to run raw queries to mongo without too much effort. I'm assuming there is some way to access a mongo driver from Mongoid since Mongoid has already loaded a connection to the database. How can I access the database to run my update queries direcly?
If you're using Mongoid 3, it provides easy access to its MongoDB driver: Moped. Here's an example of accessing some raw data without using Models to access the data:
db = Mongoid::Sessions.default
# inserting a new document
collection = db[:collection_name]
collection.insert(name: 'my new document')
# finding a document
doc = collection.find(name: 'my new document').first
# iterating over all documents in a collection
collection.find.each do |document|
puts document.inspect
end
For Mongoid 5:
db = Mongoid::Clients.default
collection = db[:collection_name]
Now we can perform queries on the collection
Here how you do it (This would work for 2+ and 3+ as well)
1) All your Model exhibit this behavior you have include Mongoid::Document inside all your model so technically each document is mapped in monogodb thru moped or mongodb-ruby driver via mongoid
so If you have model Like
class PerformerSource
include Mongoid::Document
## Definition
end
Now you can run Mongo Query using the driver (Moped or Mongodb-ruby driver) like this
PerformerSource.collection.insert("something")
## where something is json document you want to insert
This would give u the moped (if using mongoid 3) connection for that document
2) You can also do it something like this
Mongoid::Sessions.default.collections.find { |document| document.name == "performer_sources"}.insert("something")
How to more on mongo query and how mongoid map those using moped u can follow this section of querying where it describe how query is acheived internally via moped
Hope this help
For Mongoid 6:
db = Mongoid::default_client
collection = db[:collection_name]
The short answer is Moped. This is the lower-level API that Mongoid is built upon and will be available if you already use Mongoid. The Moped API is a thin wrapper around the raw MongoDB operations. The documentation here: http://mongoid.org/en/moped/docs/driver.html should be useful.
Like anyone has mentioned here, your answer is Moped.
Here is my example for a ruby script (simple file test.rb)
Define a mongoid.yml (in this case, at localhost)
development:
sessions:
default:
database: test_development
hosts:
- localhost:27017
options:
Set load config and test collection
#!/usr/bin/env ruby
require 'mongoid'
Mongoid.load!("path/to/file/mongoid.yml",:development) # :development corresponds to mongoid.yml first line environment
db = Mongoid::Sessions.default
puts "Collection documents count :> #{db[:collection].find.count}"
If you using mongoid 5(five) I would recommend using this.
Item.collection.update_one({_id: BSON::ObjectId('55512b7070722d22d3050000')}, '$set' => { 'category_name': 'Test' })
The trick to this is the BSON::ObjectID. This is like in the mongo query if you want to search for a single id.
db.items.update({ '_id': ObjectId("55512b7070722d22d3050000") }, { $set: {'category_name': 'Test' } })
Above is the mongo version of the query. I found translating ruby code to mongo code is the hard part as there are a few pieces that can be a bit hard to find in the documentation.
http://www.rubydoc.info/gems/mongo/Mongo%2FCollection%3Aupdate_one

mysql2 driver seems to write invalid queries

I'm developing an application layer on top of a rails app developed by someone else.
His application uses a module called request_logger to write to a table, which worked fine under ruby1.8/rails2/mysql gem, but in my ruby1.9/rails3/mysql2 environment, activerecord falls over, suggesting that the generated query is invalid.
It obviously is, all mysql relation names are wrapped in double quotes instead of backticks.
The call to activerecord itself just sets a bunch of attributes with
log.attributes = {
:user_id => user_id,
:controller => controller,
...etc
}
and then calls
log.save
So I'm leaning towards it not being dodgy invocation. Any suggestions?
mysql2 works fine for a lot of people, but it unashamedly sacrifices conformance to the MySQL C API for performance in the common tasks. Perhaps, if request_logger is low-level enough, it's expecting calls to exist which don't.
It's trivial to switch back to using mysql - give it a try, and if it works, stick with it. Remember to change both your Gemfile and your config/database.yml settings.
It turned out to be what seems to be a change in behaviour between rails 2 and 3 (we have the same setup working fine in rails 2)
We use database.yml to specify an (empty) "master" database and then feed in our clients with shards+octopus.
The master db is sqlite for simplicity, and it seems that activerecord was feeding off requests formatted for sqlite to the mysql2 shards, regardless of their adaptor type.

Resources