Rails 4 Mailer Uninitialized Constant - ruby-on-rails

I am trying to setup a mailer to where when a listing's available date is today, it will fire off a mailer. To do that, I am using Date.today. The other relevant code and error is below. Thanks in advance.
availabke_date_mailer.rb
class ListingAvailableDateMailer < ActionMailer::Base
default from: "Nooklyn <help#nooklyn.com>"
def listing_available_expire(listing, agent)
#listing = listing
#agent = agent
mail to: "#{agent.email}", subject: 'Availability of your listing needs to be changed!'
end
end
listing_available_expire_notification.html.erb:
Hiya <%= #agent.first_name %>,<br><br>
The Available Date for your listing has passed. Please make the necessary changes.<br><br>
Listing: <%= link_to #listing.short_address, #listing, target: "_blank" %><br><br>
Available Date: <%= #listing.date_available %><br><br>`
available_date.rake:
namespace :listings do
desc "Send a message to an agent if the available date on their listing has passed"
task listing_available_expire: :environment do
Listing.all.each do |listing|
if listing.date_available == Date.today
ListingAvailableDateMailer.listing_available_expire(listing,listing.listing_agent).deliver_now
end
end
end
end
Error:

Rename your availabke_date_mailer.rb and store it at the correct location:
app/mailers/listing_available_date_mailer.rb
Rails does a lot of magic for you, but the magic only works if you follow its conventions. One of the conventions that allows autoloading and removes the need to require all files manually is that class names (in camelcase) have to match the name of the file (in underscore) in which they are defined.
In a next step, you will have to rename your view. Because following Rails conventions it needs to be named like this:
app/views/listing_available_date_mailer/listing_available_expire.html.erb
Read about the Action Mailer Basics in the Rails Guides.

