So this seems simple enough, I have a controller action that looks like this:
class Admin::UsersController < Admin::BaseController
...
def update_password
#user = User.find(params[:user][:id])
#user.password = params[:user][:password]
if #user.save!
Notifier.admin_password_change(#user).deliver
flash[:success] = "Password Changed!"
redirect_to edit_admin_user_path(#user)
else
render "edit"
end
end
end
and it never seems to work. Do I need to something more advanced here? Here's what I see in the rails console:
Started PUT "/admin/users/update_password" for 127.0.0.1 at 2013-07-15 10:01:50 -0600
Processing by Admin::UsersController#update_password as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ipedx2MJDZTQct6I4FUObrzDpMNl3pQWNVr9Ez7bDVc=", "user"=>{"id"=>"226", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Change Password"}
(6.8ms) ALTER SESSION SET EDITION = EPACT_REDESIGN
User Load (8.4ms) SELECT "CRED_APP_USERS".* FROM "CRED_APP_USERS" WHERE "CRED_APP_USERS"."ID_NUMBER" = 10040 AND ROWNUM <= 1
CodeModel Load (9.1ms) SELECT "CRED_CODES".* FROM "CRED_CODES" WHERE (table_name = 'CRED_VEHICLES' OR table_name = 'CRED_FLEET')
User Load (3.6ms) SELECT "CRED_APP_USERS".* FROM "CRED_APP_USERS" WHERE "CRED_APP_USERS"."ID_NUMBER" = :a1 AND ROWNUM <= 1 [["id_number", "226"]]
(3.3ms) UPDATE "CRED_APP_USERS" SET "ENCRYPTED_PASSWORD" = 'ENCRYPTED PASSWORD STRING', "MODIFY_DT" = TO_DATE('2013-07-15 16:01:50','YYYY-MM-DD HH24:MI:SS') WHERE "CRED_APP_USERS"."ID_NUMBER" = 226
Rendered notifier/admin_password_change.erb (0.1ms)
Sent mail to random#person.com (22ms)
...
What am I doing wrong here? The email prints out in the console, and the :success flash appears at the top of the screen, but the password hasn't changed.
Can't say I understand why, but I needed to set a password_reset_token, and then it worked. Here's what the method looks like now:
def update_password
#user = User.find(params[:user][:id])
#user.reset_password_token = 'temp'
#user.save!
if #user.reset_password!(params[:user][:password], params[:user][:password_confirmation])
Notifier.admin_password_change(#user).deliver
flash[:success] = "Password Changed!"
redirect_to edit_admin_user_path(#user)
else
render "edit"
end
end
The token get's blown away when the reset_password! method runs. I couldn't find anything in the docs that alluded to needing a reset_password_token, but it seems to be required. I wouldn't say this code is pretty, but the solution works. If someone else comes up with something better, I'll change my answer.
Related
In my RoR app, I'm passing flash messages using "notice" and "alert".
But, when I'm trying to pass like flash["warning"], for example, I receive: undefined local variable or method warning'
What can I do to be able to create a flash message passing 'warning' value?
Code:
#app/controllers/users/passwords_controller.rb
class Users::PasswordsController < Devise::PasswordsController
def create
user = params["user"]
if User.find_by_email(user["email"]).nil?
set_flash_message(:testing, :email_not_found) if is_navigational_format?
redirect_to root_path
else
self.resource = resource_class.send_reset_password_instructions(user)
if successfully_sent?(resource)
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
else
respond_with(resource)
end
end
end
protected
def after_sending_reset_password_instructions_path_for(resource_name)
root_path
end
end
#app/views/landing/index.html.erb
.
.
<h5><%= testing %></h5>
Any help? Thanks!
Try to use a symbol. flash[:warning] = "XYZ" for example.
Backstory: I'm building a site that takes in a Soundcloud URL as part of a post. Currently, I store the link they provide and, when a user loads their feed view, I retrieve the associated image / title / favorite count etc. via my post_helper. I have quickly come to realize that this is not scalable and is hurting load times.
So, what I think I should do (feel free to tell me that there is a better way), is to retrieve the SC/YT metadata on form submit and store it along with the other post data (id, user, content etc.) in the posts' table entry. How would I go about calling the helper methods to retrieve such on form submit and include the metadata in the submitted params?
post_helper.rb excerpt:
def soundcloud_info(soundcloud_url, type)
begin
resolve = scClient.get('/resolve', :url => soundcloud_url)
track_info = scClient.get("/tracks/#{resolve.id}")
rescue Soundcloud::ResponseError => e
%Q{ Error: #{e.message}, Status Code: #{e.response.code} }
end
if type == "title"
%Q{#{track_info['title']}}
elsif type == "image"
%Q{#{track_info['artwork_url']}}
elsif type == "favCount"
%Q{Favorite count: #{track_info['favoritings_count']}}
end
end
post_controler.rb excerpt:
def create
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Your post was successful!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end
So apparently it's pretty straight forward... all I need to do is modify the parameters in the controller before I call #post = current_user.posts.build(params[:post]). My issue was that I was trying to do so in the helper.
I haven't quite adapted the whole thing to get all my required fields, but here's an example of how I have adapted the create method to pull the api URL out if someone submits SoundCloud's embed iframe.
micropost_controller.rb excerpt:
def create
#url = params[:post][:link_html]
if #url[/^.*src="(https|http):\/\/w.soundcloud.com\/player\/\?url=(.*)">/]
params[:post][:link_html] = CGI::unescape($2)
end
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Your post was successful!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end
I would like to add an optional text_field to add an optional message to the invitation email. So if nothing put into the message then the standard message from invitation_instructions.html.erb should be send otherwise the message of the text_field.
How to do this in devise?
To accomplish this you can use your own mailer instead of having devise email things for you.
Here is how to do it:
class User < ActiveRecord::Base
attr_reader :raw_invitation_token
end
class InvitationsController < Devise::InvitationsController
def create
#from = params[:from]
#subject = params[:invite_subject]
#content = params[:invite_content]
#user = User.invite!(params[:user], current_user) do |u|
u.skip_invitation = true
end
#user.deliver_invitation
email = NotificationMailer.invite_message(#user, #from, #subject, #content)
end
end
class NotificationMailer < ActionMailer::Base
def invite_message(user, venue, from, subject, content)
#user = user
#token = user.raw_invitation_token
invitation_link = accept_user_invitation_url(:invitation_token => #token)
mail(:from => from, :bcc => from, :to => #user.email, :subject => subject) do |format|
content = content.gsub '{{first_name}}', user.first_name
content = content.gsub '{{last_name}}', user.first_name
content = content.gsub '{{full_name}}', user.full_name
content = content.gsub('{{invitation_link}}', invitation_link)
format.text do
render :text => content
end
end
end
end
The raw_invitation_token only exists in newer versions of devise_invitable (compatible with devise >= 3.1).
We are essentially skipping the devise invitation process all together and using our own mailer. We take the content as a parameter and send it as the body of the email. We even substitute placeholders with their actual values.
This solution will give you a lot of flexibility to whatever you want with emails. You can even add a tracking pixel to it if you would like.
I didn't figure out the mechanics of the routing yet..
I have a User, Msg and comment model.
A User creates a Msg and inside the msg i'd like to put simple text box for comments. similar to twitter.
However, When the the form is submitted (using the form below) instead of returning to localhost/msgs/:id it returns to localhost/comments.
I have no view for /comments and I don't want to have. I want all comments to be displayed in msg/:id page.
comments controller:
class CommentsController < ApplicationController
before_filter :authenticate
def create
msgid = flash[:msg]
#current_msg = Msg.find(discid)
#comm = #current_msg.comments.build(params[:comment])
#comm.user_id = current_user.id
#comm.msg_id = msgid
puts discid
if #comm.save
flash[:success] = "Comment posted"
redirect_to msg_path(discid)
else
flash[:error] = "Comment was not posted."
redirect_to msg_path(discid)
end
end
route.rb
match '/comments' , :to => 'msgs#show'
resources :users
resources :msgs
since the comments are displayed in the show view of the msgs here is the show action in the msgs controller
def show
#msg= Msg.find(params[:id])
#title = #msg.title
#comment = Comment.new
#comments = #msg.comments.all
flash[:msg] = #msg.id
end
The error I get is
ActiveRecord::RecordNotFound in MsgsController#show
Couldn't find Msgwithout an ID
and it points to line 46 which at the moment is #msg = Msg.find(params[:id])
If I remove the route line and put a regular resources :comments I get a missing template for comments/create..
Help is appreciated.
Issue solved.. I add a :id => discid in the redirecא_to..
Also used Template is missing to understand the issue
guys!
Prior to asking i should mention, that i`m working without ActiveRecord or any self-hosted-database. So thats why i have to store some values in the session.
From the very begining i desided to set session value of the users city in the layout. - i supposed it would be loaded before anything else. So i`ve done something like this:
<% session[:city] ||= {:name => 'City-Name', :lat => '40', :lng => '40'}%>
But when i`m loading directly to inner page it occurs that session[:city is nil *(
How should i set the session properely, so that it wouldn`t be nil???
I had similar needs in one of the applications I worked on. It needed the users data to be loaded on sign-in and stored in the session. So, wrote a module called session_helpers.rb with the following:
module SessionHelpers
def get_value(key)
session[key.to_sym]
end
protected
def store_data(*objects)
objects.each do |object|
if object.is_a?(Hash)
object.each do |key, value|
session[key.to_sym] = value
end
end
end
end
def remove_data(*objects)
objects.each do |object|
if object.is_a?(String)
key = to_id(object)
else
key = to_id(object.class.name)
end
session[key] = nil
end
end
def update_data(key, value)
session[key.to_sym] = value
end
private
def to_id(name)
"#{name.parameterize('_').foreign_key}".to_sym
end
end
You can make any or all the methods available to views as well:
# application_controller.rb
helper_method :get_value
From the model I would retrieve a hash of the data that needs to be put up in the session about the user:
def common_data
#data = Hash.new
#data.merge!( { 'news' => self.news.count } )
...
#data
end
As I wanted to do this after sign-in I overrode the devise method to do this:
def after_sign_in_path_for(resource_or_scope)
store_data( '_count', current_user.common_data )
dashboard_path
end
This way I was able to load important data about the user on sign-in and store it in the session and retrieve whenever I wanted. Hope this helps.