rails4 deployment logs out all users - ruby-on-rails-4

got some strange behavior since quite a while. After deployment (with capistarano) all users need to sign in again!
happens in several apps, since Rails 4.x .. here some versions:
Rails: 4.2.5 / 4.2.6
Devise: 3.5.3 / 3.5.6 / 4.2.0
Capistrano: 3.4.0
Ruby: 2.2.1 / 2.3.0
Web-Server: nginx
App-Server: thin (1.6.4 / 1.7.0)
this is really annoying, especially because zero-downtime-deployment makes no sence anymore and remember-me doesn't work at all
models/user
class User < ActiveRecord::Base
..
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable,
:validatable, :confirmable, :lockable, :timeoutable, :omniauthable, :invitable,
:omniauth_providers => CONFIG[:devise_provider]
..
end
initializers/devise
Devise.setup do |config|
config.secret_key = 'xxx-key-xxx'
config.mailer_sender = CONFIG[:mail_system]
config.mailer = 'AccountMailer'
require 'devise/orm/active_record'
config.case_insensitive_keys = [:email]
config.strip_whitespace_keys = [:email]
config.skip_session_storage = [:http_auth]
config.stretches = Rails.env.test? ? 1 : 10
config.invite_for = 0
config.reconfirmable = true
config.expire_all_remember_me_on_sign_out = true
config.password_length = CONFIG[:password_min_length]..CONFIG[:password_max_length]
config.timeout_in = 6.hours
config.reset_password_within = 6.hours
config.sign_out_via = :delete
config.omniauth :facebook, CONFIG[:facebook_id], CONFIG[:facebook_secret], {info_fields: 'email, first_name, last_name, gender', image_size: "large"}
config.omniauth :google_oauth2, CONFIG[:google_id], CONFIG[:google_secret], {
skip_jwt: true,
scope: "email, profile, plus.me",
# prompt: "select_account",
image_aspect_ratio: "square",
image_size: 200
}
end
Most of the apps are running in production, so I don't touch the database while deployment (except for migrations).
Also happens in apps without devise_invitable, so this also don't causes it.
.. thanks for any help! ..
also posted as devise #4277

solved it!
The problem was caused by the only thing I didn't mention: rvmor better rvm1-capistrano3which completely ignores ~/.bachrc, ~/.profile and so on.
I had to put secret_key_base in /etc/environment now it works as expected.
Till now secret_key_base was just a huge pain in the ass for me, because all documented usage didn't work and I had to put secret_key_base in :default_env and also inject it in some monit scripts. ie: to restart sidekiq or thin (therefore it was hardcoded in deploy.rb)
Thanks to surendar, his answer on capistrano 3 + rvm1-capistrano3 rails 4.1 secrets.yml environmental variables issue was the solution.
It still don't seems to be the best solution (but it works), so I'll stay open for better solutions.

Related

Integrating letter_opener with Devise

I am currently using the Devise gem for authentication with my rails app and I am having trouble using the letter_opener gem with it. I can get it to work with a the standard mailer but I'm not sure how to configure the Devise mailer to work with letter_opener.
How do I configure letter_opener so that it will work with the emails sent with Devise?
Don`t know how it was in Rails 4.x but in Rails 5.1 I did it like so:
1) Install
gem 'letter_opener_web', group: :development
2) Make your devise model
confirmable
here`s the link https://github.com/plataformatec/devise/wiki/How-To:-Add-:confirmable-to-Users
3) Add this config
config.action_mailer.perform_deliveries = true
config.action_mailer.default_url_options = { host: 'localhost:3000' }
config.action_mailer.delivery_method = :letter_opener
to
config/environments/development.rb
in your devise initializer(config/initializers/devise.rb)
config.mailer_sender = 'foo#bar.com'
config.mailer = Devise.mailer
4) Do not forget to mount your letter_opener web interface to routes.rb
mount LetterOpenerWeb::Engine, at: '/letter_opener' if Rails.env.development?
This works pretty nice. Your mails will be available at
localhost:3000/letter_opener

Capybara::Poltergeist Status error, failed to reach server