Another reason for this error is if you try to run something like
UserMailer.signup_confirmation(#user).deliver
NameError: uninitialized constant UserMailer
from the rails console.
Note that the exact same code will work from the controller.
A simple way to test such code is to simply place it in a controller action that doesn't require any effort to execute, for example, the users show view is a good candidate, so simply loading that page will cause an email to send

Related

Failing Rails test based on lack of set session variable - how to set in Rails 5.2?

I have the following very simple test which has always passed.
test "should get index" do
sign_in #user
get companies_url
assert_response :success
end
However, I'm now receiving the following error.
Error:
CompaniesControllerTest#test_should_get_index:
ActionView::Template::Error: No route matches {:action=>"show", :controller=>"companies", :id=>nil}, missing required keys: [:id]
app/views/layouts/application.html.erb:53:in `_app_views_layouts_application_html_erb__2582383126246718868_70101260952060'
test/controllers/companies_controller_test.rb:16:in `block in <class:CompaniesControllerTest>'
What I've changed in my app is that I've built a sidebar (which I load via application.html.erb so it's loaded on all views (new, show, edit), which lets a user switch between various companies they "own" - which changes a session variable which we use to alter the content of the sidebar.
If we dig into the line that seems to be failing app/views/layouts/application.html.erb:53 this is how it looks:
<div class="list-group-item">
<%= link_to 'Company', company_path(session[:current_company]) unless current_user.companies.empty? %>
</div>
If I remove this link_to line then the tests pass.
My guess is that the show view is trying to load, including the sidebar which doesn't have a session[:current_company] set so the view crashes. However, in Rails 5.2 you cannot set/test session variables as far as I understand, so I'm wondering what the best way for me to set the testing up to make this pass? I do set a value for this session within my application controller a user signs in though:
def after_sign_in_path_for(resource_or_scope)
# Set a default current company scope for a use after signing in
session[:current_company] = current_user.companies.first.id unless current_user.companies.empty?
companies_path
end
Perhaps in the link_to from from within the sidebar I could add a default value to make sure we're always sending in a company, regardless of whether it's the session[:current_company] or not?
Altering the line to skip creating the link if there is no session variable present
<%= link_to 'Company', company_path(session[:current_company]) unless current_user.companies.empty? || !session[:current_company] %>
Seemed to do the trick and make all the tests pass. Would love some feedback on whether this is a good solution or not though! :)

How do I execute a Ruby command when a link_to is pressed?

Basically, what I want to do is run a FactoryGirl.create whenever a link_to is pressed.
Right now, every time I want to generate a new object in my DB, I have to go into Rails Console and type: FactoryGirl.create(:object).
But, ideally...I would love to be able to execute that from the link_to.
Not sure how to do that though.
Thoughts?
I suppose you could treat the creation of an object via FactoryGirl like any other RESTful resource with a dedicated controller and routes:
class MyFactoryGirlController
def create
if FactoryGirl.create(:object)
# Do something
end
end
end
routes.rb
post '/someroute', to: 'myfactorygirl#create', as: :factory_girl
And your link:
link_to "Create an object", factory_girl_path(object: 'SomeObject'), method: :post
Note that this code is meant to illustrate a concept and is incomplete. Copy and pasting will not work.

Ruby on Rails: How to link/route from one view/page to another view/page with a different controller

I have a view template within the following file in my Rails application:
app/views/static_pages/mission.html.erb
I want to link to that page from a view template in a different folder (corresponding to a different page in the app):
app/views/home/home.html.erb
I don't know what to write in my mission method in the StaticPagesController. I'm also a newbie at Rails. I also don't know how to write the route for it and I suspect I may need to write a get 'something' in my routes.rb file.
Can anybody help with this?
What you are asking can be accomplished in this way:
In your routes.rb:
get "/path/to/your/mission/page", to: "static_pages#mission", as: "mission"
Then in your static_pages_controller.rb:
class StaticPagesController < ApplicationController
# You can leave the mission method blank, it will render
# the corresponding static_pages/mission.html.erb by default
def mission
end
end
This should set up the static page, so that when you visit: localhost:3000/path/to/your/mission/page, you should be able to see the mission.html.erb page rendered.
To link to the mission page from any other template, you can simply point a link to it, like so:
<%= link_to "Mission Page", mission_path %>
Or, since it's a static page, you can just hardcode the path into the markup:
Mission Page
Since you're new to Rails (welcome to the world of Rails btw :D), I hope you find these really great resources useful:
Official Rails Guides
Rails For Zombies
Railscasts by Ryan Bates
Hope this was helpful!

How do rails extract an id from an instance variable?

I'm reading "Rails Routing from the Outside In" on RailsGuides.
In Section 1.2, it says
<%= link_to 'Patient Record', patient_path(#patient) %>
will generate the path /patients/17.
What I'd like to know is how rails extract the id from the instance variable.
I've been trying to find the corresponding line of the code on GitHub but can't find.
The ID comes from calling #to_param on the object. Here is a little documentation about it, http://guides.rubyonrails.org/active_support_core_extensions.html#to-param
It calls a to_param method which by default will produce the ID. You can override it to produce nice URLs like this
class Post < ActiveRecord::Base
def to_param
"#{id}-#{title}"
end
end
method responsible is to_param. link to line on
github

Devise with Mongodb won't recognize authenticate_person?

I am having trouble creating an object called person in addition to the user object that's given in the project template from here :https://github.com/RailsApps/rails3-mongoid-devise/tree/master/script
The devise-mongoid combo really doesn't like the person object I created. When I use the following line to try to sign out the person:
<%= link_to 'Logout', destroy_person_session_path, :method =>:delete %>
devise gives me the following error:
Mongoid::Errors::DocumentNotFound in PeopleController#show
Document not found for class Person with id(s) sign_out.
Rails.root: /home/jyj/rubys/rails3-mongoid-devise
So I think it's confusing sign_out with some person's id.
I grepped all instances of user in the project folder and mimicked all of them for the person object. I also created my own log in, sign up pages, instead of using the ones in the view/devise folder directly. But I had initially a lot of trouble signing out the person object. Later I found out that I need to include this javascript tag in my application.html.erb file:
<%#= csrf_meta_tag %>
<%= javascript_include_tag :defaults %>
Notice I had to comment out the other meta tag before in order for the system to recognize the javascript tag, which I don't really understand. Also I had to change a line in the config/intialize/devise.rb file, namely,
# config.sign_out_via = Rails.env.test? ? :get : :delete
config.sign_out_via = :delete
I figured out (perhaps) that the difference here between User and Person was caused by the fact that the test for User was initialized in factory_girl, but not Person. So I made Person looked the same as User in that regard also. But after seeing that didn't work, I just commented out the first line above and simply set the sign_out method to be :delete.
But now my problem became that the system won't recognize the line authenticate_person! in my peoplecontroller.rb file:
class PeopleController < ApplicationController
before_filter :authenticate_person!
def show
#person = Person.find(params[:id])
end
end
Help is greatly appreciated! Any additional code is available upon request. Here is the error message after I put in the javascript tag, deleted the meta tag, and forced the sign_out method to be :delete :
NoMethodError in PeopleController#show
undefined method `authenticate_person!' for
Rails.root: /home/jyj/rubys/rails3-mongoid-devise
While I didn't know what happened with the unrecognized authenticate_person, I did manage to get sign_out to work. The trick is to add the following overriding line in route.rb:
devise_for :person do
get 'sign_out' => 'devise/session#sign_out'
end
So apparently there is no way to make devise recognize a new user category other than user itself! I would still appreciate some help on why that's the case.

Resources