Twitter::Error::Forbidden: Error creating status - ruby-on-rails

I am trying to send tweets from a web job to notify my users of certain events.
It works fine on my local machine but when deployed to Heroku I get the following error when trying to tweet with media:
Twitter::Error::Forbidden: Error creating status.
from /app/vendor/bundle/ruby/2.2.0/gems/twitter-5.17.0/lib/twitter/rest/response/raise_error.rb:12:in `on_complete'
from /app/vendor/bundle/ruby/2.2.0/gems/faraday-0.9.2/lib/faraday/response.rb:9:in `block in call'
from /app/vendor/bundle/ruby/2.2.0/gems/faraday-0.9.2/lib/faraday/response.rb:57:in `on_complete'
from /app/vendor/bundle/ruby/2.2.0/gems/faraday-0.9.2/lib/faraday/response.rb:8:in `call'
from /app/vendor/bundle/ruby/2.2.0/gems/faraday-0.9.2/lib/faraday/request/url_encoded.rb:15:in `call'
from /app/vendor/bundle/ruby/2.2.0/gems/faraday-0.9.2/lib/faraday/request/multipart.rb:14:in `call'
from /app/vendor/bundle/ruby/2.2.0/gems/twitter-5.17.0/lib/twitter/rest/request/multipart_with_file.rb:21:in `call'
from /app/vendor/bundle/ruby/2.2.0/gems/faraday-0.9.2/lib/faraday/rack_builder.rb:139:in `build_response'
from /app/vendor/bundle/ruby/2.2.0/gems/faraday-0.9.2/lib/faraday/connection.rb:377:in `run_request'
from /app/vendor/bundle/ruby/2.2.0/gems/faraday-0.9.2/lib/faraday/connection.rb:177:in `post'
from /app/vendor/bundle/ruby/2.2.0/gems/twitter-5.17.0/lib/twitter/rest/request.rb:33:in `perform'
from /app/vendor/bundle/ruby/2.2.0/gems/twitter-5.17.0/lib/twitter/rest/utils.rb:50:in `perform_request'
from /app/vendor/bundle/ruby/2.2.0/gems/twitter-5.17.0/lib/twitter/rest/utils.rb:72:in `perform_request_with_object'
from /app/vendor/bundle/ruby/2.2.0/gems/twitter-5.17.0/lib/twitter/rest/utils.rb:64:in `perform_post_with_object'
from /app/vendor/bundle/ruby/2.2.0/gems/twitter-5.17.0/lib/twitter/rest/tweets.rb:233:in `update_with_media'
I can tweet pure text tweets without any errors. Any ideas as to what may be the cause of this?
is there some constraints on Heroku that prevents me from sending the image?
The code sending the tweet looks like this:
def send_tweet(company, data)
file_name = ChartGenerator.build_company_chart(data)
client.update_with_media(company_tweet_text(company), File.new(file_name))
end
def send_test_tweet
client.update('Test tweet')
end
def client
Twitter::REST::Client.new do |config|
config.consumer_key = ENV["TWITTER_CONSUMER_KEY"]
config.consumer_secret = ENV["TWITTER_CONSUMER_SECRET"]
config.access_token = ENV["TWITTER_ACCESS_TOKEN"]
config.access_token_secret = ENV["TWITTER_ACCESS_TOKEN_SECRET"]
end
end
send_test_tweet works fine on Heroku and locally and send_tweet works locally but NOT on Heroku.
I have via console verified that the ChartGenerator works as expected on Heroku.
Could there be some Faraday settings needed for production? (I noticed faraday in the stacktrace)

Related

Errno::ENOENT: No such file or directory # rb_file_s_mtime after feature tests

When running feature Rspecs, I receive the following error (full trace at the bottom of this message)
Puma output
Rack app error handling request { GET /rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDRG9JYTJWNVNTSm5kbUZ5YVdGdWRITXZSM0IxTkRGRFRWQlFaVXRNYVUxaVpuQjZXVmw1UTNBMUx6RXhNR1V3TVRka01UWTVNalZrWXpkak5UQTNNamhqT1dNeE5UUmhOREl3TURjNVlXRTJaVFZtWTJNME16VmtZak5sTm1VNU4ySXhNemd3WldObFl6Z0dPZ1pGVkRvUVpHbHpjRzl6YVhScGIyNUpJajFwYm14cGJtVTdJR1pwYkdWdVlXMWxQU0pwYldGblpTNXdibWNpT3lCbWFXeGxibUZ0WlNvOVZWUkdMVGduSjJsdFlXZGxMbkJ1WndZN0JsUTZFV052Ym5SbGJuUmZkSGx3WlVraURtbHRZV2RsTDNCdVp3WTdCbFE9IiwiZXhwIjoiMjAxOS0wMS0yNVQxMToxNjoyOS40NDBaIiwicHVyIjoiYmxvYl9rZXkifX0=--db9451afdc95b292aa6a77c40e00ab0ceb687766/image.png }
#<Errno::ENOENT: No such file or directory # rb_file_s_mtime - /path/to/rails/app/tmp/storage/va/ri/variants/Gpu41CMPPeKLiMbfpzYYyCp5/110e017d16925dc7c50728c9c154a420079aa6e5fcc435db3e6e97b1380ecec8>
(followed by the full trace at the end of this message)
Rspec outpout
Failure/Error: last_modified = ::File.mtime(path).httpdate
Errno::ENOENT:
No such file or directory # rb_file_s_mtime - /path/to/rails/app/tmp/storage/va/ri/variants/Gpu41CMPPeKLiMbfpzYYyCp5/110e017d16925dc7c50728c9c154a420079aa6e5fcc435db3e6e97b1380ecec8
(followed by the full trace at the end of this message)
Context
product.image is an ActiveStorage attachment. During the test the "products/_form" partial is rendered and is displaying the attachment file (namely a png image) with the following code: = image_tag url_for(product.image.variant(resize: "120x120")). If I comment out this line, the error does not occur anymore.
The test itself succeed every times, the error seems to be triggered after the test. I verified all my after blocks, it seems to happen after all my after blocks.
The trace indicates that ActiveStorage::DiskController.serve_file triggers the errors. Is it that ActiveStorage app is not shutting down gracefully ?
I'm using active_storage.service = :test configuration, but :file gives the same errors.
Image broken
While a test fail, I can see in the "remote controlled" browser that the image is not display and there is a broken image icon instead.
Running the tests
There is a group of 4 featured tests that are going through the render of the "products/_form" partial. When I run the 4 tests in a random order the error occurs randomly. Sometime I can see the error 2 times, sometimes 3 times.
when I run the tests individually the error does never appear.
How I attach the image
This is the helper I use to attach the file to the model before going through the test :
path = Rails.root.join 'spec', 'support', 'fixtures', 'img1.png'
raise 'Image does not exist' unless File.exist? path
product.image.attach io: File.open(path), filename: 'image.png'
I also tried to use this helper :
path = Rails.root.join 'spec', 'support', 'fixtures', 'img1.png'
raise 'Image does not exist' unless File.exist? path
blob = ActiveStorage::Blob.create_after_upload! io: path.open, \
filename: 'img1.png', content_type: 'image/png'
product.images.attach blob
And this helper :
path = Rails.root.join 'spec', 'support', 'fixtures', 'img1.png'
raise 'Image does not exist' unless File.exist? path
byte_size = path.size
checksum = Digest::MD5.file(path).base64digest
blob = ActiveStorage::Blob.create_before_direct_upload!(filename: 'img1.png', \
byte_size: byte_size, checksum: checksum, content_type: 'image/png').tap do |blob|
ActiveStorage::Blob.service.upload(blob.key, path.open)
end
product.images.attach blob
System configuration
Rails version: 5.2.2
Ruby version: ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]
Rbenv version: rbenv 1.1.1-39-g59785f6
Rspec related versions: rspec 3.8.0 - capybara 3.12.0 - selenium-webdriver 3.141.0
Full trace
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/file.rb:63:in `mtime'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/file.rb:63:in `serving'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activestorage-5.2.2/app/controllers/active_storage/disk_controller.rb:42:in `serve_file'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activestorage-5.2.2/app/controllers/active_storage/disk_controller.rb:12:in `show'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/abstract_controller/base.rb:194:in `process_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_controller/metal/rendering.rb:30:in `process_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/abstract_controller/callbacks.rb:42:in `block in process_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activesupport-5.2.2/lib/active_support/callbacks.rb:132:in `run_callbacks'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/abstract_controller/callbacks.rb:41:in `process_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_controller/metal/rescue.rb:22:in `process_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activesupport-5.2.2/lib/active_support/notifications.rb:168:in `block in instrument'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activesupport-5.2.2/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activesupport-5.2.2/lib/active_support/notifications.rb:168:in `instrument'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_controller/metal/instrumentation.rb:32:in `process_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activerecord-5.2.2/lib/active_record/railties/controller_runtime.rb:24:in `process_action'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/abstract_controller/base.rb:134:in `process'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionview-5.2.2/lib/action_view/rendering.rb:32:in `process'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_controller/metal.rb:191:in `dispatch'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_controller/metal.rb:252:in `dispatch'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/routing/route_set.rb:34:in `serve'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/journey/router.rb:52:in `block in serve'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/journey/router.rb:35:in `each'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/journey/router.rb:35:in `serve'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/routing/route_set.rb:840:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/tempfile_reaper.rb:15:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/etag.rb:25:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/conditional_get.rb:25:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/head.rb:12:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/http/content_security_policy.rb:18:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:232:in `context'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:226:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/middleware/cookies.rb:670:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activesupport-5.2.2/lib/active_support/callbacks.rb:98:in `run_callbacks'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/railties-5.2.2/lib/rails/rack/logger.rb:38:in `call_app'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/railties-5.2.2/lib/rails/rack/logger.rb:26:in `block in call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activesupport-5.2.2/lib/active_support/tagged_logging.rb:71:in `block in tagged'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activesupport-5.2.2/lib/active_support/tagged_logging.rb:28:in `tagged'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activesupport-5.2.2/lib/active_support/tagged_logging.rb:71:in `tagged'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/railties-5.2.2/lib/rails/rack/logger.rb:26:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/middleware/request_id.rb:27:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/method_override.rb:22:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/runtime.rb:22:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/activesupport-5.2.2/lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/middleware/executor.rb:14:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/actionpack-5.2.2/lib/action_dispatch/middleware/static.rb:127:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/sendfile.rb:111:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/railties-5.2.2/lib/rails/engine.rb:524:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/urlmap.rb:68:in `block in call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/urlmap.rb:53:in `each'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/rack-2.0.6/lib/rack/urlmap.rb:53:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/capybara-3.12.0/lib/capybara/server/middleware.rb:48:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/puma-3.12.0/lib/puma/configuration.rb:225:in `call'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/puma-3.12.0/lib/puma/server.rb:658:in `handle_request'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/puma-3.12.0/lib/puma/server.rb:472:in `process_client'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/puma-3.12.0/lib/puma/server.rb:332:in `block in run'
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/puma-3.12.0/lib/puma/thread_pool.rb:133:in `block in spawn_thread'
#
# Showing full backtrace because every line was filtered out.
# See docs for RSpec::Configuration#backtrace_exclusion_patterns and
# RSpec::Configuration#backtrace_inclusion_patterns for more information.
# ------------------
# --- Caused by: ---
# Capybara::CapybaraError:
# Your application server raised an error - It has been raised in your test code because Capybara.raise_server_errors == true
# /opt/rbenv/versions/2.5.3/lib/ruby/gems/2.5.0/gems/capybara-3.12.0/lib/capybara/session.rb:147:in `raise_server_error!'
Update
(Sorry for being silent, I had an emergency to attend to)
Here is an interesting information. I inserted after this line, this code: puts "SERVING #{path} - Exist ? #{File.exist? path}"
And here is the output (observe the files names and the boolean value at the end of each line):
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/Me/GK/MeGKkqgbb7Sg4RbPoCYWR6pZ - Exist ? true
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/sG/3v/sG3vd2viGWmaf69pNXSChZPa - Exist ? true
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/fy/2C/fy2C8PpaR96YgCzwt5WVBLrQ - Exist ? true
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/sG/3v/sG3vd2viGWmaf69pNXSChZPa - Exist ? true
. (green dot)
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/Me/GK/MeGKkqgbb7Sg4RbPoCYWR6pZ - Exist ? false
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/sG/3v/sG3vd2viGWmaf69pNXSChZPa - Exist ? false
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/Me/GK/MeGKkqgbb7Sg4RbPoCYWR6pZ - Exist ? false
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/fy/2C/fy2C8PpaR96YgCzwt5WVBLrQ - Exist ? false
F (red F)
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/Me/GK/MeGKkqgbb7Sg4RbPoCYWR6pZ - Exist ? false
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/sG/3v/sG3vd2viGWmaf69pNXSChZPa - Exist ? false
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/Me/GK/MeGKkqgbb7Sg4RbPoCYWR6pZ - Exist ? false
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/fy/2C/fy2C8PpaR96YgCzwt5WVBLrQ - Exist ? false
F (red F)
SERVING /tmp/active_storage_tests20190129-10797-1rebdf7/Tx/DL/TxDLPEk3ykf8ETkURY5YZPgY - Exist ? true
As we can see the files path are the same, even between tests. Tough the database is cleaned between each tests. So there is "somewhere" where the file checksum is kept, for activestorage to reuse the same blob record. As a result it reuse the same file path and that's the reason why I have a FileNotFound error.
Any idea ? Please note that, additionally to DatabaseCleaner, I have an after block defined like this :
config.after(:each) do
ActiveStorage::Current.reset
ActiveStorage::Attachment.all.each(&:delete)
ActiveStorage::Blob.all.each(&:delete)
end
I suspect a bug
Filled a PR with an application to reproduce https://github.com/rails/rails/issues/34989
Waiting for them response
The fact that the test passes just means that the test does not depend on that image being found. A broken image link will not generally cause a test to fail and it is in fact often the case that test writers do not even bother to supply mock images because it is (perceived to be) too much work and not relevant to the thing being tested.
See folks, this is why we ask for an example. Now that the OP has posted an example, we can see that his problem is browser caching, and will be solved by replacing
product.images.attach io: File.open(path), filename: 'image.png'
with
product.images.attach io: File.open(path), filename: "image-#{Time.now.strftime("%s%L")}.png"
in the helper that does the attachment. I would not have solved this without having the example.
Explanation
ActiveStorage handles saving and serving files. OP was saving and serving images with it, which is definitely what it was intended for. In order to allow for different services to serve files in different ways, ActiveStorage separates the published URL from the actual image serving URL.
The published URL is almost a permalink: it is an encoded version of the database key for the attachment. ActiveStorage processes a request for the URL by looking up where the file is stored and sending a 302 temporary redirect to the URL that can be used to access the file, called a "service URL". When using AWS S3 to store files, the service URL can be a signed URL that expires quickly but nevertheless connects the browser directly to S3 rather than having to go through the web server as intermediary.
By default, the service URL is good for 5 minutes, and ActiveRecord explicitly sets
Cache-Control: max-age=300, private
on the 302 redirect. The browser caches this redirect response and for the next 5 minutes the browser will not even attempt to use or verify the published URL, it will immediately replace the public URL with the cached service URL.
Unfortunately, while the public URL is predictably recreated, the service URL is randomly generated, so when the browser does its automatic redirection, the previously valid service URL no longer works. The solution (or workaround, depending on your point of view) is to distinguish the public URLs by including a timestamp in the filename, so that tests will not reuse public URLs.
Sidenote
By the way, you should not be using url_for with image_tag. Change your ERB from
= image_tag url_for(product.image.variant(resize: "120x120"))
to
= image_tag(product.image.variant(resize: "120x120"))
Rails is smart enough to handle either case, but the latter way is the recommended way.
Something is likely off with how you're setting up the image that you're testing against. You might want to update that to how the Rails team handles it in their own tests:
module ActiveStorageHelpers
# ported from https://github.com/rails/rails/blob/5-2-stable/activestorage/test/test_helper.rb#L57
def create_file_blob(filename: "image.jpg", content_type: "image/jpeg", metadata: nil)
ActiveStorage::Blob.create_after_upload! io: file_fixture(filename).open, filename: filename, content_type: content_type, metadata: metadata
end
end
RSpec.configure do |config|
config.include ActiveStorageHelpers
end
Then place a tiny image file in spec/fixtures/file/images.jpg (that's where the file_fixture method will look for it).
With that in place, you can setup the image on your model in your feature test with something like:
instance_of_model.images.attach(create_file_blob)
I'm not sure what you mean with the exception happens after the test?
Test should be usually atomic and independent, so all resources you create should be removed immediately after your test finished.
Also tests are running in random order, so tests which rely on each other will fail sometimes - and sometimes not, depending on the run order.
Can you share the output or tests which fail?

2.3.0/gems/twitter-6.1.0/lib/twitter/rest/response/raise_error.rb:13:in `on_complete': Bad Authentication data. (Twitter::Error::BadRequest)

Simply put, I'm attempting to post a tweet using these pieces of ruby code:
require 'Twitter'
client = Twitter::REST::Client.new do |config|
config.consumer_key = "my_key"
config.consumer_secret = "my_secret_key"
config.access_token = "my_token"
config.access_token_secret = "my_secret_token"
end
client.update("I'm tweeting with a #gem!")
I'm using 64-bit ruby 2.3.0 with the appropriate 64-bit dev kit on Windows 10.
However, a `on_complete': Bad Authentication data. (Twitter::Error::BadRequest) appears like so:
C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/twitter-6.1.0/lib/twitter/rest/response/raise_error.rb:13:in `on_complete': Bad Authentication data. (Twitter::Error::BadRequest)
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/faraday-0.11.0/lib/faraday/response.rb:9:in `block in call'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/faraday-0.11.0/lib/faraday/response.rb:61:in `on_complete'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/faraday-0.11.0/lib/faraday/response.rb:8:in `call'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/faraday-0.11.0/lib/faraday/request/url_encoded.rb:15:in `call'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/faraday-0.11.0/lib/faraday/request/multipart.rb:14:in `call'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/twitter-6.1.0/lib/twitter/rest/request/multipart_with_file.rb:21:in `call'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/faraday-0.11.0/lib/faraday/rack_builder.rb:139:in `build_response'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/faraday-0.11.0/lib/faraday/connection.rb:377:in `run_request'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/faraday-0.11.0/lib/faraday/connection.rb:177:in `post'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/twitter-6.1.0/lib/twitter/rest/request.rb:33:in `perform'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/twitter-6.1.0/lib/twitter/rest/utils.rb:50:in `perform_request'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/twitter-6.1.0/lib/twitter/rest/utils.rb:72:in `perform_request_with_object'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/twitter-6.1.0/lib/twitter/rest/utils.rb:64:in `perform_post_with_object'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/twitter-6.1.0/lib/twitter/rest/tweets.rb:158:in `update!'
from C:/tools/ruby23/lib/ruby/gems/2.3.0/gems/twitter-6.1.0/lib /twitter/rest/tweets.rb:128:in `update'
from om_tweet.rb:11:in `<main>'
Thanks in advance for your time and advice!
After copy/pasting the keys into their appropriate lines, whitespace was found to be present in the keys. Deleting the whitespace allowed the ruby file to function as designed. Thanks and kudos to Tom Lord for help and critique!

Why is my rspec test sending a get request to javascripts/sessions.js?

I have a very messy Rails app that I built some time ago that I am currently extending. This has involved a number of major changes to Ruby Version (1.9.x to 2.3.x), Rails Version (3.2.x to 5.0.x), and many other associated changes. It has a lot of cruft and I am uncertain about a lot of things going on in it at the moment.
In order to sort out this horrible mess I have created for myself I have decided to write a bunch of feature tests with RSpec and Capybara. I was making good progress until I needed to test something that used Javascript (eventually most of my feature tests will be testing Javascript).
My Rspec test looks like this so far (there is much left to complete - I just got stuck here);
feature "User registers a new customer", js: true do
scenario "Logged in user registers a new customer" do
user = FactoryGirl.create(:user)
visit_root_and_login user
fill_in 'reg_number', with: '123456'
click_button 'Look up'
end
end
In my app this triggers an AJAX call that looks up the registration number and returns a piece of Javascript that adds additional fields to the form depending on whether the customer has been previously registered or not.
What happens though is this;
Failure/Error: raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
ActionController::RoutingError:
No route matches [GET] "/javascripts/sessions.js"
# /Users/brad/.gem/ruby/2.3.1/gems/railties-5.0.1/lib/rails/rack/logger.rb:36:in `call_app'
# /Users/brad/.gem/ruby/2.3.1/gems/railties-5.0.1/lib/rails/rack/logger.rb:24:in `block in call'
# /Users/brad/.gem/ruby/2.3.1/gems/railties-5.0.1/lib/rails/rack/logger.rb:24:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/method_override.rb:22:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/runtime.rb:22:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/sendfile.rb:111:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/railties-5.0.1/lib/rails/engine.rb:522:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/urlmap.rb:68:in `block in call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/urlmap.rb:53:in `each'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/urlmap.rb:53:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/capybara-2.12.1/lib/capybara/server.rb:43:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/handler/webrick.rb:86:in `service'
# ------------------
# --- Caused by: ---
# NameError:
# uninitialized constant Selenium::WebDriver::Remote::W3CCapabilities
# /Users/brad/.gem/ruby/2.3.1/gems/capybara-2.12.1/lib/capybara/selenium/driver.rb:282:in `marionette?'
I tried adding driver: :webkit to see if anything different happened and got something slightly different;
Failure/Error: raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
ActionController::RoutingError:
No route matches [GET] "/javascripts/sessions.js"
# /Users/brad/.gem/ruby/2.3.1/gems/railties-5.0.1/lib/rails/rack/logger.rb:36:in `call_app'
# /Users/brad/.gem/ruby/2.3.1/gems/railties-5.0.1/lib/rails/rack/logger.rb:24:in `block in call'
# /Users/brad/.gem/ruby/2.3.1/gems/railties-5.0.1/lib/rails/rack/logger.rb:24:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/method_override.rb:22:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/runtime.rb:22:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/sendfile.rb:111:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/railties-5.0.1/lib/rails/engine.rb:522:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/urlmap.rb:68:in `block in call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/urlmap.rb:53:in `each'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/urlmap.rb:53:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/capybara-2.12.1/lib/capybara/server.rb:43:in `call'
# /Users/brad/.gem/ruby/2.3.1/gems/rack-2.0.1/lib/rack/handler/webrick.rb:86:in `service'
# ------------------
# --- Caused by: ---
# Capybara::ElementNotFound:
# Unable to find field "reg_number"
# /Users/brad/.gem/ruby/2.3.1/gems/capybara-2.12.1/lib/capybara/node/finders.rb:44:in `block in find'
I don't understand why "/javascripts/sessions.js" is being called. I don't have any such file and I don't make this request myself. It looks to be coming from Rack, but this is a zone of the Ruby and Rails world that I really don't understand.
Is anyone able to shed any light on this so I at least know where to start looking?
TIA
OK, I sorted this out.
It was an asset pipeline issue.
In my application.html.haml I had = javascript_include_tag "application", params[:controller] which was causing an attempt to include the file /app/assets/javascripts/sessions.js in my assets during the login process. I had no such file so created a blank one. I then had to add
%w( sessions ).each do |controller|
Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
end
to my /app/config/initializers/assets.rb to get it all working.
The same exception was being raised in my development environment in the server console but I had not noticed it and it was not stopping execution. In Capybara this exception was stopping the whole show though.

Authenticating Twitter on Rails app

I'm using the twitter gem along with amniauth to fetch a user's tweets and display them on my homepage. But when I try to grab tweets from the command line I'm getting a 'bad authentication data' error.
Gemfile:
gem 'omniauth'
gem 'omniauth-twitter'
gem 'twitter'
Twitter.rb in config/initializers:
Twitter.configure do |config|
config.consumer_key = 'key'
config.consumer_secret = 'secret'
config.oauth_token = 'token'
config.oauth_token_secret = 'secret'
end
omniauth.rb in config/initializers:
require 'omniauth-twitter'
config.omniauth :twitter, 'key', 'secret'
I've double checked my key and passwords, but I can't get it to run. I am using Spree. Here's the error:
irb(main):001:0> require 'twitter'
=> true
irb(main):002:0> Twitter.user_timeline(213747670)
Twitter::Error::BadRequest: Bad Authentication data
from /usr/local/lib64/ruby/gems/1.9.1/gems/twitter-4.6.2/lib/twitter/response/raise_error.rb:21:in `on_complete'
from /usr/local/lib64/ruby/gems/1.9.1/gems/faraday-0.8.7/lib/faraday/response.rb:9:in `block in call'
from /usr/local/lib64/ruby/gems/1.9.1/gems/faraday-0.8.7/lib/faraday/response.rb:63:in `on_complete'
from /usr/local/lib64/ruby/gems/1.9.1/gems/faraday-0.8.7/lib/faraday/response.rb:8:in `call'
from /usr/local/lib64/ruby/gems/1.9.1/gems/faraday-0.8.7/lib/faraday/request/url_encoded.rb:14:in `call'
from /usr/local/lib64/ruby/gems/1.9.1/gems/faraday-0.8.7/lib/faraday/request/multipart.rb:13:in `call'
from /usr/local/lib64/ruby/gems/1.9.1/gems/twitter-4.6.2/lib/twitter/request/multipart_with_file.rb:14:in `call'
from /usr/local/lib64/ruby/gems/1.9.1/gems/faraday-0.8.7/lib/faraday/connection.rb:247:in `run_request'
from /usr/local/lib64/ruby/gems/1.9.1/gems/faraday-0.8.7/lib/faraday/connection.rb:100:in `get'
from /usr/local/lib64/ruby/gems/1.9.1/gems/twitter-4.6.2/lib/twitter/client.rb:81:in `request'
from /usr/local/lib64/ruby/gems/1.9.1/gems/twitter-4.6.2/lib/twitter/client.rb:64:in `get'
from /usr/local/lib64/ruby/gems/1.9.1/gems/twitter-4.6.2/lib/twitter/api/utils.rb:51:in `objects_from_response'
from /usr/local/lib64/ruby/gems/1.9.1/gems/twitter-4.6.2/lib/twitter/api/utils.rb:42:in `objects_from_response_with_user'
from /usr/local/lib64/ruby/gems/1.9.1/gems/twitter-4.6.2/lib/twitter/api/timelines.rb:53:in `user_timeline'
from /usr/local/lib64/ruby/gems/1.9.1/gems/twitter-4.6.2/lib/twitter.rb:52:in `method_missing'
from (irb):2
Thanks for your help.
To fetch and display user's tweets its better to go with twitter gem.
Refer the following links for step-by-step instructions
http://shouweick.blogspot.in/2011/11/rails-3-and-twitter-api-by-shouweick.html?showComment=1381925399790#c6571680143535387130
https://gist.github.com/fnichol/867550

Error while upgrading to Rails 2.3.11 (HashWithIndifferentAccess error)

Whenever I attempt to create or update an environment that our app uses, I get the following:
NoMethodError (undefined method `base_url' for #<HashWithIndifferentAccess:0x107162f08>):
app/controllers/environments_controller.rb:64:in `check_base_url_for_https'
app/controllers/environments_controller.rb:56:in `update'
haml (3.0.22) lib/sass/plugin/rack.rb:41:in `call'
airbrake (3.0.4) lib/airbrake/rack.rb:27:in `call'
airbrake (3.0.4) lib/airbrake/user_informer.rb:12:in `call'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/server.rb:162:in `start'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/server.rb:95:in `start'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/server.rb:92:in `each'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/server.rb:92:in `start'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/server.rb:23:in `start'
/Users/jasonbodak/.rvm/rubies/ree-1.8.7-2011.03/lib/ruby/1.8/webrick/server.rb:82:in `start'
As I stated in the title, I recently upgraded to Rails 2.3.11. This error never occurred before. Here is the code in my environments_controller.rb that is being executed when the error occurs:
def check_base_url_for_https
#environment = params[:environment]
if /^https:\/\//i =~ #environment.base_url
#ajax_flash = "<ul class='notice'><li>The website you are trying to test is a secure site. If you are using self-signed SSL certificates please see our <a href='http://support.janova.us'>Support Site</a> and search for SSL for important tips on how to access your site.</li></ul>"
end
end
Does anyone know why this code (specifically the line if /^https:\/\//i =~ #environment.base_url no longer works in Rails 2.3.11?
I would like to add that the code in my app/models/environment.rb appears to be sound too:
def base_url
self[:base_url].try(:gsub, /\$/, '')
end
Does anyone see anything wrong with the code above?
I figured it out: params[:environment] was defined as a hash. Thank you, Frost, for forcing me to see this. Therefore, I changed the line #environment = params[:environment] to #environment = Environment.new(params[:environment]) and it worked.

Resources