I am trying to make some tests with Rspec/Capybara/Poltergeist on my Rails 4 application, Phantomjs is installed (version 2.2.1), but I always get this error :
Failure/Error: visit(perfect_landing_page_path)
Capybara::Poltergeist::StatusFailError:
Request to 'http://127.0.0.1:49623/path' failed to reach server, check DNS
and/or server status
The test i'm working on :
require 'rails_helper'
RSpec.feature 'Subscription', :type => :feature do
let!(:plan) { create(:plan) }
let!(:landing_page) { create(:landing_page) }
before(:each) { landing_page.default_plan = plan }
describe 'landing_page#perfect_show' do
scenario 'form display', js: true do
plan_2 = create(:plan)
plan_3 = create(:plan)
landing_page.plans << plan_2
landing_page.plans << plan_3
visit(perfect_landing_page_path)
expect(page).to have_css(".start-now", count: 3)
first(".start-now").click
expect(page).to have_css("#new_user")
end
end
end
My Gemfile looks like this :
gem 'rspec-rails', '~> 3.0'
gem 'factory_girl_rails'
gem 'guard-rspec'
group :test do
gem 'database_cleaner'
gem 'capybara'
gem 'capybara-screenshot'
gem 'poltergeist'
gem 'selenium-webdriver'
gem 'shoulda-matchers', require: false
gem 'show_me_the_cookies'
end
My spec/support/capybara.rb file :
require 'capybara/rails'
require 'capybara/rspec'
require 'capybara-screenshot/rspec'
require "capybara/poltergeist" # Add this line to require poltergeist
require 'selenium-webdriver'
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, {:js_errors => false, :default_max_wait_time => 30, :timeout => 30, phantomjs_options: [
'--load-images=no',
'--ignore-ssl-errors=true',
'--ssl-protocol=any']})
end
Capybara.register_driver :poltergeist_debug do |app|
Capybara::Poltergeist::Driver.new(app, :inspector => true)
end
Capybara.configure do |config|
config.javascript_driver = :poltergeist
config.ignore_hidden_elements = true
config.default_max_wait_time = 30
end
My spec_helper.rb file :
require 'capybara/rspec'
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.filter_run :focus
config.run_all_when_everything_filtered = true
Did someone encounter this problem before ? Does anyone have a solution for this ? I have been banging my head for days looking on the web...
Thank you very much.
PS : it works fine on my friend's mac (Yosemite or El Capitan), just not on mine.
I was having this problem in CI (CodeShip).
Adding a call to bundle exec rake assets:precompile at the end of the setup commands seemed to fix it:
CodeShip CI Setup Commands:
rvm use 2.3.4 --install
bundle install
export RAILS_ENV=test
bundle exec rake db:schema:load
bundle exec rake assets:precompile
Also had a whitelist per #agbodike but in the rails_helper.rb
config.before(:each, js: true) do
page.driver.browser.url_whitelist = ["127.0.0.1"]
end
I had the same issue and it was due to a 3rd party script timing out. You can prevent loading of 3rd party scripts with a blacklist. For example:
config.before(:each, js: true) do
page.driver.browser.url_blacklist = ["http://use.typekit.net"]
end
would prevent any URL starting with http://use.typekit.net from being called for each test that uses the js driver. More information can be found at:
https://robots.thoughtbot.com/speed-up-javascript-capybara-specs-by-blacklisting-urls
Alternatively you can use a whitelist:
config.before(:each, js: true) do
page.driver.browser.url_whitelist = ["127.0.0.1"]
end
which will block all requests not to 127.0.0.1
I placed the configuration in spec/feature_helper.rb to ensure it was only set for feature specs.
You can avoid these by precompile the assets before tests.
And the code is:
RSpec.configure do |config|
config.before :all do
ENV['PRECOMPILE_ASSETS'] ||= begin
case self.class.metadata[:type]
when :feature, :view
STDOUT.write "Precompiling assets..."
require 'rake'
Rails.application.load_tasks
Rake::Task['assets:precompile'].invoke
STDOUT.puts " done."
Time.now.to_s
end
end
end
end
more info

undefined method define_enum_for for RSpec::ExampleGroups

