Passing params to rails action mailer - ruby-on-rails

I am using action mailer to email winners, #result array has records of participants who has won including their email.
#result=>[#<Participant id: 47, admin_id: nil, sweepstake_id: 8, participant_name: "gomez", participant_email: "rakesh.k#birdvision.in", participant_number: "12131245421", ip_addr: "127.0.0.1", answer: "nice", reg_time: nil, entry_opt_id: nil, created_at: "2015-09-03 12:15:48", updated_at: "2015-09-07 12:12:53">, #<Participant id: 47, admin_id: nil, sweepstake_id: 8, participant_name: "gomez", participant_email: "rakesh.k#birdvision.in", participant_number: "12131245421", ip_addr: "127.0.0.1", answer: "nice", reg_time: nil, entry_opt_id: nil, created_at: "2015-09-03 12:15:48", updated_at: "2015-09-07 12:12:53">]
But when i pass the result from my controller to the mailer, the result now only has id as string.
Parameters: {"result"=>["47", "47"]}.
How can i pass the array result which has all the participant records?
Code in view page:
<%= link_to "Email Winners",email_winner_sweepstakes_path(:result=>#result) %>
Code in controller:
def email_winner
Rails.logger.info("***********************#{params.inspect}")
ParticipantMailer.winner_confirmation(params[:result]).deliver_now!
end
Code in mailer:
def winner_confirmation(result)
#result = result
#url = 'http://example.com/login'
Rails.logger.info("=================mailer=================")
Rails.logger.info(#result.inspect)
#result.each do |i|
mail(to: i.participant_email, subject: 'Congratulation')
end
end

You will have to find winners by ID, in this line:
<%= link_to "Email Winners", email_winner_sweepstakes_path(result: #result) %>
what you do is formulate the URL and you can't store objects its only string and what it did is it will call .id on #result
to fix that:
in your controller:
def email_winner
#results = Participant.where("id in (?)", params[:result])
ParticipantMailer.winner_confirmation(#results).deliver_now!
end

You cannot pass ruby objects in links, because that triggers a new page load on a different URI, and the ids are provided in that address. You need to only pass ids.
Therefore your ids being passed here, you can fetch the objects with the following:
#result.each do |id|
participant = Participant.find(id)
mail(to: participant.participant_email, subject: 'Congratulation')
end

Related

Why do I receive undefined method after dynamically building array of Objects? Ruby

I'm building a most viewed post feature for a simple blog. Each post has a view count that is increased when the Show action is called for that particular post. Then on the Dashboard , I'm trying to list the top 5 posts. So far my code works and returns an array of posts with the post with the highest number of view count being the first index and the last index in the array being the post with the lowest view count. The only thing is when I try to iterate through the array in the view , the view returns:
ERROR
undefined method `title' for nil:NilClass
WHY??? Does it have to do with the "#" infront of the object?
Heres my code.
Dashboard View
<h3> Post </h3>
<% #top_posts.each do |post| %>
<%= post.title %>
<% end %>
Controller Methods
def get_top
#top_posts = []
counts = []
#posts = Post.all
#posts.each do |post|
counts << post.view_count
end
#posts.each do |post|
if counts.max(5).include?(post.view_count)
counts.max(5).each do |n|
if n == post.view_count
#top_posts[counts.max(5).index(n)] = post
end
end
end
end
end
def dashboard
#posts = Post.all
get_top
end
The Top Podcast Array of objects
[#<Post id: 6, title: "Post 6", desc: "", tags: "", view_count: 8, s_desc: "", c_photo: nil, photos: nil, created_at: "2017-06-14 06:02:25", updated_at: "2017-06-15 01:38:40", featured: nil>, #<Post id: 3, title: "post 3", desc: "", tags: "", view_count: 5, s_desc: "", c_photo: nil, photos: nil, created_at: "2017-06-14 05:35:32", updated_at: "2017-06-14 05:35:53", featured: nil>, #<Post id: 5, title: "Post 5", desc: "", tags: "", view_count: 4, s_desc: "", c_photo: nil, photos: nil, created_at: "2017-06-14 06:02:20", updated_at: "2017-06-15 01:38:31", featured: nil>, nil, #<Post id: 4, title: "Post 4", desc: "", tags: "", view_count: 3, s_desc: "", c_photo: nil, photos: nil, created_at: "2017-06-14 05:49:29", updated_at: "2017-06-15 01:38:50", featured: nil>]
The other answer would probably solve your error, but just want to make an attempt to optimize your code.
That array, loop, etc. is unnecessary, ask your db to do that stuff and get the top posts. Fetching all posts and looping over it multiple times...nay, try the following, hopefully this is what you are looking for..
#top_posts = Post.order('view_count desc').limit(5)
That's it, your view needs no change and will work as expected.
Try:
#top_posts << post
instead of:
#top_posts[counts.max(5).index(n)] = post
You don't need to set the array index.

Undefined method 'permit' for "89718":String

I'm writing a simple Rails api that connects to a legacy SQL Server database. I am testing my REST actions for my contacts controller. When using FactoryGirl to create test objects, I ran into the error message mentioned in the title. My index and show actions work fine, but the create action is throwing this error. The relevant parts of my contacts_controller look like this:
def create
contact = Contact.new(contact_params)
if contact.save
render json: contact, status: 201, location: [:api, contact]
else
render json: { errors: contact.errors }, status: 422
end
end
...
private
def contact_params
params.require(:contact).permit(:name, :address_1, :city, :zip_code_5, :country)
end
And here is the relevant test code:
describe "POST #create" do
context "when is successfully created" do
before(:each) do
#user = FactoryGirl.create :user
#contact = FactoryGirl.create :contact
post :create, { contact: #contact }
end
it "renders the json representation for the contact record just created" do
contact_response = json_response
expect(contact_response[:name]).to eq #contact_attributes[:name]
end
it { should respond_with 201 }
end
end
The model:
class Contact < ActiveRecord::Base
belongs_to :user
validates :name, :address_1, :city, :zip_code_5, :country, :createddate, presence: true
end
The serializer (using the active_model_serializer gem):
class ContactSerializer < ActiveModel::Serializer
belongs_to :user
attributes :id, :name, :address_1, :city, :zip_code_5, :country
end
Things I've tried include:
Changing the 'belongs_to' to 'has_one' in the serializer (no change)
Removing the 'zip_code_5' from the permite...require line (strangely, I still got the error message about this property, perhaps because of the serializer?)
Removing the serializer (no change)
Any thoughts? I'm happy to provide any more necessary information.
EDIT
The value of #contact when it's passed to the create action:
#<Contact id: 89815, user_id: "d67b0d57-8f7f-4854-95b5-f07105741fa8", title: nil, firstname: nil, lastname: nil, name: "Alene Stark", company: nil, address_1: "72885 Bauch Island", address_2: nil, address_3: nil, city: "Joestad", state: nil, zip_code_5: "98117", zip_code_4: nil, country: "MF", status_id: 1, createddate: "2015-10-23 07:00:00", lastmodifieddate: "2012-11-29 08:00:00", errorreasonid: nil, computergenerated: true, sandbox: true, emailsubject: nil, jobtitle: nil, mergevar1: nil, mergevar2: nil, mergevar3: nil, mergevar4: nil, mergevar5: nil, mergevar6: nil, mergevar7: nil, mergevar8: nil, mergevar9: nil, mergevar10: nil, clientid: 1, isshared: true>
The value of params[:contact] at runtime:
{"city"=>"Seattle", "state"=>"WA", "zip_code_5"=>"98117", "country"=>"US"}
I also have my wrap parameters set to :json format, if that's relevant.
I used the console to recreate what my test was doing. I discovered that Contact was being passed as a string, instead of a hash. After a little Googling, I passed the #contact object as #contact.attributes, which passes a hash of the object. This solved the 'permit' problem, thanks for pointing me in the right direction.

Rails: Controller dumps data in view

I have a simple controller with def index having the following code:
#companies = Company.all
respond_to do |format|
format.html
end
But in the view I get these errors appended after all the companies are being displayed:
[#<Company id: 4, title: "Testing #1(1)", created_at: "2013-02-05 19:14:04", updated_at: "2013-02-05 19:14:04">, #<Company id: 7, title: "Testing #1 1", created_at: "2013-02-05 19:34:48", updated_at: "2013-02-05 19:34:48">]
Updated with the view code:
= #companies.each do |company|
%li
.box
.c
%h2
= link_to company.title, company
= #companies.each do |company|
The equals sign in Haml means "print the result of this expression." You're seeing the array of companies on the page because you asked for it.
Use a hyphen instead.
- #companies.each do |company|

Creating an array of values in FactoryGirl, each of which is unique

I have this factory defined:
factory :post, :parent => :post_without_countries, class: Post do |p|
p.country_ids {|country_ids| [country_ids.association(:country), country_ids.association(:country)]}
end
And I'm wanting it to output two unique countries. Instead it just inserts the same country as the association twice:
#<Post id: nil, title: "Atque id dolorum consequatur.", body: "Praesentium saepe ullam magnam. Voluptatum tempora ...", created_at: nil, updated_at: nil, user_id: 1>
[#<Country id: 1, name: "Dominican Republic", isocode: "lyb", created_at: "2012-10-20 13:52:18", updated_at: "2012-10-20 13:52:18">, #<Country id: 1, name: "Dominican Republic", isocode: "lyb", created_at: "2012-10-20 13:52:18", updated_at: "2012-10-20 13:52:18">]
Any ideas?
Better use the build_list or create_list methods:
post.countries = create_list(:country, 2)
Instead of doing:
2.times { post.countries << FactoryGirl.create(:country) }
in RSpec, you can make an after_create hook like this:
after_create do |post|
2.times { post.countries << FactoryGirl.create(:country) }
end
If you need to customize the number of times you want to create a country, you can make a transient attribute:
#in the post factory definition
ignore do
num_countries 0 #default to zero
end
#different after_create
after_create do |post, proxy|
proxy.num_countries.times { post.countries << FactoryGirl.create(:country) }
end
It looks like factory girl might not be iterating properly. The two questions that pop into my mind are.
Are you using FactoryGirl.build when you meant to use FactoryGirl.create?
Have you tried replacing p.country_ids with p.sequence(:country_ids)
I hope that those point you in the right direction. If not, perhaps more information?
OK, I fixed this by taking my creation of the many Countries relationship out the factory and just creating it in RSpec instead:
post = FactoryGirl.build(:post)
2.times { post.countries << FactoryGirl.create(:country) }

Rails - how to instantly get id of inserted row

I use this logic in my app:
controller
#current_user = User.find_or_create_from_oauth(auth_hash)
user.rb
def self.find_or_create_from_oauth(auth_hash)
provider = auth_hash["provider"]
uid = auth_hash["uid"].to_s
case provider
when 'twitter'
if user = self.find_by_twitter_uid(uid)
return user
else
return self.create_user_from_twitter(auth_hash)
end
end
end
def self.create_user_from_twitter(auth_hash)
a = self.create({
:twitter_uid => auth_hash["uid"],
:name => auth_hash["info"]["name"]
})
puts a.inspect
user = User.find_by_twitter_uid(a.twitter_uid)
puts '---'
puts user.inspect
end
Immediately after self.create I would need to run this line:
Assignment.create(:user_id => a.id, :role_id => 2)
The problem is, that the line puts user.inspect return something like this:
#<User id: nil, name: "...name...", twitter_uid: "96580821", provider: "twitter", created_at: nil, updated_at: nil>
Why is in the hash returned id: nil?
Or, is there any other way, how to get the ID of last created record?
If the user has been correctly saved, you can use directly a:
a.assignments.create(:role_id => 2)
Otherwise (check using create! instead of create) there may be a validation error.

Resources