I'm trying to create an email which is sent when admin click to active account for user
user has_one :account and account belongs_to :user
in user.rb
devise :database_authenticatable, :registerable, :Trackable, :rememberable, :recoverable
attr_accessible :account, :email, :password, :password_confirmation, :account_attributes, :approved
has_one :account
end
in account.rb
class Account < ActiveRecord::Base
attr_accessible :address, :approved, :name
belongs_to :user
end
in accounts_controller.rb
def activate
#accounts = Account.find(params[:id])
#users = User.where(:id => #accounts.id)
if (#accounts.update_attributes(approved: true)) && (#users.update_all(approved: true))
AccountMailer.activate_account(#users).deliver
redirect_to accounts_path
else
redirect_to accounts_path
end
end
in account_mailer.rb
class AccountMailer < ActionMailer::Base
default :from => "kapanjadi#gmail.com"
def activate_account(user)
#users = user
#account = account.find_by_user_id(user)
mail(:to => user.email, :subject => "Activation Account", :from => "kapanjadi#gmail.com")
end
end
in account_mailer/activate_account.text.erb
congratulation, your account is active now
setup_mailer.rb
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "localhost:3000",
:user_name => "kapanjadi#gmail.com",
:password => "password",
:authentication => "plain",
:enable_starttls_auto => true
}
but an email not send to email user, and no error..
these did not happened to any other action.
Any suggestions as to what I am doing wrong?
UPDATE 1
in accounts_controller.rb
def activate
#account = Account.find(params[:id])
#user = User.where(:id => #account.id)
if (#account.update_attributes(approved: true)) && (#user.update_all(approved: true))
AccountMailer.activate_account(#user,#account).deliver
redirect_to accounts_path
else
redirect_to accounts_path
end
end
in account_mailer.rb
class AccountMailer < ActionMailer::Base
default :from => "fauzieuy#gmail.com"
def activate_account(user,account)
#account = account
#accounts = Account.find_by_user_id(user)
mail(:to => user.email, :subject => "Activation", :from => "kapanjadi#gmail.com")
end
end
error
undefined method `email' for #<ActiveRecord::Relation:0x3e7c720>
in accounts_controller.rb
def activate
#account = Account.find(params[:id])
#user = User.where(:id => #account.id)
if (#account.update_attributes(approved: true)) && (#user.update_all(approved: true))
user_account = account.find_by_user_id(#user)
AccountMailer.activate_account(#user,user_account,#account.user.mail).deliver
redirect_to accounts_path
else
redirect_to accounts_path
end
end
in account_mailer.rb
class AccountMailer < ActionMailer::Base
default :from => "kapanjadi#gmail.com"
def activate_account(user,account,to)
#users = user
#account = account
mail(:to => to, :subject => "Activation Account", :from=>"kapanjadi#gmail.com")
end
end
The above will work for sure.
Why is everything plural (#accounts and #users)?
def activate
#account = Account.find(params[:id])
redirect_to accounts_path and return if #account.nil? # handles bad `params[:id]`
if #account.update_attributes(approved: true) && #account.user.update_attributes(approved: true)
AccountMailer.activate_account(#account.user).deliver
redirect_to accounts_path and return
end
redirect_to accounts_path
end
Related
I am trying to configure Google OAuth and I am facing a very silly mistake I can't solve :
When I click on the Sign in button on the home page:
<% if user_signed_in? %>
Signed in as <%= current_user.name %>. Not you?
<%= link_to "Sign out", destroy_user_session_path,:method => :delete %>
<% else %>
<%= link_to "Sign in with Google", user_omniauth_authorize_path(:google_oauth2) %>
<% end %>
I get this error undefined method find_for_google_oauth2 for #
It says the problem is at that line:
#user = user.find_for_google_oauth2(request.env["omniauth.auth"], current_user)
Here is my app/controllers/users/omniauth_callbacks_controller.rb:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user, :event => :authentication #this will throw if #user is not activated
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def google_oauth2
#user = User.find_for_google_oauth2(request.env["omniauth.auth"], current_user)
if #user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google"
sign_in_and_redirect #user, :event => :authentication
else
session["devise.google_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
Here is my app/models/user.rb:
class User < ActiveRecord::Base
before_save :default_values
attr_accessor :delete_photo
validates :first_name, presence: true
validates :last_name, presence: true
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:facebook,:google_oauth2]
has_many :usertoskills
has_many :skills, through: :usertoskills
has_many :usertoprojects
has_many :projects, through: :usertoprojects
has_many :demands
has_many :news
has_attached_file :photo, :styles => { :small => "150x150>", :regular => "300x300>" },
:url => "/assets/users/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/users/:id/:style/:basename.:extension",
:default_url => "/assets/users/default/:style/default.jpg"
validates_attachment_content_type :photo, :content_type => ['image/jpeg', 'image/png']
#def name
# "#{self.first_name.camelize} #{self.last_name.camelize}"
#end
def default_values
if self.first_name && self.last_name
self.name = "#{self.first_name.camelize} #{self.last_name.camelize}"
end
end
def admin
self.role == 'admin'
end
def accessible_demands
if self.role == 'admin'
#demands = Demand.all
else
#demands = []
self.projects.each do |p| #demands.concat(p.demands) end
#demands = Demand.includes(:project).where(projects: { collective: true }, demands: {user_id: self.id}) | #demands
end
return #demands
end
def accessible_projects
if self.role == 'admin'
#projects = Project.all
else
#projects = self.projects
end
return #projects
end
def accessible_transactions
if self.role == 'admin'
#transactions = Transaction.all
else
#transactions = Transaction.where(sender_id: self.id)
end
end
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
#user.first_name = auth.info.first_name
#user.last_name = auth.info.last_name # assuming the user model has a name
#user.image = auth.info.image # assuming the user model has an image
end
def self.find_for_google_oauth2(access_token, signed_in_resource=nil)
data = access_token.info
user = User.where(:provider => access_token.provider, :uid => access_token.uid ).first
if user
return user
else
registered_user = User.where(:email => access_token.info.email).first
if registered_user
return registered_user
else
user = User.create(name: data["name"],
provider:access_token.provider,
email: data["email"],
uid: access_token.uid ,
password: Devise.friendly_token[0,20],
)
end
end
end
end
end
Thanks in advance for your help!
You have mismatched def and end calls in your class - you're missing an end after your def self.from_omniauth(auth) method. The where on the next line is incorrectly indented, hiding it. So in actuality, your find_for_google_oauth2 method is being defined inside your from_omniauth method.
This is one of the reasons that Ruby community conventions are really strict about a two-space indentation policy.
I try to update an existing user:
Controller-Snippet
def account_settings
#user = current_user
end
def set_account_info
old_user = current_user
# verify the current password by creating a new user record.
#user = User.authenticate_by_username(old_user.username, params[:user][:password])
# verify
if #user.nil?
#user = current_user
#user.errors[:password] = "Das eingegebene Passwort ist falsch."
render :action => "account_settings"
else
# update the user with any new username and email
#user.update(params[:user])
# Set the old email and username, which is validated only if it has changed.
#user.previous_email = old_user.email
#user.previous_username = old_user.username
if #user.valid?
# If there is a new_password value, then we need to update the password.
#user.password = #user.new_password unless #user.new_password.nil? || #user.new_password.empty?
#user.save
flash[:notice] = 'Benutzerkonto-Einstellungen wurden übernommen.'
redirect_to :root
else
flash[:error] = #user.username
render :action => "account_settings"
end
end
end
I allready tried post-, put- and patch-method.
Route-Snippet
Calendar::Application.routes.draw do
root "welcome#index"
get "user/account_settings" => "user#account_settings"
patch "user/account_settings" => "user#set_account_info"
end
User-Model
class User < ActiveRecord::Base
attr_accessible :email, :username, :previous_email, :previous_username, :password, :password_confirmation, :new_password, :new_password_confirmation
attr_accessor :password, :new_password, :previous_email, :previous_username
before_save :encrypt_password
validates_confirmation_of :password
validates_confirmation_of :new_password, :if => Proc.new {|user| !user.new_password.nil? && !user.new_password.empty? }
validates_presence_of :password, :on => :create
validates_presence_of :email, :if => Proc.new {|user| user.previous_email.nil? || user.email != user.previous_email}
validates_presence_of :username, :if => Proc.new {|user| user.previous_username.nil? || user.username != user.previous_username}
validates_uniqueness_of :email, :if => Proc.new {|user| user.previous_email.nil? || user.email != user.previous_email}
validates_uniqueness_of :username, :if => Proc.new {|user| user.previous_username.nil? || user.username != user.previous_username}
def initialize(attributes = {})
super # must allow the active record to initialize!
attributes.each do |name, value|
send("#{name}=", value)
end
end
def self.authenticate_by_email(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def self.authenticate_by_username(username, password)
user = find_by_username(username)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
end
The Flash-Notice flash[:error] = #user.username puts the new username, so I dont understand why the user isn't updated in the database.
First I thought my set_account_info-method isn't right, but I have no better idea how to check the inputs.Secondly I changed the form_for method from default(post) to put and then to patch, but that also didn't help.
With rails 4 attr_accessible is no longer used, instead we now have strong params. what this means is that you now need to tell the application what parameters it can update (A whitelist).
This is all done in the controller now, I will give you an example of what I do and see if it helps you in your scenario
class ExampleController < ApplicationController
def create
#object= Object.new(my_params)
if #object.save
redirect_to root_path, notice: 'Object Successfully Created'
else
render action: 'new'
end
end
def update
#object= Object.find(params[:id])
if #object.update_attributes(my_params)
redirect_to root_path, notice: 'Object updated'
else
render action: 'edit'
end
end
private
def my_params
params.require(:object).permit(:id, :title, :overview, :category_id,
nested_attributes: [:id, :gallery_id, :gallery_category_id, :photo, :_destroy])
end
I am new to Rails and I am trying to allow users to login ONLY if a user has a variable email_activation_token set to true. For some reason I created the if statement but it allows a user to sign in REGARDLESS IF IT IS VALUE! I went to sqlitebrowser and checked my database and the user I created indeed has email_activation_token set to false.
Be mindful of two things. I am using HAML and I have a cookie to keep user logged in.
(Bonus points for any answer that has a link to a tutorial on the topic as it would be helpful)
app/controllers/sessions_controller.rb
def create
user = User.authenticate(params[:email], params[:password])
if user.email_activation_token = true
if user
if params[:remember_me]
cookies.permanent[:auth_token] = user.auth_token
else
cookies[:auth_token] = user.auth_token
end
redirect_to root_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
else
flash.now.alert = "You account has not been activated yet check your email!"
render "new"
end
end
app/controller/users_controller
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
UserMailer.registration_confirmation(#user).deliver
redirect_to root_url, :notice => "Signed up!"
else
render "new"
end
def accept_invitation
#user = User.find_by_email_activation_token!(params[:token])
#user.email_activation_token = true
redirect_to root_url, :notice => "Email has been verified."
end
end
end
app/views/sessions/new.html.haml
%h1 Log in
= form_tag sessions_path do
%p
= label_tag :email
= text_field_tag :email, params[:email]
%p
= label_tag :password
= password_field_tag :password
%p.button
%input{name: "commit", type: "submit", value: "Log in"}
.field
= label_tag :remember_me
= check_box_tag :remember_me, 1, params[:remember_me]
%p
= link_to "forgotten password?", new_password_reset_path
app/models/user.rb
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation
attr_accessor :password
before_save :encrypt_password
before_save { |user| user.email = email.downcase }
before_create { generate_token(:auth_token) }
# before_create { generate_token(:email_activation_token) }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
VALID_PASSWORD_REGEX = /^(?=.*[a-zA-Z])(?=.*[0-9]).{6,}$/
validates_confirmation_of :password
validates :password, :on => :create, presence: true, format: { with: VALID_PASSWORD_REGEX }
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64
end while User.exists?(column => self[column])
end
end
app/config/routes.rb
LootApp::Application.routes.draw do
get "password_resets/new"
get "sessions/new"
resources :users
resources :sessions
resources :password_resets
resources :email_activations
resources :users do
collection do
get :accept_invitation
end
end
# get "users/new"
get "static_pages/home"
get "static_pages/help"
root to: 'static_pages#home'
match "sign_up", to: "users#new"
match '/help', to: 'static_pages#help'
match '/log_in', to: 'sessions#new'
match '/log_out', to: 'sessions#destroy'
end
app/controllers/sessions_controller.rb:
def create
# ...
if user.email_activation_token = true
# ...
Should be:
def create
# ...
if user.email_activation_token == true
# ...
I am working on the unread folder for my inbox messaging system. I received a undefined method `unread_messages' when going to /users/1/messages?mailbox=unread and it's pointing to the messages controller. However I have unread_messages defined in the user.rb so that it shows unread messages in the inbox, so I'm assuming the code should also work for the unread folder. Any help would be appreciated.
user.rb:
class User < ActiveRecord::Base
has_secure_password
attr_accessible :role, :age, :age_end, :password_confirmation, :about_me, :feet, :inches, :password, :birthday, :career, :children, :education, :email, :ethnicity, :gender, :height, :name, :password_digest, :politics, :religion, :sexuality, :user_drink, :user_smoke, :username, :zip_code
validates_uniqueness_of :email
validates_format_of :email, with: /^[-a-z0-9_+\.]+\#([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i
validates_presence_of :password, :on => :create
has_many :galleries
has_many :photos, :through => :galleries
before_create { generate_token(:auth_token) }
ROLES = %w[admin user guest banned]
# models/user.rb
after_create :setup_gallery
def received_messages
Message.received_by(self)
end
def unread_messages?
unread_message_count > 0 ? true : false
end
def sent_messages
Message.sent_by(self)
end
# Returns the number of unread messages for this user
def unread_message_count
eval 'messages.count(:conditions => ["recipient_id = ? AND read_at IS NULL", self.user_id])'
end
def to_s; username
end
def has_role?(role_name)
role.present? && role.to_sym == role_name.to_sym
end
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64
end while User.exists?(column => self[column])
end
private
def setup_gallery
self.galleries << Gallery.create
end
end
messages_controller:
def index
if params[:mailbox] == "sent"
#messages = #user.sent_messages
elsif params[:mailbox] == "inbox"
#messages = #user.received_messages
#elsif params[:mailbox] == "archieved"
# #messages = #user.archived_messages
end
if params[:mailbox] == "unread"
#messages = #user.unread_messages
end
end
def new
#message = Message.new
if params[:reply_to]
#reply_to = User.find_by_user_id(params[:reply_to])
unless #reply_to.nil?
#message.recipient_id = #reply_to.user_id
end
end
end
def create
#message = Message.new(params[:message])
#message.sender_id = #user.id
if #message.save
flash[:notice] = "Message has been sent"
redirect_to user_messages_path(current_user, :mailbox=>:inbox)
else
render :action => :new
end
end
def show
#message = Message.find(params[:id])
#message.readingmessage if #message.recipient == current_user
end
def destroy
#message = Message.find(params[:id])
#message.destroy
flash[:notice] = "Successfully deleted message."
redirect_to user_messages_path(#user, #messages)
end
def delete_multiple
if params[:delete]
params[:delete].each { |id|
#message = Message.find(id)
#message.mark_message_deleted(#message.id,#user.id) unless #message.nil?
}
flash[:notice] = "Messages deleted"
end
redirect_to user_messages_path(#user, #messages)
end
private
def set_user
#user = current_user
end
end
message.rb:
attr_accessible :subject, :body, :sender_id, :recipient_id, :read_at,:sender_deleted,:recipient_deleted
validates_presence_of :subject, :message => "Please enter message title"
belongs_to :sender,
:class_name => 'User',
:foreign_key => 'sender_id'
belongs_to :recipient,
:class_name => 'User',
:foreign_key => 'recipient_id'
# marks a message as deleted by either the sender or the recipient, which ever the user that was passed is.
# When both sender and recipient marks it deleted, it is destroyed.
def mark_message_deleted(id,user_id)
self.sender_deleted = true if self.sender_id == user_id
self.recipient_deleted = true if self.recipient_id == user_id
(self.sender_deleted && self.recipient_deleted) ? self.destroy : self.save!
end
# Read message and if it is read by recipient then mark it is read
def readingmessage
self.read_at ||= Time.now
save
end
# Based on if a message has been read by it's recipient returns true or false.
def read?
self.read_at.nil? ? false : true
end
def self.received_by(user)
where(:recipient_id => user.id)
end
def self.not_recipient_deleted
where("recipient_deleted = ?", false)
end
def self.sent_by(user)
Message.where(:sender_id => user.id)
end
end
First of all, you've defined unread_messages? method, not unread_messages
Secondly, you should not use ? : in unread_messages? method:
unread_messages_count > 0
is enough.
You should define unread_messages method in your User model. I can't show the inner code in this method because I don't know your models relations.
You defined
unread_messages? # note the question mark
Then referred to it as
#user.unread_messages # no question mark
You probably want a method
def unread_messages ## which holds the actual unread messages and does not return boolean
So I am trying to setup a view for my friendship model from Amistad, but I keep getting this error: "undefined method `each' for nil:NilClass"
This is my friendship.rb model
class Friendship < ActiveRecord::Base
include Amistad::FriendshipModel
attr_accessible :user_id, :friend_id
end
This is my friendships_controller.rb
class FriendshipsController < ApplicationController
before_filter :authenticate_user!
def index
#friends = current_user.friends
#pending_invited_by = current_user.pending_invited_by
#pending_invited = current_user.pending_invited
end
def create
#Friend = User.find(params[:user_id])
#friendship_created = current_user.invite(#Friend)
end
def approve
#Friend = User.find(params[:user_id])
#friendship_approved = current_user.approve(#Friend)
#friends = current_user.friends
#pending_invited_by = current_user.pending_invited_by
end
def remove
#Friend = User.find(params[:user_id])
#friendship = current_user.send(:find_any_friendship_with, #Friend)
if #friendship
#friendship.delete
#removed = true
end
end
end
My user model user.rb
class User < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
has_many :cereals, dependent: :destroy
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:login]
include Amistad::FriendModel
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :username, :login, :avatar, :avatar_cache, :remove_avatar, :firstname, :lastname, :phone, :urlname
# attr_accessible :title, :body
attr_accessor :login
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions).first
end
end
def update_with_password(params={})
current_password = params.delete(:current_password)
if params[:password].blank?
params.delete(:password)
params.delete(:password_confirmation) if params[:password_confirmation].blank?
end
result = if params[:password].blank? || valid_password?(current_password)
update_attributes(params)
else
self.attributes = params
self.valid?
self.errors.add(:current_password, current_password.blank? ? :blank : :invalid)
false
end
clean_up_passwords
result
end
end
and users_controller.rb
class UsersController < ApplicationController
def show
if params[:id].nil? && current_user
#user = current_user
else
#user = User.find(params[:id])
end
#cereal = current_user.cereals.build if signed_in?
#cereals = #user.cereals.paginate(page: params[:page])
end
def first_time
if params[:id].nil? && current_user
#user = current_user
else
#user = User.find(params[:id])
end
end
def edit
if params[:id].nil? && current_user
#user = current_user
else
#user = User.find(params[:id])
end
end
def profile
#username = params[:id]
#title = "User Profile for #{#username}"
#user = User.find_by_username(#username)
#users = User.all :conditions => ["id != ?", current_user.id]
end
end
Anyone have any idea whats going on? I am still new at rails, and could use some insight.
The View:
.row
#dashboard.span12
= #user.username
#profile_pic=link_to image_tag(#user.avatar, border: '0'), action: 'profile', controller: 'users'
#bowl_outline.span9
Bowl
#friends.span3
Friends
%ul
- for #user in #friends
%li
- if current_user.friend_with? user
= user.username
|
You are already friends!
- elsif current_user.invited? user
= user.username
|
Pending request ...
- elsif user.invited? current_user
= user.username
|
= link_to "Confirm friend?", friend_path(user), :method => "put"
- else
= user.username
= link_to "Add friend?", friends_path(:user_id => #user), :method => "post"
You should not have an instance variable as your for loop variable.
for user in #friends
I believe #friends = current_user.friends returns an array so it should work with this fix.
EDIT
If this is loop is in your user/profile view, you need to have #friends defined in your profile action in your users controller.
def profile
#username = params[:id]
#friends = current_user.friends
#title = "User Profile for #{#username}"
#user = User.find_by_username(#username)
#users = User.all :conditions => ["id != ?", current_user.id]
end
and add before_filter :authenticate_user! to your UsersController.
In ruby, it is common to see the for user in #friends line to be written:
#friends.each do |user|
In this configuration, we have an each message being passed to an object stored in #friends, which might be nil and throwing the error.
Make sure #friends = current_user.friends in your FriendshipsController is not returning nil (you can't iterate over it).
If you are receiving nil, add a default by changing the line to this: #friends = current_user.friends || []