Connecting to legacy database from a gem - ruby-on-rails-3

I am trying to create a gem to provide models for a legacy database but my gem can't see the app's configuration:
In my database.yml:
firefly:
adapter: mysql2
database: ...
username: ...
password: ...
model, in the gem:
module FireflyRails
class User < ActiveRecord::base
establish_connection :firefly
set_table_name "fly_users"
end
end
I prototyped this in a regular rails app, and was able to read from the database without issue. However, when used from the gem, I can't even start the console:
Abbreviated backtrace:
/Users/Jeff/.rvm/gems/ruby-1.9.3-p327#lunar/gems/activerecord-3.2.13/lib/active_record/connection_adapters/abstract/connection_specification.rb:47:in **`resolve_hash_connection': database configuration does not specify adapter (ActiveRecord::AdapterNotSpecified)**
from /Users/Jeff/.rvm/gems/ruby-1.9.3-p327#lunar/gems/activerecord-3.2.13/lib/active_record/connection_adapters/abstract/connection_specification.rb:41:in `resolve_string_connection'
from /Users/Jeff/.rvm/gems/ruby-1.9.3-p327#lunar/gems/activerecord-3.2.13/lib/active_record/connection_adapters/abstract/connection_specification.rb:27:in `spec'
from /Users/Jeff/.rvm/gems/ruby-1.9.3-p327#lunar/gems/activerecord-3.2.13/lib/active_record/connection_adapters/abstract/connection_specification.rb:130:in `establish_connection'
The examples I've found around the web all seem to use the standard rails database, I can't find an example of a gem using a different database configuration.
What am I missing here?

Related

Rails 4.0 & Devise - Strong Parameters error

Newbie to rails here, so bear with me.
New app on Rails 4 with ruby 2.0, I installed Devise and followed the instructions(default root, etc). Devise readme on github says it should be compatible with rails4 but
db:migrate failed unless I commented out attr_accessible line in User.rb
After commenting that out, I get "ActiveModel::ForbiddenAttributesError in Devise::RegistrationsController#create" error in trying to create a user.
I see some stack overflow questions like this, but a lot of the answers jump straight into some complex talk. I get I need to specify permitted attributes for mass assignment, but how? And where? And which attributes need to be permitted, all of them? Only those that I expect to be changed/created at the same time?
Judging by the error would I create a registrations_controller.rb that inherits from Devise::registrationsController ? What do I specify in that?
Any step by step, newbie friendly answers are much appreciated. I've exhausted myself trying different code from answers here and various sites from google searches.
Welcome to stackoverflow!
The problem is that the functinality of attr_accessible changed in rails 4.0
2 possibilities to get it running
1 Update Devise that it can handle Rails 4.0
Add this line to your application's Gemfile:
gem 'devise', '3.0.0.rc'
And then execute:
$ bundle
2 Add the old functionality of attr_accessible again to rails 4.0
Try to use attr_accessible and dont comment this out.
Add this line to your application's Gemfile:
gem 'protected_attributes'
And then execute:
$ bundle
Adding below gems and doing a bundle install worked for me
source 'https://rubygems.org'
gem 'rails', '4.0.2'
gem 'bootstrap-sass', '2.3.2.0'
gem 'devise', '3.0.0.rc'
gem 'protected_attributes'
gem 'sqlite3'

Gem with models

I created a Gem with models (actually, extracted it from the main project) to share amongst the projects we have in our platform.
We have dozens of models, so instead of requiring them one by one, I wrote the following code:
Gem.find_files("my_gem/models/*.rb").each { |path| require path }
I access one of the projects that has my_gem in the gem file and running rails c I get the following output:
/Users/myuser/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.8/lib/active_record/dynamic_matchers.rb:50:in `method_missing': undefined method `has_attached_file' for #<Class:0x007fad4b93ccb8> (NoMethodError)
One of my models is using the gem paperclip, what is weird is:
If I remove the line declared above to load all the models
automatically, rails c runs fine
If I try to include onlye the model that uses paperclip require
"my_gem/models/paperclip_model" I receive the same error
So then I change my gem to not load any model, and when I try to reference any model from rails console, it says the class is not loaded, but then I run Gem.find_files("my_gem/models/*.rb").each { |path| require path } or require "my_gem/models/paperclip_model" 'they work perfectly and I am able to work with the model.
Has any of you seen the same issue?
Seems that changing require for autoload solved the problem
I changed Gem.find_files("my_gem/models/*.rb").each { |path| require path }
for
Gem.find_files("my_gem/models/*.rb").each do |f|
filename = File.basename(f, '.*')
class_name_symbol = filename.classify.to_sym
autoload class_name_symbol, "my_gem/models/#{filename}"
end
and now it is working.
It sounds like one of the models in your gem depends on Paperclip, but you don't explicitly set it as a dependency. So what's happening is that if your models get loaded before paperclip gets loaded, you'll see the UndefinedMethod error for has_attached_file.
If you use your models in a Rails application which has paperclip as a dependency, and you load those models after the console (or server) has spun up, Paperclip will be present, so you won't see this error.
The solution is to explicitly add paperclip as a dependency in your gemspec, something like:
s.add_dependency('paperclip')
Assuming that this gem will always be used in the context of a Rails application, this should work. If not, you might also need to add the following line to the top of your models that use paperclip:
require "paperclip"

Rails 3.1 / mysql2 error : "MySQL server has gone away"

