Rails 4: How to use ApplicationHelper methods in mailer view - ruby-on-rails-4

I have a helper defined in my application_helper.rb that I would like to use in my mailer view, but just doing
<%= helper_method(param) %>
in the mailer_view.html.erb file gets me an 'undefined method' error.
Is there another way to do this? I would hate to have to put the same helper somewhere else.
Thanks.

Apparently this has been asked before (who knew!) :). The answer is to include
helper ApplicationHelper
in the example_mailer.rb file:
class ExampleMailer < ApplicationMailer
helper ApplicationHelper
...
end

Related

Rails: How to check for attributes with polymorphic? (Prints okay, won't allow conditional)

Going back to accessing user attributes (name, e-mail, avatar, etc) for the comments section ("identify user as commenter"), why does it let me print out some values but not use them in conditionals?
Why can I do this? (Prints the avatar next to the comment as it should)
<%= image_tag comment.user.avatar.url, size: "64" %>
But not this? (Won't let me check if there's an avatar or not first)
<% if comment.user.avatar.url.empty/blank/nil/present? %>
So if a commenter hasn't uploaded an avatar yet, it returns:
undefined method \'avatar\' for nil:NilClass
Is there a method I need to define in a controller, or a scope in a model, or is there another way of checking in this situation?
Thank you.

url_for in an email sent by a rake task in rails 4

I have a rake task that sends out daily digest emails of player activity during a day. (See example code below.) If I run PlayerActivityMailer.activity_report.deliver in my console, everything works just fine. However, when I try to invoke the rake task, I get the following error:
rake aborted!
ActionView::Template::Error: arguments passed to url_for can't be handled.
Please require routes or provide your own implementation
After doing some research, I found that in Rails 4, they totally nerfed ActionView::Helpers::UrlHelper.url_for (http://apidock.com/rails/v4.1.8/ActionView/Helpers/UrlHelper/url_for - notice the giant red minus sign under the 4.0.2). If you look at the source, you can see the error I'm seeing - it no longer takes options. As far as I can tell, that functionality still exists in other url_fors, such as the one in ActionDispatch::Routing::UrlFor. Also, the error message suggests including Rails.application.routes.url_helpers.
What I've tried
include ActionDispatch::Routing::UrlFor in both the rake task (inside the task) and the mailer (both at the same time, and each separately)
include Rails.application.routes.url_helpers in the same places and configurations, both with and without the UrlFor include.
The error still persists. My guess is that the page view is still insisting on using the ActionView::Helpers::UrlHelper version of url_for. I don't think I can include things actually in the views (which is sloppy looking and hacky even if I could).
Example Code
(heavily sanitized)
config/environtments/development.rb:
config.action_mailer.default_url_options = { host: 'localhost:3000' }
lib/tasks/player.rake:
namespace :player do
task :activity => :environment do
PlayerActivityMailer.activity_report.deliver
end
end
app/mailers/player_activity_mailer.rb:
class PlayerActivityMailer < ActionMailer::Base
def activity_report
#activities = PlayerActivity.all
mail(to: 'foo#bar.com', subject: 'activity report')
end
end
app/views/player_activity_mailer/activity_report.html.erb:
<% #activites.each do |activity| %>
Player: <%= link_to activity.player.name, player_url(id: activity.player.id) %>
...
<% end %>
I also have a model Player, resources :players in my routes.rb file, and a PlayerActivity class with an association to Player.
I'm currently using the (really horrifying) workaround of #base_url = Rails.configuration.action_mailer.default_url_options[:host] in my mailer action and "http://#{#base_url}/players/#{activity.player.id}" in my view instead of the player_url part.
Help!
Have you tried passing just your player in the URL? Like this:
<% #activites.each do |activity| %>
Player: <%= link_to activity.player.name, player_url(activity.player) %>
<% end %>

How do I use Ruby refinements in Rails views?

I have a Rails 4 project using Ruby 2.0. I've defined some refinements. Putting
<% using MyRefinements %>
at the top of the view files causes the error "undefined method 'using'".
When I add:
using MyRefinements
At the top of my controller (above the class declaration), I can successfully use the refinement in the controller, but I get an 'undefined method' error if I try to use it in the view.
Thanks!
Unfortunately, this does not seem possible. For posterity, I'm documenting the things I tried that didn't work:
In the view:
<% using MyRefinements %>
In the controller (each tried separately):
using MyRefinements
helper :MyRefinements
helper_method :MyRefinements
helper { using MyRefinements }
In the helper:
using MyRefinements
Note that refinements become available in the controller and in the helper, but never in the view.
Too bad.
By using 'using' you can import class refinements from module into the current class or module definition.
You can not include it in view file by 'using'.
if you want to use it in view you can do following in your controller(I have not tested it):
using MyRefinements
helper :MyRefinements OR helper_method :MyRefinements

How to use activemodel to validates date_time_select

I am using rails 4.0
I wonder how to validate date_select with activemodel
let's suppose I have the code as follow
app/models/book.rb
class Book
include ActiveModel::Model
include ActiveModel::Validations
attr_accessor :title, :written_on
validates :title, presence: true, allow_blank: false
# How validates :written_on if I use date_select Please look in my view below
end
app/controllers/books.rb
class BooksController < ApplicationController
#...
def new
#book = Book.new
end
def create
#book = Book.new(book_params)
if #book.valid?
#Do something
end
end
#...
end
app/views/books/new.html.erb
<% form_for #book do |f| %>
...
<%= f.date_select :written_on %>
...
<% end %>
I have also try adding
attr_accessor 'written_on(1i)'
to my book model but I got the error invalid attribute name 'written_on(1i)'
Really appreciated for the help here.
Just to clarify, I think you're asking why you're not even able to set the written_on attribute, let alone validate it-- when I used your exact code locally and tried to create a new book, on submit I got undefined method `written_on(1i)=' for Book.
This is because the Book model isn't inheriting from ActiveRecord::Base; you're just including ActiveModel::Model and ActiveModel::Validations. The Rails guide on form helpers says "when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type."
So I started looking through the Rails source to see where this functionality was implemented, and it's currently in ActiveRecord::AttributeAssignment. There is currently an open pull request that moves this functionality to ActiveModel so that in cases like yours, you'd be able to use it by including ActiveModel::AttributeAssignment.
I'm not sure what you can do until that gets merged in and released. I tried including ActiveRecord::AttributeAssignment and still got the same error, and looking at the pull request, it doesn't seem to be that straightforward. You could fork Rails and apply that pull request, but you'd have to maintain your own Rails for a while until that lands, then get back on a released version.

How do I make a method available inside a partial?

I'm a rails beginner learning rails 4 and I'm trying to learn by doing. I'm making a simple blog that I want some simple user authentication on. I'm trying to learn here, so I don't want to implement Devise, etc. I have a header partial that takes care of my site header and I'm trying to put a link to logout that only shows if a user is logged in. I have a simple session controller that has a new action for the signup form, a create action that sets the current user after matching the email and password and sets session[:user_id] = #current_user.id, and a destroy action that nils out the session. In my application controller I have a method like this
def logged_in?
!session[:user_id].nil?
end
In my _header.html.erb partial, I have
<% if logged_in? %>
(My link)
<% end %>
When I load the page it tells me it can't find the "logged_in?" method. Anyone know why? Thanks.
Methods on controllers are by default not exposed to the views (which your partial is part of).
2 solutions:
Create your logged_in? method as a helper method, for example in an AuthenticationHelper. Doing this you cannot access it from controllers, though.
Expose your controller method to the view using helper_method:
class ApplicationController < ActionController::Base
helper_method :logged_in?
def logged_in?
[...]
end
end
Couldn't you just use:
if #current_user