Action Mailer problems (beginner) - ruby-on-rails

If I'm entirely honest, I don't understand action mailers in their entirety and I'm finding it hard to discover a learning resource that isn't using an app which is of a completely different context (e.g teamtreehouses todo app). I would really appreciate a little help.
I have a business directory, I want each listings show page to have a form which when filled in, sends the entered info to the listings attached email.
Here's my code:
Mailers/Enquiry.rb
class Enquiry < ActionMailer::Base
default from: "admin#uk-franchise.co.uk"
def lead(listing, info)
#listing = listing
mail(to: #enquiry.email, subject: 'Email Testing Rails App')
mail(to: #listing.leadrecepient, subject: "test")
end
end
listings controller method
def lead
info = params[:leadname]
notifier = Notifier.lead(#listing, info)
end
Routes I'm stuck on configuring as I don't fully understand them for mailers.
What I have in the show listing view so far
<%= form_for lead_path(#leadname, #listing), method: :put do |lead| %>
<% end %>
Again, if anyone could provide me with a learning resource that would accommodate this scenario or a little help I would really appreciate it!

Here's what you have to do:
Do not use mail method twice in one method
class Enquiry < ActionMailer::Base
default from: "admin#uk-franchise.co.uk"
def lead(listing)
#listing = listing
mail(to: #listing.leadrecepient, subject: "test")
end
end
Send your email from within controller action:
class ListingsController
def lead
##listing = Listing...
Enquiry.lead(#listing).deliver
end
end
routes.rb:
# ...
resources :listings do
member do
put :lead
end
end
# ...
view:
<%= form_for lead_listing_path(#listing), method: :put do |listing| %>
<% end %>

Related

Rails 4 - mailer - how to pass arguments to a mailer method

I'm trying to figure out how to setup a mailer class in my Rails 4 app.
I have made a mailer called admin_notes. I want to use it to send emails to the internal team when certain actions are taken across the site.
In my mailer/admin_note.rb, I have:
class AdminNote < ApplicationMailer
def unknown_organisation(organisation_request, user_full_name, name)
#organisation_request =
#user_full_name =
#organisation_request.name =
# #greeting = "Hi"
mail( to: "test#testerongmail.com",from: "test#testerongmail.com", subject: "A new organisation")
end
end
I have an organisation_requests model. It has:
class OrganisationRequest < ActiveRecord::Base
belongs_to :profile
delegate :user_full_name, to: :profile, prefix: false, allow_nil: true
The organisation request table has an attribute called :name in it.
When a new organisation request is created, I want to send an admin note to the internal team, alerting someone to start a process.
I'm struggling to figure out how I define the three variables in the mailer method.
I plan to add the send email call to the create action in the organisation requests controller.
How can I set these variables?
Form to create an organisation request is:
<%= simple_form_for(#organisation_request) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :organisation_id, collection: #all_organisations << ['other', nil] %>
</div>
<div class="form-inputs">
<%= f.input :name %>
</div>
<div class="form-actions">
<%= f.button :submit, "Create", :class => 'formsubmit' %>
</div>
<% end %>
NEW ATTEMPT:
I have a create action in my organisation controller, I added this service class request for an email:
def create
#organisation_request = OrganisationRequest.new(organisation_request_params)
#organisation_request.profile_id = current_user.profile.id
if #organisation_request.save
NewOrgRequestService.send_unknown_organisation_requested_flag(organisation_request)
return redirect_to(profile_path(current_user.profile),
flash[:alert] => 'Your request is being processed.')
else
# Failure scenario below
#all_organisations = Organisation.select(:title, :id).map { |org| [org.title, org.id] }
render :new
end
end
I then have a services/organisations requests/NewOrgRequestService.rb
class OrganisationRequest < ActiveRecord::Base
class NewOrgRequestService
attr_accessor :organisation_request
def self.send_unknown_organisation_requested_flag(organisation_request)
if #organisation_request.name.present?
AdminNote.unknown_organisation_requested(organisation_request, user_full_name, name).deliver_later
end
end
end
end
The AdminNote mailer has:
class AdminNote < ApplicationMailer
layout 'transactional_mailer'
def unknown_organisation_requested(organisation_request, user_full_name, name)
#organisation_request = #organisation_request
#user_full_name = #organisation_request.user_full_name
#name = organisation_request.name
# #greeting = "Hi"
mail
to: "test#testerongmail.com",from: "test#testerongmail.com", subject: "A new organisation"
end
end
This doesnt work, but I'm wondering if Im on the right track? Im not sure if the create action in the controller needs to have some kind of reference to the services/organisation_requests/ path that gets to the file??
I think I may have made a bigger mess than I started with - but I'm out of ideas for things to try next.
This may help you.
In your mailer method
def unknown_organisation(org,user)
#org = org
#user = user
mail(to: "test#testerongmail.com",from: "test#testerongmail.com", subject: "A new organisation")
end
In your controller method after saving organization_request and this is how you set your variable. You can pass variable you want.
AdminNote.unknown_organization(#organization_request, current_user).deliver_now
In your mailer template access passed value as you do in action view. And this is how you use your variable.
<%= #org.name %>
<%= #org.full_name %>
Hope this helps
If you want to queue message or send later you can use ActiveJob to send mails in the background.
For more, see http://guides.rubyonrails.org/active_job_basics.html
I know I am super late but here I go.
I understand that you are trying to send in some parameters (values) to mailer so that you can use it while sending an email.
To do so you just need to define a mailer method that accepts some parameters. What you have done is right in your AdminNote Mailer unknown_organization method.
Let's get to your NEW ATTEMPT.
Everything you have done there seems about right except you are passing an undefined variable organization_request. You have created an instance variable #organization_request but you are passing something that is not defined. Here
NewOrgRequestService.send_unknown_organisation_requested_flag(organisation_request)
That is your first problem. This can be improved as:
Your Organizations#create
def create
#organisation_request = OrganisationRequest.new(organisation_request_params)
#organisation_request.profile_id = current_user.profile.id
if #organisation_request.save
#organisation_request.send_unknown_organisation_requested_flag
redirect_to(profile_path(current_user.profile),
flash[:alert] => 'Your request is being processed.')
else
# Failure scenario below
#all_organisations = Organisation.select(:title, :id).map { |org| [org.title, org.id] }
render :new
end
end
And your model can be as follows:
class OrganisationRequest < ActiveRecord::Base
def send_unknown_organisation_requested_flag
if self.name.present?
AdminNote.unknown_organisation_requested(self).deliver_later
end
end
end
I don't know why you are defining a class inside your model class.
Your Mailer should look like below:
class AdminNote < ApplicationMailer
layout 'transactional_mailer'
def unknown_organisation_requested(organisation_request)
#organisation_request = organisation_request
#user_full_name = #organisation_request.user_full_name
#name = organisation_request.name
# #greeting = "Hi"
mail
to: "test#testerongmail.com",from: "test#testerongmail.com", subject: "A new organisation"
end
end
There are a lot of typos and method implementation errors here.

Rails Partials - conditionality with locals

I have the following code in a Rails partial being used in some mailers but am not happy with my solution and have the feeling this is far from optimal.
I have an email which
From my mailer:
def the_email_i_am_sending(user, inquiry, params = {})
get_variables(inquiry) #This also provides access to my `#user` object
#contact_name = [params[:guest_last_name].to_s, " ", params[:guest_first_name].to_s].join
I always have #user but on occasion a specific partner will call our API with additional params of [:guest_last_name] and [:guest_first_name] as defined above. This allows me to define #contact_name as a separate instance variable.
When this is .present? i.e. not nil, I want to render #contact_name in a field on the email rather than the #user.login that would pull from our DB.
My mailer view then uses the following code to decide which partial it will render.
<% if #contact_name.present? %>
<%= render 'meet_your_guest_v3', tujia_guest: #contact_name %>
<% else %>
<%= render 'meet_your_guest_v3' %>
<% end %>
My solution is then to utilise this code in the partial being rendered in the mailer. It seems a little verbose but I am unsure about the correct usage of local_assigns.has_key?
<% if local_assigns.has_key?(:partner_guest) %>
<%= partner_guest %> <p>(via our partner</p>
<% else %>
<%= #user.login %>
<% end %>
Is there a better way?
You should definitely follow the advice from #Jon regarding dealing with params in your controller/mailer. Additionally you should just pass #contact_name every time to the underlying partial, regardless if it is present or not, then check only where you want to render it, if it is present. This way you would skip one conditional:
#email_view.html.erb
render 'meet_your_guest_v3', parnter_guest: #contact_name
_contact_name.html.erb
<% partner_guest.present? %>
...
A further step could be using a special decorator object, which would deal with the presentation logick. It would check wether contact_name was provided from outside or from the model and render the desired html tag for the contact_name (or it could just return it as string). See following pseudocode using the draper gem:
class MyController < ApplicationController
def send_mail
#user = User.find(...).decorate(
contact_name: [params[:guest_last_name].to_s, " ", params[:guest_first_name].to_s].join
)
MyMailer.the_email_i_am_sending(#user)
end
end
class MyMailer < ApplicationMailer
def the_email_i_am_sending(user)
#user = user
mail(to: ..., subject: ...)
end
end
class UserDecorator < Draper::Decorator
def contact_name_tag
if (contact_name.present?)
h.content_tag(:div, contact_name)
else
h.content_tag(:div, user_name)
end
end
end
#email_view.html.erb
<%= #user.contact_name_tag %>
However if the presentation logic isn't very complicated, going with a couple conditionals and perhaps extracting them into basic rails helpers is fine and using a presenter may be an overkill

Polymorphic association gone bad?

I am working on a self-learning project for learning Rails that can be found on github here. (The latest commit includes this error)
However I am posting here all codes:
Model: photo_post.rb
class PhotoPost < ActiveRecord::Base
belongs_to :user
has_attached_file :image, styles: {
post: "200x200>"
}
end
Controller: PostsController
class PostsController < ApplicationController
def show
#post = Post.find(params[:id])
end
end
Controller: PhotoPostsController
class PhotoPostsController < ApplicationController
def create
content = build_content
post = current_user.posts.build(content: content)
if post.save
redirect_to root_path
else
flash.alert = "Please enter a title"
redirect_to root_path
end
end
private
def build_content
PhotoPost.new(photo_post_parameters)
end
def photo_post_parameters
params.require(:photo_post).permit(:image)
end
end
_post.html.erb
<%= div_for post do %>
<%= link_to post.user.username, post.user %>
suggested
<%= render post.content %>
<%= link_to time_ago_in_words(post.created_at), post %>
home_controller.rb
class HomeController < ApplicationController
protect_from_forgery
def show
#title_post = TitlePost.new
#photo_post = PhotoPost.new
#posts = current_user.posts
end
end
I created three models. Posts is the main one and TitlePosts and PhotoPosts are models under Posts.
The Title Posts work fine as I can submit a title.
For Photo Posts I used paperclip. However I try to upload an image I get the following error:
'nil' is not an ActiveModel-compatible object that returns a valid partial path.
You can also check the error on imageshack here.(Screenshot with better_errors).
I was going to copy the relevant codes and files but the full project can be found on github at the link I provided. If you need any further info please ask me.
Thank you.
Any help is greatly appreciated.
In just hitting the page current_user isn't defined, so current_user.posts is trying to get posts on a Nil object.
This cleared up the error, though it isn't going to correct your issues:
HomeController ~ line 7
#posts = []
if current_user
#posts = current_user.posts
end
You may also want to add something to your controller to require authentication so that current_user is set:
before_filter :authenticate_user!
OK this seems weird (to me). The error was caused by forgetting to install ImageMagick.
After installing it everything works fine.

Any suggestion for contact form rails 4

I am a newbie in Rails , trying to make a contact form for my app, but I can not catch the parameters that comes from contact form (like name and message) in Emailer class without asscociating a model. Any suggestion on that? Here are the list of classes and controllers.
My Emailer class is :
class Contact < ActionMailer::Base
default from: "from#example.com"
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
# en.contact.send_email.subject
def send_email(contact)
#greeting = "Hi"
mail to: "ostadfree#gmail.com"
end
end
Staticpages controller is :
def email_contact()
Contact.send_email().deliver
redirect_to contact_url
end
Contact.html.erb is include a form and two buttons at the end:
<%= submit_tag "Submit", class: "btn btn-large btn-primary" %>
<%= link_to 'Send Email', email_contact_path %>
and send_email.text.erb is :
Contact#send_email
<%= #greeting %>, find me in app/views/app/views/contact/send_email.text.erb
<%#= "Name :" + #name.to_s %>
Thanks.
Based on your code, you really don't have a grasp on how rails is designed to work. You're probably better off following a tutorial than getting a question like this answered here.
http://seanrucker.com/simple-ruby-on-rails-contact-form-using-activemodel-and-pony/
Try this:
in mailer:
def send_email(name,message)
#greeting = "Hi"
#name = name
#message = message
mail to: "ostadfree#gmail.com"
end
in controller:
def email_contact()
Contact.send_email(params[:name],params[:message]).deliver
redirect_to contact_url
end
where name and message - names of form's fields. If it sent a mails before, that code should work.
Anyway, check it, really: http://guides.rubyonrails.org/action_controller_overview.html#parameters

Trying to link to specfic new comic review page

I'm trying to get a link on an articles show page so that when a user clicks write new review it takes them to the link
/comic_reviews/'the article they want to comment on'/reviews/new
where they will be directed to the new reviews page
how can i accomplish this with
In your routes file you would specify a route like this
match '/comic_reviews/:comic_name/reviews/new' => 'reviews#new', via: :get
Then in your reviews controller you would need something like this
reviews_controller.rb
class ReviewsController < ApplicationController
def new
#comic = Commic.find_by_name(params[:comic_name])
if #comic
#review = #comic.reviews.build
render 'new'
else
#Render some error page since comic was not found
end
end
end
You will then have access to #comic and #review in your reviews/new view so you could build a form that just makes a post to create a review and allows you to store it. This should get you going.
Edit
In your new view you'd need to have a form that looks something like this
<%= form_for #review do |f| %>
<%= f.label :some_attribute %>:
<%= f.text_field :some_attribute %><br />
<%= f.submit %>
<% end %>
This will be expecting you have a route to create a review in your routes file and an action in your ReviewsController.
If you are struggling with such topics I suggest you read over this excellent tutorial
http://ruby.railstutorial.org/ruby-on-rails-tutorial-book
Or just read through the documentation for Rails API which will give you pretty accurate examples.
You can do this via routes
resources :comic_reviews do
resources :reviews
#probably_some_other_route_here
end
And with restful pattern it will be easy to achieve whatever you want
controller
Someclass < Someotherclass
#some your code
def new
#instance_var = Your_model.new
end
def create
#instance_var = Your_model.new(params[:some_name_here])
if #instance_var.save
redirect_to somewhere
else
render 'new'
end
end
end
Also you'll need form, but i dont think that will cause any troubles

Resources