Missing host to link to error in Rails 5.2.1 - ruby-on-rails

I've gone through every stackoverflow question regarding this error:
https://duckduckgo.com/?q=rails+Missing+host+to+link+to
All the posts mention the same solution, which is to add the config in the environment file you're working on. In my case, I added to my development.rb:
config.active_storage.service = :local
config.action_mailer.default_url_options = { host: "localhost", port: "3000" }
MyApp::Application.default_url_options = Robson::Application.config.action_mailer.default_url_options
Rails.application.routes.default_url_options = Robson::Application.config.action_mailer.default_url_options
But I still get the infamous error message:
Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
In the following locations if I try to open a file that I uploaded locally:
open(file.service_url)
or if I try to access the files from ActiveAdmin (I called the model "Attachments" and I'm using ActiveStorage)
column(:file) {|a| link_to a.file.filename, a.file.service_url}
I also tried setting "host" in a dictionary as a parameter in the above "link_to" and "open" functions. I also tried "only_path".
Nothing works.
Any help would be appreciated!
P.S.: my active storage config:
local:
service: Disk
root: <%= Rails.root.join("storage") %>
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
amazon:
service: S3
access_key_id: S3_ACCESS_KEY_ID
secret_access_key: S3_SECRET_ACCESS_KEY
bucket: S3_BUCKET
region: S3_REGION
UPDATE
Trying to use rails_representation_url but getting an error undefined method 'variation' for ActiveStorage::Attached
class Attachment < ApplicationRecord
include Rails.application.routes.url_helpers
has_one_attached :file
....
def with_uploaded_file
tempfile = Tempfile.open([file.filename.to_s, File.extname(file.filename.to_s)]) do |file_temp|
file_temp.binmode unless file.content_type =~ /text/
require 'open-uri'
# file_temp.write(open(file.service_url).read)
file_temp.write(open(rails_representation_url(file, only_path: true)).read)
file_temp
end
begin
yield(tempfile)
ensure
tempfile.unlink
end

I upgraded Rails from 5.1 to 5.2 and had same problem.
Solution: https://github.com/rails/rails/issues/32866
So when you have your ActiveRecord variant instead of
variant.service_url
do
rails_representation_url(variant, only_path: true)

Related

ActiveStorage - has_one_attached ignores service option

In my Ruby on Rails 6.1.3.2 application, I'm trying to has_one_attached service option to upload one of the model attachments to the separate S3 bucket.
Here is how my storage.yml looks like:
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
local:
service: Disk
root: <%= Rails.root.join("storage") %>
amazon:
service: S3
access_key_id: <%= ENV['AWS_ACCESS_KEY_I'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
region: us-east-2
bucket: <%= ENV['AWS_BUCKET'] %>
amazon_logos_images:
service: S3
access_key_id: <%= ENV['AWS_ACCESS_KEY_I'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
region: us-east-2
bucket: <%= ENV['AWS_LOGOS_BUCKET'] %>
In my production.rb I have the following Active Storage configuration:
config.active_storage.service = :amazon
My Logo model looks like this:
class Logo < ApplicationRecord
has_one_attached :image, service: :amazon_logos_images
end
Unfortunately, when I create a new Logo record, the image is uploaded to the amazon bucket instead of amazon_logos_images. Any idea why the service option is ignored by the has_one_attached method?
If you come from 6.0:
If our project is already using Active Storage and when we upgrade to Rails 6.1, we should run rake app:update to make sure service_name column is added to the internal ActiveStorageBlob model.
https://blog.saeloun.com/2020/02/03/rails-allows-configure-service-for-attachments-to-activestorage.html
Otherwise check that AWS_LOGOS_BUCKET is properly being populated (i.e. is not the wrong bucket)
Are you using direct upload? If it is, 6.1 can't support direct uploads to multiple services, you need to upgrade to 7.0.

NoMethodError in Rails::Conductor::ActionMailbox::InboundEmailsController#create + RubyonRails 6

Any idea why I'm getting this errors on my localhost when I send an inbound email?
It is not a part of code that I can fix. Maybe some settings?
http://localhost:3000/rails/conductor/action_mailbox/inbound_emails
I've just experienced this in an application that didn't use active_storage before adding in action_mailbox (which depends on active_storage).
The solution that worked for us was to specify an active_storage config like:
config/storage.yml
local:
service: Disk
root: <%= Rails.root.join("storage" %>
And reference which active storage config to load the environment:
config/environments/development.rb
Rails.application.configure do
# ... other stuff
config.active_storage.service = :local
end

Rails - Activestorage causing rails configuration failure

I am having an issue trying to deploy my app to heroku with rails active storage. In development I have no issues using
config.active_storage.service = :local
and all works as it should.
However in my production.rb file I have set config.active_storage.service = :amazon
and followed the set up guides.
My storage.ymlis as follows:
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
local:
service: Disk
root: <%= Rails.root.join("storage") %>
amazon:
service: S3
access_key_id: <%= ENV['S3_ACCESS_KEY'] %>
secret_access_key: <%= ENV['S3_SECRET_ACCESS_KEY'] %>
region: <%= ENV['S3_REGION'] %>
bucket: <%= ENV['S3_BUCKET_NAME'] %>
When I run git push heroku master, the app will deploy, but the following error will appear in the logs: "Detecting rails configuration failed".
I am unable to open the app and the herkou log will display the following error: "Missing configuration for the :amazon Active Storage service. Configurations available for [:test]".
This same error occurs if I change
config.active_storage.service = :amazon
to
config.active_storage.service = :local
however if I change it to
config.active_storage.service = :test
the app will deploy without error and I am able to open the app and upload files as expected.
I have trawled the web but haven't seen anyone else with this error, so any comments or thoughts are appreciated.
Thanks in advance.
The problem is the indentation in storage.yml
test: local: are indented one space, and amazon: is indented two spaces.
I had the same problem, and it was hard to notice an extra space. In YAML the spaces matter, but Ruby devs are not accustomed to having the spaces matter.

Cannot load Rails.config.active_storage.service

I'm setting up a new rails 5.2 app utilising Active Storage and using AWS for the hosting of images in production.
However, I'm having an issue with the app reading the credentials:
2018-07-06T08:11:52.625415+00:00 app[web.1]: ! Unable to load application: Aws::Sigv4::Errors::MissingCredentialsError: Cannot load `Rails.config.active_storage.service`:
2018-07-06T08:11:52.625432+00:00 app[web.1]: missing credentials, provide credentials with one of the following options:
2018-07-06T08:11:52.625435+00:00 app[web.1]: - :access_key_id and :secret_access_key
2018-07-06T08:11:52.625437+00:00 app[web.1]: - :credentials
2018-07-06T08:11:52.625479+00:00 app[web.1]: - :credentials_provider
This is an existing S3 Bucket which I created a new user just for this app. I'm happy with the CORS etc.
The user is set up under the S3FullAccess group.
I've edited the credentials in my app via $EDITOR="atom --wait" rails credentials:edit
The contents of the file:
aws:
access_key_id: [my access key]
secret_access_key: [my secrect key]
# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: [my secret key base]
Appreciate this is in YAML format, I have played with using one space, and one tab on the keys, but this doesn't seem to make a difference.
When I save and close the file, the terminal writes New credentials encrypted and saved.
I also have gem 'aws-sdk-s3', '~>1', require: false installed.
And config/storage.yml
test:
service: Disk
root: <%= Rails.root.join("tmp/storage") %>
local:
service: Disk
root: <%= Rails.root.join("storage") %>
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)
amazon:
service: S3
access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
region: eu-west-2
bucket: [mybucket]
Any suggestions on what I might be doing wrong?
I think you're missing the master.key file in your server. Check your local repo in config/master.key (this file is added to your .gitignore by default).
Add this file to your server or set ENV["RAILS_MASTER_KEY"].
This worked for me on Heroku: in "Settings > Config vars" add a RAILS_MASTER_KEY key, with the content of your your config/master.key file (from your Rails app) as the value.
Go into config/environments/development.rb and make sure you have this:
config.active_storage.service = :local
in config/environments/production you should have
config.active_storage.service = :amazon
amazon is for Amazon S3. It can be changed to whichever storage service you want to use. See the Rails docs for more info on storage services and Active Storage.
In Rails 5.2, do the following:
Step 1. In config/storage.yml add
amazon:
service: S3
access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
region: ap-south-1
bucket: my-bucket
Step 2:
Copy config/credentials.yml.example to config/credentials.yml
and add the following in config/credentials.yml
development:
AWS_ACCESS_KEY_ID: YOUR-KEY
AWS_SECRET_ACCESS_KEY: YOUR-SECRET
credentials.yml is already added to .gitignore by default.
Step 3:
In application.rb
Uncomment the following:
# Load ENV variables from credentials.yml file
config.before_configuration do
env_file = File.join(Rails.root, 'config', 'credentials.yml')
YAML.load(File.open(env_file))[Rails.env].each do |key, value|
ENV[key.to_s] = value
end if File.exists?(env_file)
end
Restart the server and try to upload again.
Another way of solving this issue (worked for me)
Run rake secret in the console
copy the key
go to config and open application.rb
inside the class type: config.secret_key_base = "paste the output of rake secrete"
I had the same error. In my case the problem was neither with configs, nor with master.key. Starting Redis server fixed the error. For MacOS:
$> redis-server

Recaptcha gem error "No site key specified."

I am trying to setup Recaptcha in my rails 5 application as it's described in the documentation but it fails.
I use this gem: recaptcha (4.6.6), ruby 2.5.0 and rails 5.1.4
In view form:
<%= flash[:recaptcha_error] %>
<%= recaptcha_tags %>
In devise registrations controller:
prepend_before_action :check_captcha, only: :create
private
def check_captcha
unless verify_recaptcha
self.resource = resource_class.new sign_up_params
resource.validate # Look for any other validation errors besides Recaptcha
respond_with_navigational(resource) { redirect_to new_user_registration_path }
end
end
In my initializers/recaptcha.rb
Recaptcha.configure do |config|
config.site_key = Rails.application.config_for(:recaptcha)['site_key']
config.secret_key = Rails.application.config_for(:recaptcha)['secret_key']
end
In my recaptcha.yml:
default: &default
site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %>
secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %>
development:
<<: *default
test:
<<: *default
staging:
<<: *default
production:
<<: *default
In /etc/environments:
# RECAPTCHA
RECAPTCHA_SITE_KEY=6Lfg3ksUAAAAABOD_OXCtPO60*******
RECAPTCHA_SECRET_KEY=6Lfg3ksUAAAAAOmFGdAxdo8*******
PROBLEM
After adding ENV variables to /etc/environments, I exported it with this command:
for line in $( cat /etc/environment ) ; do export $line ; done
Then I check that Recaptcha module is configured correctly:
/home/deploy/apps/app_name/current$ bundle exec rails c
Loading staging environment (Rails 5.1.4)
2.5.0 :001 > Recaptcha::Configuration.new
=> #<Recaptcha::Configuration:0x0000000006601908 #skip_verify_env=["test", "cucumber"], #handle_timeouts_gracefully=true, #secret_key="6Lfg3ksUAAAAAOmFGdAxdo8H*************", #site_key="6Lfg3ksUAAAAABOD_OXCtPO*************">
2.5.0 :002 > Recaptcha::Configuration.new.site_key!
=> "6Lfg3ksUAAAAABOD_OXCtPO*************"
Also, I see these ENV variables when I run printenv command (so it's really loaded)
After that, I restarted rails and got an error
No site key specified.
/home/deploy/apps/app_name/shared/bundle/ruby/2.5.0/gems/recaptcha-4.6.6/lib/recaptcha/configuration.rb:47:in `site_key!'
/home/deploy/apps/app_name/shared/bundle/ruby/2.5.0/gems/recaptcha-4.6.6/lib/recaptcha/client_helper.rb:79:in `recaptcha_components'
/home/deploy/apps/app_name/shared/bundle/ruby/2.5.0/gems/recaptcha-4.6.6/lib/recaptcha/client_helper.rb:15:in `recaptcha_tags'
/home/deploy/apps/app_name/releases/20180310222304/app/views/users/registrations/new.html.erb:27:in `block in _app_views_users_registrations_new_html_erb___216558772140569572_69973306795360'
/home/deploy/apps/app_name/shared/bundle/ruby/2.5.0/gems/actionview-5.1.4/lib/action_view/helpers/capture_helper.rb:39:in `block in capture'
/home/deploy/apps/app_name/shared/bundle/ruby/2.5.0/gems/actionview-5.1.4/lib/action_view/helpers/capture_helper.rb:203:in `with_output_buffer'
/home/deploy/apps/app_name/shared/bundle/ruby/2.5.0/gems/actionview-5.1.4/lib/action_view/helpers/capture_helper.rb:39:in `capture'
/home/deploy/apps/app_name/shared/bundle/ruby/2.5.0/gems/actionview-5.1.4/lib/action_view/helpers/form_helper.rb:450:in `form_for'
/home/deploy/apps/app_name/releases/20180310222304/app/views/users/registrations/new.html.erb:21:in `_app_views_users_registrations_new_html_erb___216558772140569572_69973306795360'
/home/deploy/apps/app_name/shared/bundle/ruby/2.5.0/gems/actionview-5.1.4/lib/action_view/template.rb:157:in `block in render'
I am posting here in case someone is looking for a Rails 5.2 solution to setting up Recaptcha keys. This solution utilizes the new config/master.key and config/credentials.yml.enc encryption file.
Add the Recaptcha keys to the credentials.yml.enc file by editing the file in your local terminal:
EDITOR="vim" rails credentials:edit
After adding the keys to the credentials file (see example below), save and exit the file. Upon exit, the credentials.yml.enc file will then be automatically encrypted. The master.key is necessary for decryption by your application. Before encryption:
recaptcha_site_key: 6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy
recaptcha_secret_key: 6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxx
3. Create a file named config/recaptcha.rb in your Rails application and add the following code to it:
Recaptcha.configure do |config|
config.site_key = Rails.application.credentials.dig(:recaptcha_site_key)
config.secret_key = Rails.application.credentials.dig(:recaptcha_secret_key)
end
This solution works locally and on Ubuntu/nginx in production. You won't need a gem or environment variables for it to work. If the master.key fails to decrypt, you may need to delete both the credentials.yml.enc file and possibly even the master.key file, then repeat this process locally (EDITOR="vim" rails credentials:edit, etc.) before copying over a new master.key to production and re-deploying.
I still don't know what is the cause of the "No site key specified" error.
I really don't like gem 'recapthca' works directly with ENV variables,
and also I spent too much time on investigations.
So, I decided to not use this gem and write my own code.
I use only Invisible Recaptcha in my application.
Config file (loads secret and site keys)
# /config/recaptcha.yml
default: &default
site_key: <%= ENV["RECAPTCHA_SITE_KEY"] %>
secret_key: <%= ENV["RECAPTCHA_SECRET_KEY"] %>
development:
<<: *default
test:
<<: *default
staging:
<<: *default
production:
<<: *default
Application helper (a button with Recaptcha helper)
# /app/helpers/application_helper.rb
module ApplicationHelper
def submit_with_recaptcha(text, custom_options)
unless custom_options[:data].has_key?(:form_id)
raise "Data Form Id option not found ('{data: {form_id: 'id_without_dash'}')."
end
options = {
type: 'button',
data: {
form_id: custom_options[:data][:form_id],
sitekey: recaptcha_site_key,
callback: "submit#{custom_options[:data][:form_id].camelize}#{Time.current.to_i}"
},
class: (custom_options[:class].split(' ') + ['g-recaptcha']).uniq.join(' ')
}
script_code = <<-SCRIPT
function #{options[:data][:callback]}() {
document.getElementById('#{options[:data][:form_id]}').submit();
}
SCRIPT
javascript_tag(script_code) + content_tag(:div, class: 'recaptcha_wrapper'){ submit_tag(text, options) }
end
private
def recaptcha_site_key
Rails.application.config_for(:recaptcha)['site_key']
end
end
Verification service (as it uses external API)
# app/services/google_recaptcha/verification.rb
module GoogleRecaptcha
# https://developers.google.com/recaptcha/docs/verify
class Verification
# response - params['g-recaptcha-response'])
def self.successful?(recaptcha_params, remoteip)
verify_url = URI.parse('https://www.google.com/recaptcha/api/siteverify')
verify_request = Net::HTTP::Post.new(verify_url.path)
verify_request.set_form_data(
response: recaptcha_params,
secret: secret_key,
remoteip: remoteip
)
connection = Net::HTTP.new(verify_url.host, verify_url.port)
connection.use_ssl = true
Rails.logger.info '[RECAPTCHA] Sending verification request.'
verify_response = connection.start { |http| http.request(verify_request) }
response_data = JSON.parse(verify_response.body)
Rails.logger.info "[RECAPTCHA] Verification response is#{' not' unless response_data['success']} successful."
response_data['success']
end
private
def self.secret_key
Rails.application.config_for(:recaptcha)['secret_key']
end
end
end
Controller Concern (Recaptcha verification in before_action)
# app/controllers/concerns/recaptchable.rb
module Recaptchable
extend ActiveSupport::Concern
included do
before_action :verify_recaptcha, only: [:create]
end
private
def verify_recaptcha
unless GoogleRecaptcha::Verification.successful?(recaptcha_params['g-recaptcha-response'], request.remote_ip)
render :new
return
end
end
def recaptcha_params
params.permit(:'g-recaptcha-response')
end
end
Usage
Add concern to your controller:
class MyController < ShopController
include Recaptchable
end
Add www.google.com/recaptcha/api.js javascript to your page
Add submit_with_recaptcha helper into your form
<%= form_for #delivery, url: users_delivery_path, method: 'post' do |f| %>
<%= submit_with_recaptcha t('order.deliver.to_confirmation'), data: {form_id: 'new_delivery'}, class: 'btn-round' %>
<% end %>
<%= javascript_include_tag "https://www.google.com/recaptcha/api.js?hl=#{I18n.locale}", 'data-turbolinks-track': 'reload' %>
That's it.
Note: I'm posting this answer here for people who may find this question. Here is how I solved the problem.
I use local_env.yml for my environment variables. I just started using the gem and added RECAPTCHA_SITE_KEY & RECAPTCHA_SECRET_KEY to local_env.yml. I got the same error.
It took a bit to figure out that the gem directly used the variables. I ended up putting the following statements in ~/.bashrc similar to what the documentation said but without the quotes around the values.
export RECAPTCHA_SITE_KEY=6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy
export RECAPTCHA_SECRET_KEY=6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx
I host my applications on Heroku. I executed the following terminal commands to set my environment variables in Heroku.
heroku config:set RECAPTCHA_SITE_KEY=‘6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy’
heroku config:set RECAPTCHA_SECRET_KEY=‘6LcGuI4U6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxxAAAAGAWMYRKFGfHUCSD0SPrMX2lfyl9’
Are you using nginx? Nginx removes ENV vars (except TZ) and it seems that the recaptcha gem is particularly sensitive to this. From experience, when using the dotenv gem other ENV vars work ok, recaptcha ENV vars are ignored.
You can solve the issue by adding the env vars to the top of your nginx.conf.
env RECAPTCHA_SITE_KEY=value1;
env RECAPTCHA_SECRET_KEY=value2;
Here's nginx's documentation on the matter.

Resources