I'm experiencing trouble upgrading my rails 2.3.14 / ruby 1.8.7 app to 3.1.1/1.9.2 : I have some
(ActiveRecord::StatementInvalid) "Mysql2::Error: MySQL server has gone away"
errors happening sporadically. It's important to precise that I never had such issues with the 'mysql' gem on 2.3.14 and the exactly same db (so the bug shouldn't come from mysql (v5.5.10)).
Example :
$ rails c production
Loading production environment (Rails 3.1.1)
ruby-1.9.2-p290 :001 > ActiveRecord::Base.connection.active?
=> false
ruby-1.9.2-p290 :002 > exit
$ rails c production
Loading production environment (Rails 3.1.1)
ruby-1.9.2-p290 :001 > ActiveRecord::Base.connection.active?
=> true
This happens only with my (remote) production database, no problem with my local development db. I've tried to set "reconnect: true" in my database.yml but it led to a
Mysql2::Error: Host '****' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts':...
I've tried to isolate the problem with a little rb script only loading mysql2 and activerecord but I didn't manage to reproduce the bug that way (so it may be linked to the rails stack).
I can't go back from the 'mysql2' to the 'mysql' gem because of encoding issues ( http://www.rorra.com.ar/2010/07/30/rails-3-mysql-and-utf-8/ ). As a consequence, I had to rollback my production to my rails 2.3.14 app, which saddens me very much...
Do you see what I can do to debug this ? I can't even find a sure way to reproduce the error... Have anyone met the same bug ?
I just found few people mentionning this bug (ex : https://github.com/brianmario/mysql2/issues/213) but not a solution.
Thanks for your help.
Ok, I think I solved my problem. I didn't notice it when I posted my question, but it seemed that the error was timeout related : after about 20s, activerecord losts its connection.
$ rails runner "sleep 23; puts ActiveRecord::Base.connection.active?"
=> true
$ rails runner "sleep 25; puts ActiveRecord::Base.connection.active?"
=> false
So I dug further and I realized that mysql and mysql2 gems didn't deal with the MySQL 'wait_timeout' param the same way : mysql gem doesn't set it thus uses the MySQL default value 28800, whereas mysql2 gem sets it at 2592000 if not defined in the database.yml.
But I have the impression that the value 2592000 is over the max value for this param : 2147483 ! Which could lead to the unexpected behavior I described...
I build a script test showing the bug : https://gist.github.com/1514154
And if I had some apparently random disconnect while loading rails console (cf my question), I think it's because of my app taking a long time to load and me sometimes waiting a few seconds before typing my command.
I can't explain why we are so few to encounter this problem. Perhaps it's specific to my conf (remote database, MySQL version ?). I've tried with another remote staging database : the bug didn't reproduce...
So as a conclusion, I will set wait_timeout: 2147483 in my database.yml. And maybe pull request rails...
Had a lot of lost connections - but I couldn't say if they went away due to the following tweak or elsewise :/
Had to throw the following script into initializers and add a line of configuration to each of my databases in my database.yml like this:
...
flags: <%= 65536 | 131072 %>
...
The script looks like this:
/config/initializers/mysql2.rb
module ActiveRecord
class Base
# Overriding ActiveRecord::Base.mysql2_connection
# method to allow passing options from database.yml
#
# Example of database.yml
#
# login: &login
# socket: /tmp/mysql.sock
# adapter: mysql2
# host: localhost
# encoding: utf8
# flags: 131072
#
# #param [Hash] config hash that you define in your
# database.yml
# #return [Mysql2Adapter] new MySQL adapter object
#
def self.mysql2_connection(config)
config[:username] = 'root' 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
end
end

Rails Active Admin resource problem

I recently have watched railscast 284 about active admin and wanted to implement it into my web app, however I am running into an issue when I add a resource. I get the following message every time I try to navigate to the created tab:
NameError in Admin::LoadsController#index
undefined local variable or method `per' for []:ActiveRecord::Relation
Rails.root: /Users/thomascioppettini/rails_projects/want-freight
Application Trace | Framework Trace | Full Trace
Request
Parameters:
{"order"=>"id_desc"}
Show session dump
Show env dump
Response
Headers:
None
The only thing I can think of that may affect the application is adding a recaptcha to devise, which active admin depends on.
For me, it looks like this is a pagination problem. What gem are you using? You should give as more details about your settup. Can you show us your resource file from admin directory? What version of rails and what ActiveAdmin are you using ?
If you are using the will_paginate gem, set the version to 3.0.pre2. I was using ~>3.0.pre2, which auto-updated to 3.0.2 when I ran a bundle update Reverting fixed the issue. If you're using Bundler, the line is this:
gem "will_paginate", "3.0.pre2"
I agree with Dawaid. It is a pagiantion error. Add "Kaminari" gem to you Gemfile. According to active admin docs, it is using kaminari for pagination.. will_paginate will also work for you as swilliams described...
As I understand active_admin doesn't support will_paginate anymore. But if you don't want to rewrite your pagination to Kaminari you can fix this problem with putting some code to initializers
# config/initializers/will_paginate.rb
if defined?(WillPaginate)
module WillPaginate
module ActiveRecord
module RelationMethods
alias_method :per, :per_page
alias_method :num_pages, :total_pages
end
end
end
end
module ActiveRecord
class Relation
alias_method :total_count, :count
end
end

How to access Rails 3 engine models in rails console

In the mail app's rails console (irb), how to access engine's models.
update: Say "team" is my main app and "team_page" is the engine. "team_page" is required in main app in the gemfile through 'gem => "team_page", :path => "local/path/to/team_page"'.
when I go to team's rails console, I couldn't access team_page's models.
First you must know the module's name. To help with that, you can run a
bundle show team_page
to find its directory and explore over there (probably under lib/team_page.rb) until
you see the following definition:
module TeamPage
# ...
end
Let's say that the module is called TeamPage. Then just prepend double colon to its name like this:
::TeamPage::SomeModel.some_method