In my Rails application development, I would like to write a script to create a new database and a table in the new database (I am using MySQL), so that I can later run the script like following:
rails runner db/scripts/data_mover.rb
But I do not know how to do it in ruby code or Rails way...Anyone can provide some hint or sample?
write the code in a class, and place the file under app/models, such as `app/models/data_mover.rb'
class DataMover
def self.run
ActiveRecord::Base.connection.execute("CREATE DATABASE somedatabase")
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "myuser",
:password => "mypass",
:database => "somedatabase"
)
ActiveRecord::Base.connection.create_table :sometable do |t|
#...
end
end
end
Then you can run rails runner 'DataMover.run' to create databases and tables.
Related
I want Sidekiq to support multiple dynamic databases for the same project
desc "Start sending the client invitation"
task "sidekiq:start", [:database] => :environment do |task, args|
database = args[:database]
config = ActiveRecord::Base.establish_connection(
:adapter => "postgresql",
:host => "localhost",
:username => "postgres",
:password => 12345678,
:database => database
)
puts "Start Running Sidkiq Server for new database instance - #{database}"
system("bundle exec sidekiq -d -L log/sidekiq.log -P tmp/pids/#{database}_sidekiq.pid")
puts "Finished Running Sidkiq Server for new database instance - #{database}"
puts "Finished connecting the client sidkiq"
end
rake sidekiq:start[hellodb]
Is there anything within sidekiq to pass database configuration dynamically ?
It's always taking the database configuration from database.yml, even I used this establish_connection method. I want it to support database configurations dynamically.
Basically, I am using multiple databases in my project depending on the sub domains. There, I am using same project but using multiple databases dynamically. So, I am looking for some ability that may allow using multiple sidekiq instances for different databases.
config = ActiveRecord::Base.establish_connection(
:adapter => "postgresql",
:host => "localhost",
:username => "postgres",
:password => 12345678,
:database => database
)
I will appreciate views on the same :)
am trying to use ActiveRecord without Rails, to create a gem that connects to a MySql database. The connection to the database should be settable, because the gem is intended mainly for console use, so I don't want to provide the database connection information beforehand in a YAML file, but provide it "on-the-fly". This seems to bring a lot of problems, since the ActiveRecord models are loading the database information on initialisation. Is there any other way of sharing the database information or some way to make active_record not preload the database configurations? Is there maybe a better way to share connection information than "establish_connection"?
here is my code:
class Blog
##options = { :adapter => "mysql2" }
def self.options
##options
end
def initialize(options = Hash.new)
##options = {
:adapter => "mysql2",
:host => options[:host] || "localhost",
:username => options[:user] || "root",
:password => options[:pass] || "",
:database => options[:db] || "my_blog"
}
end
end
module Foobar
class Post < ActiveRecord::Base
establish_connection(Blog.options)
end
end
on the command line
Blog.new(user:"foo",pass:"bar",db:"bang")
p=Foobar::Post.all
You should just call ActiveRecord::Base.establish_connection(...).
class Blog
# No need to use initializer method if you don't intend
# to use initialized instance. Static method will do better.
def self.connect(options = Hash.new)
ActiveRecord::Base.establish_connection(
adapter: "mysql2",
host: options[:host] || "localhost",
username: options[:user] || "root",
password: options[:pass] || "",
database: options[:db] || "my_blog"
)
end
end
module Foobar
class Post < ActiveRecord::Base
# Connection is done via Blog model
end
end
Blog.connect(username: 'john', password: 'qwerty')
posts = Foobar::Post.all
A colleague and I are working in different projects that share some models. So, we are sharing the models through a git submodule.
Additionally, we'd like to be able to also share migrations:
In this way, my colleague's migrations would be in the folder db/migrate/other_db of my project.
How can I configure rails migrations to also run the migrations in this extra folder?
In your config file (config/application.rb for all environments or config/environments/$(environment).rb only for particular environment) add this line:
config.paths['db/migrate'] += 'db/migrate/other_db'
And if you want to change default 'db/migrate' path (config.paths['db/migrate'] is an array with one string 'db/migrate' by default), do this:
config.paths['db/migrate'] = ['db/my_migrate']
Here are default config.paths, which we also can change:
"app" => ["app"],
"app/assets" => ["app/assets"],
"app/controllers" => ["app/controllers"],
"app/helpers" => ["app/helpers"],
"app/models" => ["app/models"],
"app/mailers" => ["app/mailers"],
"app/views" => ["app/views"],
"lib" => ["lib"],
"lib/assets" => ["lib/assets"],
"lib/tasks" => ["lib/tasks"],
"config" => ["config"],
"config/environments" => ["config/environments"],
"config/initializers" => ["config/initializers"],
"config/locales" => ["config/locales"],
"config/routes" => ["config/routes.rb"],
"db" => ["db"],
"db/migrate" => ["db/migrate"],
"db/seeds" => ["db/seeds.rb"],
"vendor" => ["vendor"],
"vendor/assets" => ["vendor/assets"],
"vendor/plugins" => ["vendor/plugins"],
"config/database" => ["config/database.yml"],
"config/environment" => ["config/environment.rb"],
"lib/templates" => ["lib/templates"],
"log" => ["log/development.log"],
"public" => ["public"],
"public/javascripts" => ["public/javascripts"],
"public/stylesheets" => ["public/stylesheets"],
"tmp" => ["tmp"],
Update for Rails 5/6;
Rails 5 recommends setting additional migration paths in your config/database.yml file. It's very easy, see this example;
development:
migrations_paths:
- "db/migrate/other_db"
- "db/migrate/something_else"
ActiveRecord::Migrator.migrations_path= will be deprecated in Rails 6.
based on the answer by Swanand, we can write a migration to load the migrations in an external dir:
class MigrateMetadata < ActiveRecord::Migration
MIGRATIONS_PATH='db/migrate/metadata'
def self.up
Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].
sort.map{|filename|require filename}.flatten.
each{|class_name| const_get(class_name).up}
end
def self.down
Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].sort.reverse.
map{|filename|require filename}.flatten.
each{|class_name| const_get(class_name).down}
end
end
By the way, if you are building a gem to work with Rails, you can place a block like the following in your rail tie to add the gem's own migrations.
root = ... # the path to your gem
initializer :append_migrations do |app|
unless app.root.to_s.match root
app.config.paths["db/migrate"] << File.join(root, 'db/migrate')
end
end
There is no need to copy migrations from your gem with generators if you use this technique.
You can make a method to yield the root directory of your gem with some thing like this...
module MyGemName
def root
File.expand_path '../..', __FILE__
end
module_method :root
end
... in the file lib/my_gem_name.rb in your gem.
I do not know of a very clean way to do it, but the code that runs migrations looks something like:
#migrations ||= begin
files = Dir["#{#migrations_path}/[0-9]*_*.rb"]
migrations = files.inject([]) do |klasses, file|
version, name = file.scan(/([0-9]+)_([_a-z0-9]*).rb/).first
Where,
#migrations_path = 'db/migrate'
So if you change this to read from config file instead, it may work out in your favour. But as I said, this is definitely not a very clean way to do it.
Just add this initializer to your lib/engine.rb:
initializer 'your_engine_name.migrations' do |app|
config.paths['db/migrate'].expanded.each do |expanded_path|
app.config.paths['db/migrate'] << expanded_path
ActiveRecord::Migrator.migrations_paths << expanded_path
if Rake.application.top_level_tasks.empty?
ActiveRecord::Migration.check_pending! if ActiveRecord::Migrator.needs_migration?
end
end
end
I have a MySQL table and I want to pick certain columns to create RSS Feed from it. How to do it using Ruby or Rails or Gems?
Depending on what I was trying to do, I would probably just go for a simple Ruby script. I would use ActiveRecord so I didn't have to write any SQL. Then I would use either Builder or RubyRSS to generate the feed.
Connecting ActiveRecord to a MySQL server directly is as simple as:
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "myusername",
:password => "mypassword",
:database => "mydb"
)
Then you are free to define ActiveRecord models like you would in a regular Rails app.
There are RSS generator examples on the RubyRSS website and a Builder one on the Railscasts website.
Hernan is right...here is are the full steps you'll need to get data from the database (I moved the code to below the steps for easier formatting:
Install ActiveRecord: sudo gem install activerecord
Establish the connection per hernan43's recommendation (preferrably in a separate file, let's call it "connection.rb"
Create a class that uses that connection by inheriting from ActiveRecord
Retrieve record(s) from the table, and use it/them to populate your RSS generator
You don't have to separate everything out into a file...you could put everything below in one file, and remove the 'requires' in files 2 and 3, but it's a convention to separate out your concerns in a manner similar to what I've done.
#1: file connection.rb
require 'rubygems'
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:database => "appdb",
:username => "appuser",
:password => "secret"
)
#2 filename: singural_rss_table_name.rb
require 'connection'
class SingularRSSTableName < ActiveRecord::Base
set_table_name 'real_database_table_name' #if the table name is the lowercase, underscore plural of the class name, then you don't need this line.
end
#3 filename: rss_creator_file.rb
require 'singular_rss_table_name'
# Here you retrieve the rows from your database table,
# based on the condition that the column 'title' is exactly the text 'article_title'
# there are a lot more options for
# conditions in ActiveRecord, and you'll probably want to look them up.
records_for_rss_entries = SingularRssTableName.find(:all, :conditions => {:title => 'article_title'})
rss_object = RSS::Maker.new(version) do |feed|
feed.channel.title = "Example Ruby RSS feed"
records_for_rss_entries.each do |entry_record| # here we're iterating through
# each of the rows we found.
entry = feed.items.new_item
entry.title = entry_record.title # at this point, each 'entry_record' is a row in your db table
# use the dot (.) operator to access columns in the table.
...
end
end
The contents of this answer were partially answered from:
http://rubyrss.com/
and
http://www.agileadvisor.com/2008/01/using-activerecord-outside-rails.html
I need to run a ruby-script as a service. The script needs access to the ActiveRecords of a rails-app.
What would be the best way? A rake task? How can it be started as a service on both windows and linux?
This Stackoverflow thread seems to have a good answer on how to run Ruby as a service on windows: Running a Ruby Program as a Windows Service?
And here is how to instantiate ActiveRecord outside of rails: http://www.juixe.com/techknow/index.php/2009/01/14/activerecord-ruby-on-rails-optional/
If you want to use the same models as your Rails application, you can require them.
Here's an example in console:
irb(main):001:0> require 'ActiveRecord'
=> true
irb(main):002:0> ActiveRecord::Base.establish_connection(
irb(main):003:1* :adapter => 'mysql',
irb(main):004:1* :database => 'development',
irb(main):005:1* :username => 'root',
irb(main):006:1* :password => '',
irb(main):007:1* :host => 'localhost'
irb(main):008:1> )
=> #<ActiveRecord::ConnectionAdapters::ConnectionPool:0x59613
irb(main):009:0> require 'app/models/User.rb'
=> ["User"]
irb(main):010:0> User.find(1)
=> #<User id: 1, first_name: "Michael">
Good luck!
I would say maybe a Sinatra app might be the way to go if it's just one script as a service.
I'll go with a custom daemon