500 Error in production adapter rails when starting new user session - mysql

I have been having this issue ever since I deployed and i can't figure it out.
I'll give some information and let me know if you need anything else! Thanks!
I, [2013-09-08T12:44:31.935143 #19456] INFO -- : Started POST "/sessions" for {IP ADDRESS} at 2013-09-08 12:44:31 -0700
I, [2013-09-08T12:44:31.937969 #19456] INFO -- : Processing by SessionsController#create as HTML
I, [2013-09-08T12:44:31.938102 #19456] INFO -- : Parameters: {"utf8"=>"✓", "authenticity_token"=>"{AUTHENTICITY TOKEN}", "email"=>"mike#test.com", "password"=>"[FILTERED]", "commit"=>"Log In"}
I, [2013-09-08T12:44:31.941064 #19456] INFO -- : Completed 500 Internal Server Error in 3ms
F, [2013-09-08T12:44:31.943631 #19456] FATAL -- :
ActiveRecord::StatementInvalid (Could not find table 'users'):
app/controllers/sessions_controller.rb:6:in `create'
Obviously it's telling me that the "users" table doesn't exist, but that BS, because it does. Perhaps it can't find the table? Which i ALSO think is wierd, because I created the table using Rails migrations.
Here is my production Adapter just for reference:
production:
adapter: mysql
database: {DATABASENAME}
username: {USERNAME}
password: {PASSWORD}
host: localhost
port: 3306
Here is my seeds file:
User.create([{ email: 'mike#test2.com' }, { password_digest: 'password' }])
And my user model:
class User < ActiveRecord::Base
has_secure_password
validates_uniqueness_of :email
end
And my sessions controller (handles the login):
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_url, notice: "Logged in!"
else
flash.now.alert = "Email or password is invalid"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, notice: "Logged out!"
end
end
I created the user directly in the database, so the issue isn't that the user doesnt exist, the log file is saying the table 'users' doesnt exist, but that is false as well...i really don't know whats going on...
OH, BTW this all works in development. Login, user creation, everything. I was using sqlite3 for development and switched to mysql for production, just screwed everything up....
Any help is appreciated!

For future reference, this is the fix if anyone else is having an issue with their seeds not working:
This is what I was using:
User.create([{ email: 'mike#test2.com' }, { password_digest: 'password' }])
This is what it should be:
users =User.create!(:email 'mike#test2.com', :password 'password', :password_confirmation 'password')
users.save
Using
Create!
instead of just plain
Create
enables validation, and the seed will fail and explain the problem. In my case, it was that I was using password_digest, which is the column name, instead of password and password_confirmation.
Also, save the seed creation in a variable (users in my case), then save said variable by doing this:
users.save
Simple as that!
Hope this helps a fellow newbie in the future!

Related

make queries on multiple db in same action controller with transaction rails?

I have in my database.yml :
default: &default
[...]
development_1:
<<: *default
database: dev1
development_2:
<<: *default
database: dev2
I need to make many queries in foo action but using these 2 DB :
class UsersController < ApplicationController
def foo
users_nb = User.count #this use my default db : dev1
other_connexion = ActiveRecord::Base.establish_connection("#{Rails.env}_2").connection
users_nb_other_site = connexion.execute("SELECT COUNT(*) FROM users").first[0]
end
end
that works, BUT I encapsulate all action controller in transaction like :
ActiveRecord::Base.transaction do
begin
yield
rescue Exception => e
raise ActiveRecord::Rollback
end
with this, my previous code doesn't works, it raise an error :
ActiveRecord::StatementInvalid in UsersController#foo NoMethodError:
undefined method `query' for nil:NilClass Did you mean? to_query:
ROLLBACK
the line of error is : ActiveRecord::Base.transaction do
So how can I do to make my connexion and queries on another db in same time that my principal db?
Ok, my problem was I don't understand ActiveRecord::Base.establish_connection overwrite my first connexion and the transaction too.
I create an abstract class like said here : https://makandracards.com/makandra/10169-when-connecting-to-a-second-database-take-care-not-to-overwrite-existing-connections
class ReadDatabaseConnection < ActiveRecord::Base
def self.abstract_class?
true # So it gets its own connection
end
end
ReadDatabaseConnection.establish_connection(slave_settings)
I keep my 2 connexion like that, without pb !

Running Stored procedure giving error can't return a result set in the given context

I know this problem has been asked many times. But I tried the solutions and they didn't work for me. I have a web application built on rails 3.2.12 and ruby 1.9.2p180. I have a stored procedure in it which returns me data of a query having 5 inner joins. Multiple rows approximately 600 are returned in present case. On the local the stored procedure runs fine with no issues. But when I tried it on the server it is throwing:
ActiveRecord::StatementInvalid: Mysql2::Error: PROCEDURE test.sp_procedure can't return a result set in the given context: call sp_procedure('2015-02-14 00:00:00 -0500', '2015-03-03 23:59:00 -0500', 5, '13')
I have searched for this issue and found that I need to set CLIENT_MULTI_RESULTS flag when establishing connection to MySQL server. For this I have done monkey patching as said. Here is the file in initializers:
module ActiveRecord
class Base
def self.mysql2_connection(config)
config[:username] = 'deploy' if config[:username].nil?
if Mysql2::Client.const_defined? :FOUND_ROWS
config[:flags] = config[:flags] ? config[:flags] | Mysql2::Client::FOUND_ROWS : Mysql2::Client::FOUND_ROWS
end
client = Mysql2::Client.new(config.symbolize_keys)
options = [config[:host], config[:username], config[:password], config[:database], config[:port], config[:socket], 0]
ConnectionAdapters::Mysql2Adapter.new(client, logger, options, config)
end
def self.select_sp(sql, name = nil)
connection = ActiveRecord::Base.connection
begin
connection.select_all(sql, name)
rescue NoMethodError
ensure
connection.reconnect! unless connection.active?
end
end
end
end
In my database.yml I have added: flags: <%= 65536 | 131072 %> and also tried with flags: 131072. But it didn't work.
However using the following works:
client = Mysql2::Client.new(:host => "localhost", :username => "root", :flags => Mysql2::Client::MULTI_STATEMENTS )
result = client.query( 'CALL sp_procedure('2015-02-14 00:00:00 -0500', '2015-03-03 23:59:00 -0500', 5, '13')')
This worked on the server too. But each time the stored procedure will run it will create a new connection which I don't want.
And also one thing to note while I am doing this on local as soon as I call the stored procedure I have to execute this:
ActiveRecord::Base.connection.reconnect!
If I don't write this it throws an error:
ActiveRecord::StatementInvalid: Mysql2::Error: Commands out of sync; you can't run this command now
So this is also the same thing means it creates a new connection each time. So I am finding for a solution which saves me from doing this.
And if the monkey patching is correct then what am I missing. Please help.

Rails 4.1.1 Postgres app with Mysql Legacy database Import

I've been building a rails app using a postgres database but of course I also have been tasked with importing data from a legacy mysql database.
The way I've been handling this so far:
# config/database.yml
development:
adapter: postgresql
encoding: unicode
database: myapp_development
pool: 10
username: myuser
password:
legacy_development:
adapter: mysql2
encoding: utf8
reconnect: false
database: myapp_legacy
pool: 10
username: myuser
password:
socket: /tmp/mysql.sock
# app/models/legacy.rb
class Legacy < ActiveRecord::Base
self.abstract_class = true
establish_connection "legacy_#{Rails.env}".to_sym
def self.import
self.find_each do |object|
imported_model = object.class.model.new object.attribute_map
object.report_failures unless imported_model.save
end
end
def self.import_all
Rails.application.eager_load!
self.subclasses.each {|subclass| subclass.import }
end
end
# app/models/legacy/chapter.rb
# a bunch of different subclasses like this
class Legacy::Chapter < Legacy
self.table_name = 'chapters'
def self.model
'Chapter'.constantize
end
def attribute_map
{
id: id,
name: name,
body: chapterBody
}
end
end
Then I have a rake task that runs Legacy.import_all. A lot of this was stolen from this post.
There's a few things wrong with this:
The main problem is, when i run Legacy.import_all it makes it through about half of the tables then I get an error like:
NoMethodError: undefined method 'import' for Legacy::SomeSubclass(Table doesn't exist):Class
I think this is because we just have too many connections in the pool. It seems though like it is looking for the SomeSubClass table_name from within the postgres database, but it should be looking on the mysql database.
This is probably because of the methods like:
def self.model
'Chapter'.constantize
end
in the above subclass. I am doing it like that instead of:
def self.model
Chapter
end
because I have a normal model (non-legacy) in my app also called Chapter and I was running into scoping issues there as well.
Anyways this is a huge mess and any thoughts about where I should dig would be greatly appreciated.
Thanks
Can you try prefixing subclass.import with ::
def self.import_all
Rails.application.eager_load!
self.subclasses.each {|subclass| ::subclass.import }
end

How to make a model point to non-default schema

I've searched all over and I can't find anything related to this.
Basically I have the default schema set to abc
In abc I have some tables, etc ...............
I want to make a model that uses table mobile_activity_logs in schema def
The default rails model looks like this:
class MobileActivityLogs < ActiveRecord::Base
# attr_accessible :title, :body
end
but the query is on abc.mobile_activity_logs and not def.mobile_activity_logs
abc.mobile_activity_logs doesn't exist
In the database.yml file:
tester:
adapter: mysql2
database: def
host:
port:
username:
password:
enable_call: true
flags: CLIENT_MULTI_RESULTS
In the model:
class MobileActivityLogs < ActiveRecord::Base
establish_connection "tester"
self.table_name = "mobile_activity_logs"
end
This is a bit ugly though as it will make a second connection just to access a different schema :/

Rails: specifying a different database in the model

I'm trying to set up Rails (v3.2.2) to use multiple databases. I'm doing this based on this Connecting Rails 3.1 with Multiple Databases.
My model:
class Category < ActiveRecord::Base
establish_connection :category_database
self.primary_key = "cat_id"
validates_presence_of :name, :display_name, :description, :icon, :image, :parent_category_id, :create_time
end
database.yml:
category_database:
adapter: mysql2
encoding: utf8
reconnect: false
database: main_cat
pool: 5
username: root
password: blah
socket: /var/run/mysqld/mysqld.sock
When I run this spec file:
require 'spec_helper'
describe Category do
puts "ENV: #{Rails.env}"
it { should validate_presence_of :name }
it { should validate_presence_of :display_name }
it { should validate_presence_of :description }
it { should validate_presence_of :icon }
it { should validate_presence_of :image }
it { should validate_presence_of :parent_category_id }
it { should validate_presence_of :create_time }
end
like this:
>rspec /path/to/category_spec.rb
I get:
/home/user/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb:45:in `resolve_hash_connection': database configuration does not specify adapter (ActiveRecord::AdapterNotSpecified)
I've also tried setting establish_connection like this:
establish_connection(
:adapter => "mysql2",
:encoding => "utf8",
:reconnect => false,
:database => "main_cat",
:pool => 5,
:username => "root",
:password => "blah",
:socket => "/var/run/mysqld/mysqld.sock")
which results in the same exception. (AdapterNotSpecified)
What's strange is that if I abandon establish_connection altogether and apply the exact same connection configuration via the database.yml file like this:
test:
adapter: mysql2
encoding: utf8
reconnect: false
database: main_cat
pool: 5
username: root
password: blah
socket: /var/run/mysqld/mysqld.sock
it works.
It seems that Rails is ignoring establish_connection altogether...am I missing some application-level config setting or something? How do I get Rails to recognize establish_connection so that I can place different models in different databases?
Much appreciated!
So it turns out that Rails requires the presence of a default configuration. In this case, the database.yml file still requires a test database. Otherwise, Rails will throw an exception as it expects to establish some connection before the models are initialized. Once the default configuration is loaded, Rails goes on later to initialize the models and then model-level database configuration can take place via establish_connection.
I hope this helps someone else out there. It took me a considerable amount of time running the debugger through
activerecord-3.2.2/lib/active_record/connection_adapters/abstract/connection_specification.rb
to figure this out.
I was experiencing the same error for much the same reason, however I did have a test: configuration in my database.yml; but the problem was in my provisioning of the "establish connection" method within the model definition:
establish_connection 'cm_inv_mgmt_' + Rails.env.downcase
although I provided the sections of database.yml for the production/staging and development environments, I was missing cm_inv_mgmt_test!