Is there an easy 'command line/console' way of checking if a Rails app is connecting properly to MySQL?
Unfortunately, I can't get a Rails console to come up. It complains about:
/home/nexargi/www/gi/vendor/ruby/1.9.1/gems/activerecord-3.2.1/lib
/active_record/dynamic_matchers.rb:50:in `method_missing': undefined
local variable or method `abddadhocbkgid' for #<Class:0x000000036427f8> (NameError)
from /home/nexargi/www/gi/app/models/adhoc_bkg_diners_diet.rb:5:in
`<class:AdhocBkgDinersDiet>'.
The 'abddadhocbkid' is the first attribute of the first table and therefore I am thinking that it is not managing to connect to the mysql database. I need to find a way of checking if Rails can connect to the mysql database without logging into the rails console.
Here is my model code:
class AdhocBkgDinersDiet < ActiveRecord::Base
validates_presence_of :abddadhocbkgid, :abddmealdietid, :abddadultnos, :abddchildnos
validates_numericality_of :abddadultnos, :abddchildnos, greater_than_or_equal_to: 0
belongs_to :adhoc_bkg, foreign_key:abddadhocbkgid
belongs_to :meal_diet, foreign_key: :abddmealdietid
end
If you just need to check if your connection is active after it has been established, there is the ActiveRecord::Base.connected? method.
You can try connecting directly using console:
ActiveRecord::Base.establish_connection(
Rails.configuration.database_configuration[Rails.env]
)
Or if you have a model you can try finding one:
SomeModel.first
Related
I wrote a migration with the following (create new table named sources):
class CreateSources < ActiveRecord::Migration
def change
create_table :sources do |t|
t.string :name, null: false, default: ""
t.timestamps null: false
end
end
end
And then I modified my existing model :
class Property < ActiveRecord::Base
validates :source, allow_blank: true, inclusion: { in:
Source.all.map{ |source| source.name } }
I want to add validation to the property's source to only allow source from sources table.
And then when I run the migration, I got the following error:
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'sources' doesn't exist: SELECT `sources`.* FROM `sources`
The problem is query of source table is occured when it hasn't been initialized yet.
Any tips on how I can get the migration to run?
This is run on production level. so I might can't drop all the migration and rearrange it.
Rails version 4.2.5
SQL version 5.7
Keep in mind that your Source.all.map{ |source| source.name } is going to be executed when the Property class is being loaded. The Source class might not be properly initialized at that point and there might not be a proper database connection set up. Also, you'll only access Source.all once so you'd have to restart your app if you added a new Source.
Instead, validate by hand:
class Property < ActiveRecord::Base
validate :valid_source
private
def valid_source
return if(source.blank?)
return if(Source.where(name: source).exists?)
errors.add(:source, 'Unknown source') # Or whatever you want to say
end
end
That way you're checking the sources table at the right time.
Also, I wouldn't expect the error you're seeing to occur in a migration. Perhaps you're using a model inside a migration, that is to be avoided.
As an aside, is there particular reason that you don't have belongs_to :source instead? Copying the name around like that is very error prone, using a reference (hopefully backed by a foreign key in the database) would be much safer.
Have you defined Source model? I hope so.
Here the problem looks like the loading of Property class takes priority before
migration is run and hence the issue.
I am building an rails 5 app that connects to 2 different databases (dbA & dbB). My databases are on the same database host.
I want to make a wishlist. Pretty easy when using the same DB, but I am stuck with an "interesting" error.
This is what the databases look like:
the models are as follow:
user.rb
class User < ApplicationRecord
has_one :wishlist, dependent: :destroy
end
wishlist.rb
class Wishlist < ApplicationRecord
belongs_to :user
# has_and_belongs_to_many :wines
# The above did not work
# so I had to revert to has_many through
has_many :wines_wishlists
has_many :wines, through: :wines_wishlists
end
wines_wishlist.rb
class WinesWishlist < ApplicationRecord
belongs_to :wine
belongs_to :wishlist
def self.table_name_prefix
"dbA_#{Rails.env}."
end
# I added the above to prevent ActiveRecord from
# looking for the table in the wrong database
end
wine.rb (legacy model)
class Wine < ApplicationRecord
self.abstract_class = true
establish_connection LEGACY_DB
# LEGACY_DB is the legacy database connection info from a yaml file
# located in config.
def self.table_name_prefix
"dbB_#{Rails.env}."
end
end
This is quite straigth forward IMHO. Now the interresting error:
When I try the following :
user = User.last
user.wishlist.wines
It works on my local machine in development. It doesn't work on my staging server! When I try in the rails console, I get this:
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'dbA_staging.wines_wishlists' doesn't exist: SELECT `dbB_staging`.`wines`.* FROM `dbB_staging`.`wines` INNER JOIN `dbA_staging`.`wines_wishlists` ON `dbB_staging`.`wines`.`id` = `dbA_staging`.`wines_wishlists`.`wine_id` WHERE `dbA_staging`.`wines_wishlists`.`wishlist_id` = 1
This is the expected SQL.
user.wishlist.wines.to_sql
=> "SELECT `dbB_staging`.`wines`.* FROM `dbB_staging`.`wines` INNER JOIN `dbA_staging`.`wines_wishlists` ON `dbB_staging`.`wines`.`id` = `dbA_staging`.`wines_wishlists`.`wine_id` WHERE `dbA_staging`.`wines_wishlists`.`wishlist_id` = 1"
Even better, when I try the same SQL in rails db on my staging machine, it works!! It doesn't work in rails even though the SQL is correct, but it works in mysql command line.
I based my code on the following article and made some research, but I can't seem to figure out how to go around this problem.
I am using (same for development and staging):
Rails 5.1.1
ruby 2.4.0p0
mysql 5.6.34 (staging)
mysql 5.7.17 (development)
Any help would be greatly appreciated!
Taking a look at the article you linked to, it seems to be using a gem st-elsewhere, i.e.
has_many_elsewhere :wines, :through => :wines_wishlist
Also, as stated in the article, you can't make JOIN queries across database connections. The gem circumvents this using some less efficient queries, the details of which I did not look up.
For the reason, I've used mysql cmd insert into table_name (....) update custom_reports ...and hence I miss out on Model validations
validates_uniqueness_of :name
validates_presence_of :name, :description
How to validate now in rails way? Or, use the mysql way to validate(needs help in this way too)?
Rails validation and other ActiveRecord and ActiveModel magic don't work if you only execute custom SQL command. None of your model classes is even instantized then.
For Mysql (or any sql like DB), you can modify the column attribute to:
Unique (this would validate uniqueness)
Not null (this would validate presence)
I know doing the above with OCI8 and oracle would result in exceptions which I am guessing should be same with ActiveRecord and Mysql, so you should be handling your exceptions correctly
But as #Marek as said you should be relying on Active record and be doing things like
Model.create()
OR
model_instance.save()
If you want to find (and perhaps handle) the entries in your db that are not valid, try the following in the rails console:
ModelName.find_each do |item|
unless item.valid?
puts "Item ##{item.id} is invalid"
# code to fix the problem...
end
end
valid? runs the Validations again, but does not alter the data.
Currently I am developing an rails project to connect the database from salesforce.com with our SQL server. Atm we use the gems 'mysql2' for the sql part and 'databasedotcom'
+ 'databasedotcom-rails' for the salesforce part.
Our problem ist, that we have the same names for the tables in both databases. So both adapter try to encapsulate them into activerecord classes and as you guess, its a big problem. Unfortunately we found no solution in the internet.
So how can I prevent the namespaceconfict?
I may not be understanding the question but I think the following would work for you.
class Account < ActiveRecord::Base
# table name is 'accounts' in mysql db
end
class SalesForceAccount < ActiveRecord::Base
establish_connection "#{Rails.env}_salesforce"
table_name = :accounts
end
With a database.yml of
development:
# your mysql credentials and adapter info
development_salesforce:
# your salesforce credentials and adapter info
To solve the problem with the conflicting namespaces, we put the module for mysql in his own namespace.
the databasedotcom gem create the models on runtime, so you just have to create models for your mysql db.
create modeles for sql
create folder named after your wished prefix in models folder (for us: Mad)
put your models in the namespacee-folder (for us: Mad)
wrap the model classes in module <namespace>
like account.rb:
module Mad
class Account < ActiveRecord::Base
attr_accessible :name, :website, :phone
end
end
now you can access the Accounts for salesforce via Account and the mysql with Mad::Account
please an example for use multiple data bases for my app in rails, i need create and save only one table internal and external, no all database so any idea or example explicit please??
i use mysql, the replication i dont like because is for all database and i need use only one table external.
tnks!
If I'm interpreting your question correctly, you want to know how to use a different database for one or more models in your app.
You can do this quite simply in Rails. First, you'll have to create another entry in your config/database.yml file:
production:
....
development:
...
test:
...
# Our external database
external:
adapter: mysql
host: some_host
username: some_username
password: some_password
database: some_db
Then, in your model, simply tell Rails that for this particular model, use a different connection:
class MyModel < ActiveRecord::Base
establish_connection :external
end
This will send any queries for MyModel to the external database, while all other models will use the production/development database as usual.
Please note that when you're using two different databases together, MySQL itself will not let you perform certain functions, such as joins. Otherwise, you should be fine with this approach.
well my solution is the next with help vonconrad post.
database.yml
like of vonoconrad post
MyModelconn.rb
class MyModelconnection < ActiveRecord::Base
# No corresponding table in the DB.
self.abstract_class = true
# Open a connection to the appropriate database depending
# on what RAILS_ENV is set to.
establish_connection(:connyml)
end
class User < ActiveRecord::Base
end
In users_controller.rb where i need insert into in external table with data values where i save in my Active Record of usres internal so an external swicht conection next line:
MyModelconn.connection.execute('INSERT INTO 'users' (fileld1,filed2)VALUES('#{lcfield1}','#{lcfield2}')')
and BINGO! workiT! perfect!
So dont need you again swicht back AR internal.