I have an application (rails 3.2) with haml (3.1.4) emails. In the email template I wanted to use link_to, but apparently none of those 4 is working in production:
#{link_to(my_models_url)}
= link_to(my_models_url)
/ #url set to my_models_url
#{link_to(#url)}
= link_to(#url)
On development mode everything works fine, but in production, I keep getting the following error:
No route matches {}
actionpack (3.2.0) lib/action_dispatch/routing/route_set.rb:503:in `raise_routing_error'
It works when I use helper methods before:
/ #my_link set to link_to(my_models_url)
#{#my_link}
= #my_link
But this is not convenient, if there are more links in the email and in general I don't see why any of the first 4 options should not be ok. I have no idea where is this problem comming from. I would appreciate any help on this...
SOLUTION:
Thanks to iWasRobbed I found where my problems were:
all {resource}_path and {resource}_url have to be set in mailers as #variables, they are not available in mailer views
apparently link_to() method in mailer is not the same as in rails views... it always needs 2 arguments, so instead of link_to(#link) available in views, one needs to do link_to(#link,#link). Pffff...
You need to declare the URL within the mailer.rb file. This isn't a HAML issue so much as it's just the way ActionMailer was designed.
def some_mailer_here
#url = my_models_url
end
Then in your mailer view you can do:
= link_to("My models URL", #url)
http://guides.rubyonrails.org/action_mailer_basics.html#generating-urls-in-action-mailer-views
Related
background
I am trying to migrate an old Rails 2 (Ruby 1.8.7) app to Rails 3.0.9 (Ruby 1.9.3) — yes it's a stepping stone to get it to Rails 4 and Ruby 2.2 — and I've hit the following problem.
The original app makes extensive use of an old Active Form gem which we've hacked slightly to support Ruby 1.9.
It mostly works, but there appears to be some issue with how it interacts with the ActionView::Helpers::AssetTagHelper that's part of ActionPack 3.0.9.
In my specific case I have an ActiveForm::DateCalendarSection (built dynamically) which subclasses ActiveForm::Element::Section, which, according to self.class.ancestors, is a subclass of ActionView::Helpers::AssetTagHelper. Looking at the ActiveForm source however there is no mention of AssetTagHelper or asset_tag_helper so how they are actually connected remains a mystery to me.
Problem
Calls to the method image_path result in an error
undefined local variable or method 'config'
The call to image_path is simply a wrapper around a call to compute_public_path in ActionView::Helpers::AssetTagHelper
# File actionpack/lib/action_view/helpers/asset_tag_helper.rb, line 741
def compute_public_path(source, dir, ext = nil, include_host = true)
return source if is_uri?(source)
source += ".#{ext}" if rewrite_extension?(source, dir, ext)
source = "/#{dir}/#{source}" unless source[0] == //
source = rewrite_asset_path(source, config.asset_path)
has_request = controller.respond_to?(:request)
if has_request && include_host && source !~ %{^#{controller.config.relative_url_root}/}
source = "#{controller.config.relative_url_root}#{source}"
end
source = rewrite_host_and_protocol(source, has_request) if include_host
source
end
Diving into that with binding.pry it's evident that config is indeed not defined. Likewise controller is also not defined.
Question
What would have changed between Rails 2 and Rails 3, such that methods from ActionView::Helpers::AssetTagHelper can no longer access Rails' config or the current controller?
It could be you don't have enough of the Rails support loaded. Maybe pull in everything inside your gem with
require "active_support/all"
Alternatively, have a look at how modern Rails hooks things up via a proxy to the config:
https://github.com/rails/rails/pull/12622/files
I feel like this should be a simple problem, but I'm pulling my hair out trying to track it down. I'm installed the chargify_api_ares gem, but can't do even basic things such as
Chargify::Subscription.create
As I get this path error. I feel like this must be a gem issue somehow but don't know where to go from here.
UPDATE: bundle show chargify_api_ares shows the correct path, I just somehow can't access it. Still trying random environment related things.
Looks like this is the source of the problem, in active_resource\base.rb:
# Gets the \prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1.json</tt>)
# This method is regenerated at runtime based on what the \prefix is set to.
def prefix(options={})
default = site.path
default << '/' unless default[-1..-1] == '/'
# generate the actual method based on the current site path
self.prefix = default
prefix(options)
end
As I understand it, Chargify.subdomain should be setting the site.path, but I don't understand activeresource well enough yet to know what's happening and will continue to dig.
I too had the same issue.
I executed the following on the console
Chargify.configure do |c|
c.api_key = "<<api_key>>"
c.subdomain = "<<subdomain>>"
end
After that performing any Chargify console commands went through fine.
I want to define a function available_translations which lists the translations I have made for my application into the I18n module.
I tried putting the following into the file lib/i18n.rb, but it doesn't work when I try to use it from the rails console:
module I18n
# Return the translations available for this application.
def self.available_translations
languages = []
Dir.glob(Rails.root.to_s + '/config/locales/*.yml') do |filename|
if md = filename.match #^.+/(\w+).yml$#
languages << md[1]
end
end
languages
end
end
Console:
ruby-1.9.2-p290 :003 > require Rails.root.to_s + '/lib/i18n.rb'
=> false
ruby-1.9.2-p290 :004 > I18n.available_translations
NoMethodError: undefined method `available_translations' for I18n:Module
...
Besides solving my concrete problem, I would be very pleased to learn how this whole module thing in Ruby on Rails works because it still confuses me, so I would appreciate links to the docs or source code very much.
Either of these will solve your problem:
move the code to config/initializers/i18n.rb, or
require your file from config/application.rb, or
name your class otherwise (to trigger autoload)
The code in lib/i18n.rb wil not be loaded by autoload since I18n name will be already loaded, so either you load it yourself or change the class name (and file name) so the new name will trigger autoload behavior.
BTW, the I18n.available_locales() method is presented in rails.
I would like to alter the Message-ID header that is in the header portion of an email sent from a Ruby on Rails v3 application using ActionMailer.
I am using Sendmail on localhost for mail delivery.
Do I configure this in Sendmail or ActionMailer?
Where do I configure this (if it is ActionMailer): a file in config/ folder or a file in app/mailers/ folder?
Teddy's answer is good, except that if you actually want each message to have a different ID, you need to make the default a lambda. In the first block of code in his answer, it calculates the message-ID once, at init, and uses the same one for every message.
Here's how I'm doing this in my app:
default "Message-ID" => lambda {"<#{SecureRandom.uuid}##{Rails.application.config.mailgun_domain}>"}
... with the domain taken from a custom app config variable (and using SecureRandom.uuid, which is a little more straightforward than a SHA-2 based on the timestamp IMO.)
I usually prefer generating the message-id with a UUID. Assuming you have the uuid gem:
headers['Message-ID'] = "<#{ UUID.generate }#example.com>"
Also you should note that according to RFC 2822 the message-id should be placed inside "<" and ">"
In Rails 4+ (or just Ruby 2.0+) the folowing syntax is working correctly:
default "Message-ID" => ->(v){"<#{Digest::SHA2.hexdigest(Time.now.to_i.to_s)}#yourdomain.com>"}
Tested this with MailCatcher.
I figured this out. The easiest way to do is to use the default method at the top of the mailer class file.
Example:
require 'digest/sha2'
class UserMailer < ActionMailer::Base
default "Message-ID"=>"#{Digest::SHA2.hexdigest(Time.now.to_i.to_s)}#yourdomain.com"
# ... the rest of your mailer class
end
However, I found this difficult to test, so I wrote a private method and used the sent_at time instead of Time.now:
def message_id_in_header(sent_at=Time.now)
headers["Message-ID"] = "#{Digest::SHA2.hexdigest(sent_at.to_i.to_s)}#yourdomain.com"
end
And I simply called that method before calling the mail method. This made it easy to pass a sent_at parameter from my test and verify a match in email.encoded.
#jasoncrawford is almost right. The problem is that the mailgun_domain attribute may not be able at development environment, so it is better to access the ActionMailer configs.
default "Message-ID" => lambda {"<#{SecureRandom.uuid}##{ActionMailer::Base.smtp_settings[:domain]}>"}
I'm struggling to get my app to display a timeline of feeds from my app. So far I've used the oauth-plugin, oauth and twitter gems (for rails3) to get it authorised. This has worked just fine.
Now I'm struggling when I try and connect.
I end up with an error:
uninitialized constant Twitter::OAuth
Have checked I don't have another action calling twitter (as in another post here). But so far, no luck.
Hope someone can help!
Edit -
I forgot to mention I'm using Devise to authenticate my users. Have tried inserting:
require 'twitter'
But still no success..
-- EDIT TWO --
Found a solution on the twitter gem git site about depreciating this in version 1.0.
I've now replaced the code in my twitter_token.rb file with:
def client
unless #client
#twitter_oauth=Twitter::Client.new(:TwitterToken.consumer.key,:TwitterToken.consumer.secret)
#twitter_oauth.authorize_from_access(token,secret)
#client=Twitter::Base.new(#twitter_oauth)
end
Which gets rid of that error but now leads to another :(
undefined method `consumer' for :TwitterToken:Symbol
I have also tried this:
def client
unless #client
#twitter_oauth=Twitter::Client.new(:oauth_token =>'TwitterToken.consumer.key', :oauth_token_secret=>'TwitterToken.consumer.secret')
#twitter_oauth.authorize_from_access token,secret
#client=Twitter::Base.new(#twitter_oauth)
end
Which gives the following error:
undefined method `authorize_from_access' for #<Twitter::Client:0x00000102da1530>
Any ideas? I'm going insane!
I'm going to answer my own question here - if it helps one person, it's worth it considering I lost three days to it.
Using the latest twitter gem, devise and oauth-plugin. I was seeing a lot of errors. The latest twitter_token controller on the oauth-plugin site does not work, even though it's been updated for a recent twitter gem..
In the end, I deleted my entire twitter_token.rb file and started again:
require 'twitter'
class TwitterToken < ConsumerToken
TWITTER_SETTINGS={:site=>"http://api.twitter.com", :request_endpoint => 'http://api.twitter.com',}
def self.consumer
#consumer||=OAuth::Consumer.new credentials[:key],credentials[:secret],TWITTER_SETTINGS
end
def client
Twitter.configure do |config|
config.consumer_key = TwitterToken.consumer.key
config.consumer_secret = TwitterToken.consumer.secret
config.oauth_token = token
config.oauth_token_secret = secret
end
#client ||= Twitter::Client.new
end
end
You can then update twitter using something like this:
<%= current_user.twitter_token.client.update("At last it's working!") %>
Also, make sure you're using the rails3 branch of the oauth-plugin..