Rails/ActionMailer/Postmark-rails sending same e-mail multiple times - ruby-on-rails

I have a problem. My mailer sends the same e-mail 4 times. I'm pretty sure I only call it once though. What could be the reason?
Running Rails 3.0.7 on Ruby 1.9.2 and Unicorn, if that matters.
Here is the mailer:
class NotificationMailer < ActionMailer::Base
default :from => "herald#artistsnclients.com"
def order_new(user, order)
#user = user
#order = order
mail( :to => "#{user.name} <#{user.email}>", :subject => "You have one new order to review (##{order.id})" )
end
end
What calls the mailer is a callback in the model Notification:
class Notification < ActiveRecord::Base
attr_accessible :read, :user_id, :happening_type, :happening_id, :happening_status
enum_attr :happening_status, %w(new approved rejected cancelled payed completed accepted new_post)
belongs_to :user
belongs_to :happening, :polymorphic => true
after_create :send_email
private
def send_email
# Send e-mail here
if [:new, :approved, :rejected, :cancelled, :payed, :completed, :accepted].include? self.happening_status
right_mailer = NotificationMailer.method("order_#{self.happening_status}".to_sym)
right_mailer.call(self.user, self.happening).deliver
elsif [:new_post].include? self.happening_status
NotificationMailer.note_new(self.user, self.happening).deliver
end
end
end
The Notification object is created from a callback in the Note model:
class Note < ActiveRecord::Base
...
after_create :notify_artist
private
def notify_artist
self.notifications.create :read => false, :happening_status => :new, :user_id => self.artist_id
end
end
Also, here is the part of the log that belongs to the controller from which the Notification model is created:
Started POST "/notes" for 178.8.127.86 at 2011-07-15 18:03:45 +0000
Processing by NotesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8UhgV74SUZibcrowriqQZAketiALnkpHMhu0bkuZ4VQ=", "note"=>{"content"=>"Okaaay, *will do*", "order_id"=>"1"}, "commit"=>"Reply"}
[1m[36mUser Load (0.1ms)[0m [1mSELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1[0m
[1m[35mSQL (0.1ms)[0m BEGIN
[1m[36mSQL (0.5ms)[0m [1mdescribe `notes`[0m
[1m[35mAREL (0.3ms)[0m INSERT INTO `notes` (`user_id`, `order_id`, `content`, `created_at`, `updated_at`) VALUES (1, 1, 'Okaaay, *will do*', '2011-07-15 18:03:45', '2011-07-15 18:03:45')
[1m[36mOrder Load (0.1ms)[0m [1mSELECT `orders`.* FROM `orders` WHERE `orders`.`id` = 1 LIMIT 1[0m
[1m[35mNotification Load (0.5ms)[0m SELECT `notifications`.* FROM `notifications` WHERE (`notifications`.happening_id = 12 AND `notifications`.happening_type = 'Note') LIMIT 1
[1m[36mSQL (0.9ms)[0m [1mdescribe `notifications`[0m
[1m[35mAREL (0.3ms)[0m INSERT INTO `notifications` (`read`, `user_id`, `happening_id`, `happening_type`, `created_at`, `updated_at`, `happening_status`) VALUES (0, 2, 12, 'Note', '2011-07-15 18:03:45', '2011-07-15 18:03:45', 'new_post')
[1m[36mUser Load (0.2ms)[0m [1mSELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1[0m
[1m[35mNote Load (0.3ms)[0m SELECT `notes`.* FROM `notes` WHERE `notes`.`id` = 12 LIMIT 1
Rendered notification_mailer/note_new.html.haml (3.6ms)
Sent mail to [MY E-MAIL] (2362ms)
Date: Fri, 15 Jul 2011 18:03:46 +0000
From: herald#artistsnclients.com
To: Dummy <[MY E-MAIL]>
Message-ID: <4e208102724f_55c11225a4584d7#artistsnclients.mail>
Subject: New message in order #1
Mime-Version: 1.0
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit
<p>Hello Dummy,</p>
<p>There is a new message in your order #1.</p>
<blockquote>
Okaaay, *will do*
</blockquote>
<hr>
<p>
With lots and lots of love,
<br>
Artists&Clients Staff
</p>
[1m[36mSQL (564.1ms)[0m [1mCOMMIT[0m
Redirected to http://dev.artistsnclients.com/orders/1
Completed 302 Found in 3623ms

Please try newer version of the gem named 0.9.8, I think we managed to fix that bug:
https://rubygems.org/gems/postmark
Let me know if it helped.

Related

uninitialized constant Degree(error)

I am getting the error uninitialized constant Degree. I have a column in database with column name type. When i give data to that field and save, the data i gave is getting saved in database but error message is displayed after that and i am not able to reload that page.
Controller code
class ProfileController < ApplicationController
before_action :set_user, only: %i[index update_profile]
def index; end
def update_profile
if #user.update(user_params)
redirect_to profile_index_path, notice: 'Profile was successfully updated.'
else
render :index
end
end
private
def set_user
#user = User.find(current_user.id)
#user.education || #user.build_education
end
def user_params
params.require(:user).permit(:name, education_attributes: %i[id type name issue_institute education_status])
end
end
education.rb
class Education < ApplicationRecord
belongs_to :user
validates_presence_of :user_id
end
user.rb
class User < ApplicationRecord
has_one :education, dependent: :destroy
accepts_nested_attributes_for :education
end
View code
<%= form_for(#user, url: {action: 'update_profile'}, html: {class: 'm-form m-form--fit m-form--label-align-right'}) do |f| %>
<%= f.fields_for :education, #user.education do |e| %>
<%= e.select :type, options_for_select(%w(Degree Certification), params[:type]), prompt: 'Degree/Certification', class: 'form-control m-input' %>
<%= end %>
<%= f.submit 'Save Changes'%>
<%= end %>
Terminal Log when i save that field
Started PATCH "/profile/update_profile" for 127.0.0.1 at 2018-05-30 09:04:37 +0530
Processing by ProfileController#update_profile as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9QiEdSxqwkhHqZHiraiQjJcUvUS+oJknYjYaxWUSQrh+je0ASeYQvs//Z+p+oZkOqyAiwxc3nsxp/iohO9B1BA==", "user"=>{"name"=>"Admin", "email"=>"admin#gmail.com", "address_attributes"=>{"area"=>"5, nehru Street", "city"=>"pune", "state"=>"mumbai", "country"=>"india", "postcode"=>"626781", "id"=>"1"}, "education_attributes"=>{"type"=>"Degree", "name"=>"ffgxh", "issue_institute"=>"", "education_status"=>"", "id"=>"1"}, "fee_attributes"=>{"fee_hour"=>"", "fee_month"=>"", "id"=>"1"}}, "commit"=>"Save Changes"}
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 ORDER BY `users`.`id` ASC LIMIT 1
User Load (0.2ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
Address Load (0.2ms) SELECT `addresses`.* FROM `addresses` WHERE `addresses`.`user_id` = 2 LIMIT 1
Fee Load (0.2ms) SELECT `fees`.* FROM `fees` WHERE `fees`.`user_id` = 2 LIMIT 1
Education Load (0.2ms) SELECT `educations`.* FROM `educations` WHERE `educations`.`user_id` = 2 LIMIT 1
Unpermitted parameter: :email
(0.2ms) BEGIN
SQL (0.4ms) UPDATE `educations` SET `type` = 'Degree', `updated_at` = '2018-05-30 03:34:37' WHERE `educations`.`id` = 1
(5.3ms) COMMIT
Redirected to http://localhost:3000/profile
Completed 302 Found in 19ms (ActiveRecord: 7.1ms)
Started GET "/profile" for 127.0.0.1 at 2018-05-30 09:04:37 +0530
Processing by ProfileController#index as HTML
User Load (0.7ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 ORDER BY `users`.`id` ASC LIMIT 1
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
Address Load (0.4ms) SELECT `addresses`.* FROM `addresses` WHERE `addresses`.`user_id` = 2 LIMIT 1
Fee Load (0.3ms) SELECT `fees`.* FROM `fees` WHERE `fees`.`user_id` = 2 LIMIT 1
Education Load (0.8ms) SELECT `educations`.* FROM `educations` WHERE `educations`.`user_id` = 2 LIMIT 1
Completed 401 Unauthorized in 12ms (ActiveRecord: 2.4ms)
NameError - uninitialized constant Degree:
app/controllers/profile_controller.rb:41:in `set_user'
Data gets saved but i have error page after that. Can someone help me with it? Thanks in advance.
I am posting my comment as an answer so that anyone can reference that in future:
type is a reserved keyword for AR. Check list of reserve active record keywords from here. Change the column name. It will resolve the error.

How to create check boxes, select multiple items and store them -- in rails?

Working on a video-game review website for practice.
When creating a new video-game object, I have to assign platforms to them (xbox, playstation etc.)
my form is below and the Game model has many platforms, while the Platforms model belongs to game
Currently I use collection select. how do i turn this into checkboxes, and be able to select multiple platofrms with the checkboxes and save them?
thanks so much.
server log
Started PATCH "/games/6" for ::1 at 2015-07-08 05:07:59 -0400
Processing by GamesController#update as HTML
Parameters: {"utf8"=>"√", "authenticity_token"=>"n9+Tnko0702pGPDbC3/rzdqGx92yR
ZZymKw3zd+dLwjl+zVqlrEa1yby1/xeXJVeXr+sht8XgXOD0ytCL+dnMw==", "game"=>{"title"=>
"Test", "release_date(1i)"=>"2015", "release_date(2i)"=>"7", "release_date(3i)"=
>"8", "genre_id"=>["1", ""], "platform_id"=>["1", ""]}, "commit"=>"Update Game",
"id"=>"6"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDE
R BY "users"."id" ASC LIMIT 1 [["id", 1]]
Game Load (1.0ms) SELECT "games".* FROM "games" WHERE "games"."id" = ? LIMIT
1 [["id", 6]]
Unpermitted parameters: genre_id, platform_id
(0.0ms) begin transaction
(0.0ms) commit transaction
Redirected to http://localhost:3000/games/6
Completed 302 Found in 10ms (ActiveRecord: 1.0ms)
Started GET "/games/6" for ::1 at 2015-07-08 05:07:59 -0400
Processing by GamesController#show as HTML
Parameters: {"id"=>"6"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDE
R BY "users"."id" ASC LIMIT 1 [["id", 1]]
Game Load (0.0ms) SELECT "games".* FROM "games" WHERE "games"."id" = ? LIMIT
1 [["id", 6]]
(0.0ms) SELECT COUNT("previews"."vote") FROM "previews" WHERE "previews"."ga
me_id" = ? [["game_id", 6]]
CACHE (0.0ms) SELECT COUNT("previews"."vote") FROM "previews" WHERE "previews
"."game_id" = ? [["game_id", 6]]
(0.0ms) SELECT COUNT("reviews"."vote") FROM "reviews" WHERE "reviews"."game_
id" = ? [["game_id", 6]]
CACHE (0.0ms) SELECT COUNT("reviews"."vote") FROM "reviews" WHERE "reviews"."
game_id" = ? [["game_id", 6]]
News Load (1.0ms) SELECT "news".* FROM "news" WHERE "news"."game_id" = ? OR
DER BY "news"."id" DESC LIMIT 5 [["game_id", 6]]
Rendered games/_review.html.erb (2.0ms)
Review Load (1.0ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."game_i
d" = ? [["game_id", 6]]
(0.0ms) SELECT COUNT(*) FROM "reviews" WHERE "reviews"."game_id" = ? [["gam
e_id", 6]]
Review Load (0.0ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."game_
id" = ? ORDER BY "reviews"."id" DESC LIMIT 5 [["game_id", 6]]
Rendered games/show.html.erb within layouts/application (16.0ms)
Completed 200 OK in 162ms (Views: 157.1ms | ActiveRecord: 2.0ms)
server log 2 when using Emu's suggestion <-- still not saving, but unpermitted parameters error is gone.
Started PATCH "/games/6" for ::1 at 2015-07-08 05:56:55 -0400
Processing by GamesController#update as HTML
Parameters: {"utf8"=>"√", "authenticity_token"=>"lzku1Wa89d6a2i2yArfyiyQwfhLcW
iigah0Pv6XpUAjtHYghujkARBUwCpVXlIwYoAkVSbEIP6FxYhMwVZMYMw==", "game"=>{"title"=>
"Test", "release_date(1i)"=>"2015", "release_date(2i)"=>"7", "release_date(3i)"=
>"8"}, "platform_ids"=>["4", "5"], "commit"=>"Update Game", "id"=>"6"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDE
R BY "users"."id" ASC LIMIT 1 [["id", 1]]
Game Load (0.0ms) SELECT "games".* FROM "games" WHERE "games"."id" = ? LIMIT
1 [["id", 6]]
(0.0ms) begin transaction
(0.0ms) commit transaction
(0.0ms) begin transaction
(0.0ms) commit transaction
Redirected to http://localhost:3000/games/6
Completed 302 Found in 9ms (ActiveRecord: 0.0ms)
Started GET "/games/6" for ::1 at 2015-07-08 05:56:55 -0400
Processing by GamesController#show as HTML
Parameters: {"id"=>"6"}
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDE
R BY "users"."id" ASC LIMIT 1 [["id", 1]]
Game Load (0.0ms) SELECT "games".* FROM "games" WHERE "games"."id" = ? LIMIT
1 [["id", 6]]
(0.0ms) SELECT COUNT("previews"."vote") FROM "previews" WHERE "previews"."ga
me_id" = ? [["game_id", 6]]
CACHE (0.0ms) SELECT COUNT("previews"."vote") FROM "previews" WHERE "previews
"."game_id" = ? [["game_id", 6]]
(0.0ms) SELECT COUNT("reviews"."vote") FROM "reviews" WHERE "reviews"."game_
id" = ? [["game_id", 6]]
CACHE (0.0ms) SELECT COUNT("reviews"."vote") FROM "reviews" WHERE "reviews"."
game_id" = ? [["game_id", 6]]
News Load (0.0ms) SELECT "news".* FROM "news" WHERE "news"."game_id" = ? OR
DER BY "news"."id" DESC LIMIT 5 [["game_id", 6]]
Rendered games/_review.html.erb (7.0ms)
Review Load (0.0ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."game_i
d" = ? [["game_id", 6]]
(0.0ms) SELECT COUNT(*) FROM "reviews" WHERE "reviews"."game_id" = ? [["gam
e_id", 6]]
Review Load (1.0ms) SELECT "reviews".* FROM "reviews" WHERE "reviews"."game_
id" = ? ORDER BY "reviews"."id" DESC LIMIT 5 [["game_id", 6]]
Rendered games/show.html.erb within layouts/application (26.0ms)
Completed 200 OK in 197ms (Views: 177.1ms | ActiveRecord: 3.0ms)
games table
create_table "games", force: :cascade do |t|
t.string "title"
t.string "image"
t.date "release_date"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "platform_id"
t.integer "genre_id"
t.integer "review_id"
t.integer "steelbook_id"
end
_game.html.erb <-- if I change the check boxes to use "genre_ids" and "platform_ids" i get a no method error at games#edit controller
<%= form_for #game do |g| %>
<p><%= g.label :title %></p>
<p><%= g.text_field :title %></p>
<p><%= g.label :release_date %></p>
<p><%= g.date_select :release_date %></p>
<p><%= g.label :genre_id %></p>
<p><%= g.collection_check_boxes :genre_id, #genres, :id, :category %></p>
<p><%= g.label "Platform(s)" %></p>
<p><%= g.collection_check_boxes :platform_id, #platforms, :id, :system %></p>
<p><%= g.label :image %></p>
<p><%= g.file_field :image %></p>
<hr>
<p><%= g.submit %></p>
<% end %>
game controller
class GamesController < ApplicationController
before_action :authenticate_user!
before_action :set_game, only: [:show, :edit, :update, :destroy]
def index
#games = Game.all
end
def show
#reviews = Review.where(game_id: #game.id)
#previews = Preview.where(game_id: #game.id)
#news = News.where(game_id: #game.id)
end
def create
#game = Game.new(game_params)
#game.save
redirect_to #game
end
def new
#game = Game.new
set_platforms
set_genres
end
def edit
set_platforms
set_genres
end
def update
#game.update(game_params)
redirect_to #game
end
def destroy
#game.destroy
redirect_to root_path
end
private
def game_params
params.require(:game).permit(:title, :image, :release_date, :genre_ids => [], :platform_ids => [])
end
def set_game
#game = Game.find(params[:id])
end
def set_platforms
#platforms = Platform.order(:system)
end
def set_genres
#genres = Genre.order(:category)
end
end
routes
Rails.application.routes.draw do
devise_for :users
root "games#index"
resources :games do
resources :news
resources :reviews, except: [:show]
resources :previews, except: [:show]
end
resources :platforms
resources :genres
end
platforms model
class Platform < ActiveRecord::Base
belongs_to :game
end
game model
class Game < ActiveRecord::Base
has_many :platforms
has_many :preview, through: :users
has_many :reviews, through: :users
has_many :news
has_one :genre
end
You can use collection_check_boxes.
<p><%= g.collection_check_boxes :platform_ids, #platforms, :id, :system %></p>
And change game_params to the following.
def game_params
params.require(:game).permit(:title, :image, :release_date, :genre_id, :platform_ids => [])
end
Didn't tested it. I guess you require a little tweak in the code.
For each platform create a new checkbox using the loop below:
<% #platforms.each do |platform| %>
<%= check_box_tag "platform_ids[]", platform.id %>
<%= platform.name %> // I assume that your platform has a name which can be used as a label
<% end %>
In the controller you can access the values of the checkboxes using params[:platform_ids]
Just change the game_params method in the controller with the following code:
def game_params
params.require(:game).permit(:title, :image, :release_date, :genre_id, :platform_ids => [])
end
or
you can see a railscasts video.

Rails 4 CRUD Update Successful but not saved to Database

I am experiencing a really weird issue in my rails 4 app. I've created a CRUD operation called FOO. All sections work as one would expect it to, except for the Update operation.
The FOO model has 4 Attributes:
title
body
author
status
When I load the Update form, the model is loaded into the form as it should be. The update action returns a "SUCCESS" status if a valid form is submitted, but here is the issue: Only the "Title" attribute is ever updated. All the other attributes remain unchanged. If I Update them one-by-one, they also do not change.
Here is my FooController code:
def update
if #foo.validate( params[ :foo ] )
#foo.save
respond_with( #foo, location: root_path )
else
render :edit
end
end
I am using the Reform GEM instead of Strong Params:
class FooForm < ApplicationForm
property :title
property :body
property :author
property :status
end
And I'm loading the #foo instance in my controller like this:
before_action :load_form_instance, only: [ :edit, :update ]
def load_form_instance
#foo = FooForm.new( Foo.find( params[ :id ]) )
end
I have tested overwriting these values from my Rails console and that seems to work just fine.
Does anybody have any idea where things might be going wrong?
UPDATE
Here is my development LOG as per a request below:
Started PATCH "/foo/1" for 127.0.0.1 at 2015-06-04 20:19:10 +0200
[1m[36mUser Load (1.0ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1[0m [["id", 1]]
Processing by FooController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"yB+BwFSKt62uSQZtY6auHZ4+DbxVdcZZE2VIWzgRAhVX3Hqn7xmdKewcJ39LnSQm0hfkK+7HazGdypyI7noobA==", "foo"=>{"title"=>"This is a test", "body"=>"This is Body 2", "author"=>"Test1", "status"=>"Active"}, "commit"=>"Update Foo", "id"=>"1"}
[1m[35mFoo Load (0.7ms)[0m SELECT "foo".* FROM "foo" WHERE "foo"."id" = $1 LIMIT 1 [["id", 1]]
[1m[36m (0.3ms)[0m [1mSELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'super_admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))[0m [["user_id", 1]]
[1m[35m (0.2ms)[0m BEGIN
[1m[36m (0.2ms)[0m [1mCOMMIT[0m
Redirected to http://localhost:3000/foo
Completed 302 Found in 32ms (ActiveRecord: 1.4ms)

Actionmailer not sending email even though no error

I have a couple of different mailers setup on my system. One is working fine and the other gives no errors but doesn't send out an email.
The mailer that works looks like this:
class UserMailer < ActionMailer::Base
default from: "info#footballpoolmania.com"
# Subject can be set in your I18n file at config/locales/en.yml
# with the following lookup:
#
# en.user_mailer.password_reset.subject
#
def password_reset(user)
#user = user
mail to: user.email, subject: "Password Reset"
end
def confirm_registration(user)
#user = user
mail to: user.email, subject: "Confirm Registration"
end
end
and when sending a password_reset email I get the following in the log:
Started POST "/password_resets" for 127.0.0.1 at 2013-12-06 17:24:32 -0600
Processing by PasswordResetsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"jwGUtsyNRbCfBRFJm3uqcVZA4luHc05Gf0OBm4jyFpI=", "email"=>"robertr2112#yahoo.com", "commit"=>"Reset Password"}
[1m[35mUser Load (0.8ms)[0m SELECT "users".* FROM "users" WHERE "users"."email" = 'robertr2112#yahoo.com' LIMIT 1
[1m[36m (0.2ms)[0m [1mBEGIN[0m
[1m[35mSQL (2.7ms)[0m UPDATE "users" SET "password_reset_token" = $1, "updated_at" = $2 WHERE "users"."id" = 2 [["password_reset_token", "c851e80faeb3612c654c512857cfb29afc6a4665"], ["updated_at", Fri, 06 Dec 2013 23:24:32 UTC +00:00]]
[1m[36m (5.8ms)[0m [1mCOMMIT[0m
[1m[35m (1.2ms)[0m BEGIN
[1m[36mSQL (1.5ms)[0m [1mUPDATE "users" SET "password_reset_sent_at" = $1, "updated_at" = $2 WHERE "users"."id" = 2[0m [["password_reset_sent_at", Fri, 06 Dec 2013 23:24:32 UTC +00:00], ["updated_at", Fri, 06 Dec 2013 23:24:32 UTC +00:00]]
[1m[35m (1.6ms)[0m COMMIT
Rendered user_mailer/password_reset.text.erb (2.3ms)
Sent mail to robertr2112#yahoo.com (316.8ms)
Date: Fri, 06 Dec 2013 17:24:32 -0600
From: info#footballpoolmania.com
To: robertr2112#yahoo.com
Message-ID: <52a25cb0c52be_c94585623640840#debian.mail>
Subject: Password Reset
Mime-Version: 1.0
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bit
To reset your password, click the URL below.
http://localhost:3000/password_resets/c851e80faeb3612c654c512857cfb29afc6a4665/edit
If you did not request your password to be reset, just ignore this email and
your password will continue to stay the same.
Redirected to http://localhost:3000/
Completed 302 Found in 380ms (ActiveRecord: 13.7ms)
Also, the view for the message is defined as password_reset.text.erb and is located in app/views/user_mailer and looks like this:
To reset your password, click the URL below.
<%= edit_password_reset_url(#user.password_reset_token) %>
If you did not request your password to be reset, just ignore this email and
your password will continue to stay the same.
The mailer that doesn't work looks like this:
class PoolMailer < ActionMailer::Base
default from: "info#footballpoolmania.com"
def send_pool_message(pool, subject, msg, allMembers)
#pool = pool
#msg = msg
email_list = Array.new
#pool.users.each do |user|
if allMembers
entries = Entry.where(user_id: user.id)
else
entries = Entry.where(pool_id: pool.id, user_id: user.id, survivorStatusIn:true)
end
if entries.any?
email_list << "#{user.name} <#{user.email}>"
end
end
subject_text = pool.name + ": " + subject
if mail to: email_list, subject: subject_text
puts "Successfully sent email"
return false
else
puts "Couldn't send email"
return true
end
end
end
And the log looks like the following:
Started POST "/pools/2/pool_messages" for 127.0.0.1 at 2013-12-06 17:50:54 -0600
Processing by PoolMessagesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"jwGUtsyNRbCfBRFJm3uqcVZA4luHc05Gf0OBm4jyFpI=", "subject"=>"This is a test", "msg"=>"A test of the group pool message.", "allMembers"=>"false", "commit"=>"Send email", "pool_id"=>"2"}
[1m[36mPool Load (8.9ms)[0m [1mSELECT "pools".* FROM "pools" WHERE "pools"."id" = $1 LIMIT 1[0m [["id", "2"]]
[1m[35mUser Load (0.7ms)[0m SELECT "users".* FROM "users" INNER JOIN "pool_memberships" ON "users"."id" = "pool_memberships"."user_id" WHERE "pool_memberships"."pool_id" = $1 [["pool_id", 2]]
[1m[36m (0.4ms)[0m [1mSELECT COUNT(*) FROM "entries" WHERE "entries"."user_id" = 2[0m
[1m[35m (0.3ms)[0m SELECT COUNT(*) FROM "entries" WHERE "entries"."user_id" = 3
[1m[36m (0.3ms)[0m [1mSELECT COUNT(*) FROM "entries" WHERE "entries"."user_id" = 4[0m
[1m[35m (0.4ms)[0m SELECT COUNT(*) FROM "entries" WHERE "entries"."user_id" = 5
Rendered pool_mailer/send_pool_message.text.erb (0.7ms)
Redirected to http://localhost:3000/pools/2
Completed 302 Found in 1527ms (ActiveRecord: 11.0ms)
And the view for this email is called send_pool_message.text.erb and is located in app/views/pool_mailer and looks like this:
<%= #msg %>
This is an automated email sent by the pool administer. Do not reply to this
email.
The first mailer sends out the email correctly and logs it as well. The second mailer neither sends an email or logs the email. I'm not sure where to look to correct the problem because I get absolutely zero error messages on any of this.
Any help pointing me in the right direction to fix this would be greatly appreciated.
You need to call .deliver to your mailer function
PoolMailer.send_pool_message(...).deliver
Otherwiser it just generates the email without delivering it

Rails nested attributes not being updated

I'm building my first Rails app and one of the important features in it is having users who speak and/or want to learn languages. In the user edit profile page, I allow him/her to choose what languages he/she speaks and/or wants to learn from a list (I'm using ryanb's nested_form gem):
There are 3 models involved in this: User, Speaks, Language
The languages table is just a table with languages of the world, it doesn't change. It consists basically of ISO codes for languages and their names. I populate it by running a script that reads from the official file I downloaded. Still I was simply using Rails defaults, so the table had an id column, and it was all working fine.
Then I decided to make a change and remove the id column, because it didn't make any sense anyway. I want my app to be up to date with the ISO list. I want the ISO code to identify the languages, not a meaningless id. I want to use
user.speaks.create!(language_id: "pt", level: 6)
instead of
user.speaks.create!(language_id: 129, level: 6)
I know it's unlikely that the ISO list will change but, if it does, I want to simply run my script again with the new file and not worry if the id column will still match the same ISO code as before. So I made the change. Now I can use user.speaks.create the way I want and the association works perfectly in the console. The problem is my form simply isn't working anymore. The data is sent but I don't understand the logs. They show a bunch of SELECTS but no INSERTS or UPDATES, I don't get why. Does anybody have any idea?
Here are my models:
class User < ActiveRecord::Base
attr_accessible ..., :speaks, :speaks_attributes, :wants_to_learn_attributes
has_many :speaks, :class_name => "Speaks", :dependent => :destroy
has_many :speaks_languages, :through => :speaks, :source => :language #, :primary_key => "iso_639_1_code"
has_many :wants_to_learn, :class_name => "WantsToLearn", :dependent => :destroy
has_many :wants_to_learn_languages, :through => :wants_to_learn, :source => :language #, :primary_key => "iso_639_1_code"
...
accepts_nested_attributes_for :speaks #, :reject_if => :speaks_duplicate, :allow_destroy => true
accepts_nested_attributes_for :wants_to_learn #, :reject_if => :wants_to_learn_duplicate, :allow_destroy => true
# EDIT 1: I remembered these pieces of code silenced errors, so I commented them out
...
end
class Speaks < ActiveRecord::Base
self.table_name = "speak"
attr_accessible :language, :language_id, :level
belongs_to :user
belongs_to :language
validates :user, :language, :level, presence: true
...
end
#EDIT 4:
class WantsToLearn < ActiveRecord::Base
self.table_name = "want_to_learn"
attr_accessible :language, :language_id
belongs_to :user
belongs_to :language
validates :user, :language, presence: true
...
end
class Language < ActiveRecord::Base
attr_accessible :iso_639_1_code, :name_en, :name_fr, :name_pt
has_many :speak, :class_name => "Speaks"
has_many :users_who_speak, :through => :speak, :source => :user
has_many :want_to_learn, :class_name => "WantsToLearn"
has_many :users_who_want_to_learn, :through => :want_to_learn, :source => :user
end
Controller:
def update
logger.debug params
if #user.update_attributes(params[:user])
#user.save
flash[:success] = "Profile updated"
sign_in #user
redirect_to :action => :edit
else
render :action => :edit
end
end
View:
<%= nested_form_for(#user, :html => { :class => "edit-profile-form"} ) do |f| %>
<%= render 'shared/error_messages' %>
<table border="0">
<tr><td colspan="2"><h2 id="languages" class="bblabla">Languages</h2></td></tr>
<tr>
<td><span>Languages you speak</span></td>
<td class="languages-cell">
<div id="speaks">
<%= f.fields_for :speaks, :wrapper => false do |speaks| %>
<div class="fields">
<%= speaks.select(:language_id,
Language.all.collect {|lang| [lang.name_en, lang.id]},
{ :selected => speaks.object.language_id, :include_blank => false },
:class => 'language') %>
<%= speaks.label :level, "Level: " %>
<%= speaks.select(:level, Speaks.level_options, { :selected => speaks.object.level }, :class => 'level') %>
<%= speaks.link_to_remove raw("<i class='icon-remove icon-2x'></i>"), :class => "remove-language" %>
</div>
<% end %>
</div>
<p class="add-language"><%= f.link_to_add "Add language", :speaks, :data => { :target => "#speaks" } %></p>
</td>
</tr>
...
Log:
Started PUT "/users/1" for 127.0.0.1 at 2013-07-19 08:41:16 -0300
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ZmaU9...", "user"=>{"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374234067848"=>{"language_id"=>"en", "level"=>"5", "_destroy"=>"false"}}, "wants_to_learn_attributes"=>{"0"=>{"language_id"=>"ro", "_destroy"=>"false", "id"=>"1"}}, "home_location_attributes"=>{"google_id"=>"7789d9...", "latitude"=>"-22.9035393", "longitude"=>"-43.20958689999998", "city"=>"Rio de Janeiro", "neighborhood"=>"", "administrative_area_level_1"=>"Rio de Janeiro", "administrative_area_level_2"=>"", "country_id"=>"BR", "id"=>"1"}, "gender"=>"2", "relationship_status"=>"2", "about_me"=>""}, "commit"=>"Save changes", "id"=>"1"}
[1m[35mUser Load (0.3ms)[0m SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'bjdvI...' LIMIT 1
[1m[36mUser Load (0.2ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1[0m [["id", "1"]]
{"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"ZmaU9W...", "user"=>{"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374234067848"=>{"language_id"=>"en", "level"=>"5", "_destroy"=>"false"}}, "wants_to_learn_attributes"=>{"0"=>{"language_id"=>"ro", "_destroy"=>"false", "id"=>"1"}}, "home_location_attributes"=>{"google_id"=>"7789d9...", "latitude"=>"-22.9035393", "longitude"=>"-43.20958689999998", "city"=>"Rio de Janeiro", "neighborhood"=>"", "administrative_area_level_1"=>"Rio de Janeiro", "administrative_area_level_2"=>"", "country_id"=>"BR", "id"=>"1"}, "gender"=>"2", "relationship_status"=>"2", "about_me"=>""}, "commit"=>"Save changes", "action"=>"update", "controller"=>"users", "id"=>"1"}
[1m[35m (0.1ms)[0m BEGIN
[1m[36mWantsToLearn Load (0.2ms)[0m [1mSELECT "want_to_learn".* FROM "want_to_learn" WHERE "want_to_learn"."user_id" = 1 AND "want_to_learn"."id" IN (1)[0m
[1m[35mLocation Load (0.3ms)[0m SELECT "locations".* FROM "locations" WHERE "locations"."google_id" = '7789d...' AND "locations"."latitude" = '-22.9035393' AND "locations"."longitude" = '-43.20958689999998' AND "locations"."city" = 'Rio de Janeiro' AND "locations"."neighborhood" = '' AND "locations"."administrative_area_level_1" = 'Rio de Janeiro' AND "locations"."administrative_area_level_2" = '' AND "locations"."country_id" = 'BR' LIMIT 1
[1m[36mUser Exists (40.0ms)[0m [1mSELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('ariel#pontes.com') AND "users"."id" != 1) LIMIT 1[0m
[1m[35m (96.7ms)[0m UPDATE "users" SET "remember_token" = 'd0pb...', "updated_at" = '2013-07-19 11:41:16.808422' WHERE "users"."id" = 1
[1m[36m (28.7ms)[0m [1mCOMMIT[0m
[1m[35m (0.1ms)[0m BEGIN
[1m[36mUser Exists (0.3ms)[0m [1mSELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('ariel#pontes.com') AND "users"."id" != 1) LIMIT 1[0m
[1m[35m (0.3ms)[0m UPDATE "users" SET "remember_token" = 'gKlW...', "updated_at" = '2013-07-19 11:41:17.072654' WHERE "users"."id" = 1
[1m[36m (0.4ms)[0m [1mCOMMIT[0m
Rendered shared/_error_messages.html.erb (0.0ms)
[1m[35mSpeaks Load (0.3ms)[0m SELECT "speak".* FROM "speak" WHERE "speak"."user_id" = 1
[1m[36mWantsToLearn Load (0.2ms)[0m [1mSELECT "want_to_learn".* FROM "want_to_learn" WHERE "want_to_learn"."user_id" = 1[0m
[1m[35mLanguage Load (0.3ms)[0m SELECT "languages".* FROM "languages"
[1m[36mCountry Load (0.3ms)[0m [1mSELECT "countries".* FROM "countries" WHERE "countries"."iso_3166_code" = 'BR' LIMIT 1[0m
[1m[35mCACHE (0.0ms)[0m SELECT "languages".* FROM "languages"
[1m[36mCACHE (0.0ms)[0m [1mSELECT "languages".* FROM "languages" [0m
Rendered users/edit.html.erb within layouts/application (39.8ms)
Rendered layouts/_shim.html.erb (0.0ms)
Rendered layouts/_header.html.erb (1.1ms)
Rendered layouts/_footer.html.erb (0.2ms)
Completed 200 OK in 576ms (Views: 160.7ms | ActiveRecord: 168.7ms)
Hope someone has an insight cause I've been looking all over the internet for the past 2 days with no luck. Thanks in advance!
EDIT 1
I placed the accepts_nested_attributes_for lines after the associations were made, as suggested by ovatsug25, but it didn't seem to make any change. I remembered, however, that there were some options in the User model that silenced errors, which of course hinders the debugging, so I commented these options out. Now I have the following error:
PG::Error: ERROR: operator does not exist: character varying = integer
LINE 1: ...M "languages" WHERE "languages"."iso_639_1_code" = 0 LIMIT ...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT "languages".* FROM "languages" WHERE "languages"."iso_639_1_code" = 0 LIMIT 1
I have NO IDEA why Rails is trying to select a language with pk = 0. Even if the pk WAS an integer this wouldn't make sense (would it???) since the default id starts from 1. And even if it started from zero, why would it be trying to select it anyway? Where is this zero comming from?? And I can't "add explicit type casts". The pk is a string and will never be 0 or '0' for that matter. This query doesn't make sense and simply isn't supposed to happen!
EDIT 2
I tried to update the attributes in the console and got the following:
irb(main):006:0> ariel = User.find(1)
User Load (101.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 1]]
=> #<User id: 1, first_name: "Ariel", last_name: "Pontes", ...>
irb(main):007:0> params = {"user"=>{"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374444891951"=>{"language_id"=>"en", "l
evel"=>"5", "_destroy"=>"false"}}, "wants_to_learn_attributes"=>{"0"=>{"language_id"=>"ro", "_destroy"=>"false"}}, "home_location_attributes"=>{"google_id"=>"778...c5a", "latitude"=>"-22.9035393", "longitude"=>"-43.20958689999998", "city"=>"Rio de Janeiro", "neighborhood"=>"", "administrative
_area_level_1"=>"Rio de Janeiro", "administrative_area_level_2"=>"", "country_id"=>"BR", "id"=>"1"}, "gender"=>"2", "relationship_status"=>"2", "about_me"=>""}}
=> {"user"=>{"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374444891951"=>{"language_id"=>"en", "level"=>"5", "_destroy"=
>"false"}}, "wants_to_learn_attributes"=>{"0"=>{"language_id"=>"ro", "_destroy"=>"false"}}, "home_location_attributes"=>{"google_id"=>"778...c5a", "latitude"=>"-22.9035393", "longitude"=>"-43.20958689999998", "city"=>"Rio de Janeiro", "neighborhood"=>"", "administrative_area_level_1"=>"Rio de
Janeiro", "administrative_area_level_2"=>"", "country_id"=>"BR", "id"=>"1"}, "gender"=>"2", "relationship_status"=>"2", "about_me"=>""}}
irb(main):008:0> ariel.update_attributes(params[:user])
(0.1ms) BEGIN
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('ariel#pontes.com') AND "users"."id" != 1) LIMIT 1
(24.9ms) UPDATE "users" SET "remember_token" = '0tv...Cw', "updated_at" = '2013-07-22 15:45:30.705217' WHERE "users"."id" = 1
(54.3ms) COMMIT
=> true
irb(main):009:0>
Basically, it only updates the remember_token and updated_at for some reason.
EDIT 3
I tried to update only the spoken languages and it worked:
irb(main):012:0> ariel.update_attributes({"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374444891951"=>{"language_id"=>"e
n", "level"=>"5", "_destroy"=>"false"}}})
(0.2ms) BEGIN
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Language Load (0.8ms) SELECT "languages".* FROM "languages" WHERE "languages"."iso_639_1_code" = 'pt' LIMIT 1
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Language Load (0.2ms) SELECT "languages".* FROM "languages" WHERE "languages"."iso_639_1_code" = 'en' LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('ariel#pontes.com') AND "users"."id" != 1) LIMIT 1
(0.2ms) UPDATE "users" SET "remember_token" = 'MYh5X1XoF6OsVIo3rhDNzQ', "updated_at" = '2013-07-22 22:05:08.198025' WHERE "users"."id" = 1
SQL (42.9ms) INSERT INTO "speak" ("created_at", "language_id", "level", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Mo
n, 22 Jul 2013 22:05:08 UTC +00:00], ["language_id", "pt"], ["level", 6], ["updated_at", Mon, 22 Jul 2013 22:05:08 UTC +00:00], ["user_id", 1]]
SQL (0.4ms) INSERT INTO "speak" ("created_at", "language_id", "level", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Mon
, 22 Jul 2013 22:05:08 UTC +00:00], ["language_id", "en"], ["level", 5], ["updated_at", Mon, 22 Jul 2013 22:05:08 UTC +00:00], ["user_id", 1]]
(14.7ms) COMMIT
=> true
I'm starting to fear it may be a case of witchcraft.
PS: Does anybody know why it loads the User 3 times? Seems rather pointless and wasteful.
The biggest clue is this error that caught your eye:
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT "languages".* FROM "languages" WHERE "languages"."iso_639_1_code" = 0 LIMIT 1
If you're providing a string value for a model attribute, but the underlying database column is a numeric column, Rails will try to convert the string value to the appropriate numeric type. So, if the underlying column is of type integer, the string input will be interpreted as an integer, using String#to_i. If the string doesn't start with a number, it will be converted to 0.
The Rails console (rails c) can be a useful tool for debugging issues like this. In this case, on the console, you can run WantsToLearn.columns_hash['language_id'].type to see what type Rails thinks it should be using for that attribute. Of course, you can also just as easily check the migrations.
I used to have a problem like this and solved it by segreating the accepts_attributes_for calls to the very bottom after all associations and accessible attributes have been declared. (I also merged attr_accesible into one call. I think ryanb says something in this video about the order of the calls. http://railscasts.com/episodes/196-nested-model-form-revised?view=asciicast.
Makes sense? No. But it worked for me.

Resources