I am getting undefined define_enum_for method error after upgrading rails to 4.2.0 from 4.1.
Is there any fix for this?
Rails : 4.2.0
Ruby : ruby 2.1.5p273 (2014-11-13 revision 48405) [i686-linux]
1) Recording
Failure/Error:
should define_enum_for(:state).
with({
initial: 'initial',
running: 'running',
stopped: 'stopped'
})
NoMethodError:
undefined method `define_enum_for' for #<RSpec::ExampleGroups::Recording:0x99a0ea8>
shoulda-matchers#define_enum_for
specifying the test_framework :rspec for shoulda-matchers#configuration solved this problem.
shoulda-matchers#configuration
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :active_record
with.library :active_model
with.library :action_controller
end
end
Configuration Required
spec_helper.rb/rails_helper.rb configure block
type: metadata
spec_helper.rb/rails_helper.rb
I required the Shoulda::Matchers configuration in the spec_helper.rb (the application had not been migrated to rails_helper.rb - but rails_helper.rb is the place I would have put it if available):
# spec/spec_helper.rb
Shoulda::Matchers.configure do |config|
config.integrate do |with|
with.test_framework :rspec
with.library :rails # same as :active_record + :active_model + :active_controller
end
end
Metadata
But, it also required the type: metadata before it worked:
This==============\/
describe User, type: :model do
it { should define_enum_for(:status) }
end

With Rails 4 and selenium web driver, use Sauce Labs on Travis CI but not locally

I'm filling out specs for an open source Rails project and need to run the app in a browser for some of my feature specs. I'd like to use Sauce Labs on Travis CI, but without having to rewrite my specs to also use Sauce Labs locally, because:
I don't want to have to be connected to the Internet during development to run my specs.
Making the specs reliant on Sauce Labs would make it impossible for contributors to run the specs themselves without setting up their own Sauce Labs account and env vars.
I couldn't find documentation detailing this scenario. What's the best way of achieving this?
For those with similar needs, this is what I ended up doing:
.travis.yml:
env:
global:
- secure: "encrypted sauce username"
- secure: "encrypted sauce secret key"
addons:
sauce_connect: true
before_install:
# install the ed text editor which we use to append
# file contents to a specific line of another file
- sudo apt-get install -y ed
# appends contents of travis/Gemfile.travis to Gemfile
- cat travis/Gemfile.travis >> Gemfile
# adds contents of travis/rails_helper.rb.travis to line 12 of spec/rails_helper.rb
- ed -s spec/rails_helper.rb <<< '12r travis/rails_helper.rb.travis'$'\nw'
travis/Gemfile.travis:
group :test, :development do
gem 'sauce', '~> 3.1.1'
gem 'sauce-connect'
gem 'parallel_tests'
end
travis/rails_helper.rb.travis:
require 'sauce'
require 'sauce/capybara'
# change to "Capybara.default_driver = :sauce" to use sauce
# for ALL feature specs, not just ones marked with "js: true"
Capybara.javascript_driver = :sauce
Sauce.config do |config|
config[:browsers] = [
['Linux', 'Chrome', nil],
# and other OS/browser combos you want to support...
]
end
UPDATE (2014/11/25):
I ended up using a slightly different configuration in my final solution. I didn't like the brittleness of inserting at a line number. Instead of having special Sauce inclusions in separate files, I just nested special configuration in a conditional, depending on whether an environment variable SAUCY is set to true.
.travis.yml:
env:
global:
- secure: "encrypted sauce username"
- secure: "encrypted sauce secret key"
- SAUCY: true
addons:
sauce_connect: true
Gemfile:
group :development, :test do
# other gems...
if ENV['SAUCY']
# gems for sauce
gem 'sauce', '~> 3.1.1'
gem 'sauce-connect'
gem 'parallel_tests'
end
end
spec/rails_helper.rb:
# after other requires
if ENV['SAUCY']
require 'sauce'
require 'sauce/capybara'
# change to "Capybara.default_driver = :sauce" to use sauce
# for ALL feature specs, not just ones marked with "js: true"
Capybara.javascript_driver = :sauce
Sauce.config do |config|
config[:browsers] = [
['Linux', 'Chrome', nil],
# and other OS/browser combos you want to support...
]
end
end
This way, I can also easily use Sauce locally if I choose to with:
SAUCY=true bundle install
SAUCY=true SAUCE_USERNAME=username SAUCE_ACCESS_KEY=access_key bundle exec rspec

rake db:migrate fails with globalize gem and rails 4.1.7

I'm trying to use the globalize gem with Rails 4.1.7.
Using latest RVM version, os is Ubuntu 12.04, db is postgresql 9.3.
Following the instructions found in readme.md on github i added the translates directive in my model and scaffolded a migration
class Ingredient < ActiveRecord::Base
translates :name, :description
end
class CreateIngredientTranslations < ActiveRecord::Migration
def up
Ingredient.create.translation_table!({
name: :string,
descripion: :text
}, {
migrate_data: true
})
end
def down
Ingredient.drop_translation_table! migrate_data: true
end
end
Then when i do rake db:migrate i get the following error
PG::UndefinedTable: ERROR: relation "ingredient_translations" does not exsist
LINE 5: WHERE a.attrelid = '"ingredient_translations"...
^
: SELECT a.attname, format_type(a.atttypid, a.atttypmod),
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = '"ingredient_translations"'::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum
/home/kranz/.rvm/gems/ruby-2.1.4#recipes/gems/activerecord-4.1.7/lib/active_record/connection_adapters/postgresql_adapter.rb:822:in `async_exec'
This is really weird.
Googling around for this kind of error I found a ticket in github
https://github.com/globalize/globalize/issues/288
opened in Dec 2013 and still not closed which seems very similar; the only solution seems to be a hack in globalize code, but i'd prefer not to monkey patching code at that level.
Is it due to the combination of postgres and globalize or there is any other solution to this?