I am building a inbox messaging system from scratch and when I add self.id to the condition in the model I get a undefined method `id' error on all pages with a title of NoMethodError in MessagesController. I have tried a few workarounds though I can't get a grip on it.
messages_controller:
class MessagesController < ApplicationController
before_filter :set_user
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
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.recepient_id = #reply_to.user_id
end
end
end
def create
#message = Message.new(params[:message])
#message.sender_id = params[: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.readingmessage(params[:id],#user_id)
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
user.rb:
:conditions => ["messages.recipient_deleted = ? AND messages.recipient_id = ?",false,self.id]
..
..
def unread_messages?
unread_message_count > 0 ? true : false
end
# Returns the number of unread messages for this user
def unread_message_count
eval 'messages.count(:conditions => ["recepient_id = ? AND read_at IS NULL", self.user_id])'
end
Related
I'm currently trying to store an updated value in the database.
The process is the following, a user chooses to buy 3 bottles, the stock goes down by -3. The stock is set within the Wines Controller and then displayed in the reservations controller for the user
The current problem is that for each new reservation, the stock get's reset in the reservations controller, since the stock isn't updating in the wines controller.
Here lays the problem:
#reservation.in_stock = wine.in_stock - #reservation.bottle
Here is my full Reservations Controller:
class ReservationsController < ApplicationController
before_action :authenticate_user!
before_action :set_reservation, only: [:approve, :decline]
def create
wine = Wine.find(params[:wine_id])
if current_user == wine.user
flash[:alert] = "Du kannst nicht deinen eigenen Wein kaufen!"
else
start_date = Date.parse(reservation_params[:start_date])
#reservation = current_user.reservations.build(reservation_params)
#reservation.wine = wine
#reservation.price = wine.price
#reservation.in_stock = wine.in_stock - #reservation.bottle
#reservation.total = wine.price * #reservation.bottle
# #reservation.save
if #reservation.save
if wine.Reservieren?
flash[:notice] = "Anfrage versendet!"
else
#reservation.Bearbeitung!
flash[:notice] = "Eroflgreich bestellt!"
end
else
flash[:alert] = "Can't make a reservation!"
end
end
redirect_to wine
end
def your_orders
#orders = current_user.reservations.order(start_date: :asc)
end
def your_reservations
#wines = current_user.wines
redirect_to root_path unless current_user.admin == true
#count = Reservation.count(:all)
#total = Reservation.sum(:total)
end
def your_upcoming_reservations
#wines = current_user.wines
redirect_to root_path unless current_user.admin == true
end
def approve
#reservation.Versendet!
redirect_to your_reservations_path
redirect_to root_path unless current_user.admin == true
end
def decline
#reservation.Abgelehnt!
redirect_to your_reservations_path
redirect_to root_path unless current_user.admin == true
end
# Each Order Details
def order_details
#orders = current_user.reservations.order(start_date: :asc)
end
private
def set_reservation
#reservation = Reservation.find(params[:id])
end
def set_stock
#reservation.in_stock = wine.in_stock
end
def reservation_params
params.require(:reservation).permit(:start_date, :bottle, :in_stock)
end
end
I added a link_to method to the view to allow users to select messages from the inbox to delete. I am using the Mailboxer gem. The error I receive when adding the code is ActiveRecord::RecordNotFound Couldn't find Conversation without an ID. Error points to the controller on line #conversation ||= mailbox.conversations.find(params[:id])
index.html.slim:
ul.right
li
= link_to 'Move to trash', [:trash, conversation], method: :post
img alt="" src="/assets/del_icon.png" /
li
input type="checkbox" class='select_conversations'
Conversations controller:
helper_method :mailbox, :conversation
before_filter :conversation, only: :show
before_filter :check_has_access
def index
#user = current_user
sentbox_page = params[:page] if params[:sentbox].present?
inbox_page = params[:page] if params[:inbox].present?
mailbox = #user.mailbox
#inbox = mailbox.inbox.paginate(:page => inbox_page, :per_page => 5)
#sentbox = mailbox.sentbox.paginate(:page => sentbox_page, :per_page => 5)
render layout: 'new_application'
end
def show
user = current_user
#receipts = conversation.receipts_for(user).paginate(:page => params[:page], :per_page => 5)
#conversation.receipts.recipient(user).update_all(is_read: true)
respond_to do |format|
format.html {render layout: 'new_application'}
format.js {}
end
end
def reply
current_user.reply_to_conversation(conversation, *message_params(:body, :subject))
redirect_to conversation
end
def trash_folder
#trash ||= current_user.mailbox.trash.all
end
def trash
conversation.move_to_trash(current_user)
redirect_to :conversations
end
def untrash
conversation.untrash(current_user)
redirect_to :conversations
end
def empty_trash
current_user.mailbox.trash.each do |conversation|
conversation.receipts_for(current_user).update_all(:deleted => true)
end
redirect_to :conversations
end
private
def mailbox
#mailbox ||= current_user.mailbox
end
def conversation
#conversation ||= mailbox.conversations.find(params[:id])
end
def conversation_params(*keys)
fetch_params(:conversation, *keys)
end
def message_params(*keys)
fetch_params(:message, *keys)
end
def fetch_params(key, *subkeys)
params[key].instance_eval do
case subkeys.size
when 0 then self
when 1 then self[subkeys.first]
else subkeys.map{|k| self[k] }
end
end
end
protected
def check_has_access
redirect_to(root_url) unless Subscription.exists?(user_id: current_user.try(:id) || -1, cancelled: nil)
end
end
The error is caused by the combination of these lines.
# in the controller
helper_method :mailbox, :conversation
# in the view
= link_to 'Move to trash', [:trash, conversation], method: :post
What happens is that the conversation variable called in the view is the controller method. Since you're in the index page, you don't have a params[:id] which causes find to raise the exception.
The easiest solution would be to remove conversation as a helper and just use #conversation in the view.
I have internal messages in my application. I am using devise and I have installed password module but did not configured it yet. when I tried to press on Forget Password? I got this error:
No route matches {:controller=>"messages", :mailbox=>:inbox, :user_id=>nil}
So what I need is: How to solve this problem ? and How to make the forget password feature works for action mailer so user can reset his password using the email which saved in the database.
Note: Before installing internal messages into my app , when i tried to click forget password link it was redirecting normally.
I am using another controller for registration instead of that one by devise and on signup , users are added by admin.
this is from my routes file
devise_for :users, :controllers => { :registrations => "users" }
resources :users, only: [:index, :new, :create, :show, :destroy, :edit, :update] do |user|
resources :messages do
collection do
post 'delete_multiple'
end
end
end
Forget Password link
<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
<%= link_to "Forgot your password?", new_password_path(resource_name), :class => "btn btn-danger" %><br />
<% end -%>
Users_Controller.rb
class UsersController < ApplicationController
load_and_authorize_resource
def index
#users = User.all
#users_grid = initialize_grid(User,
:per_page => 5)
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = 'A new user created successfully.'
redirect_to users_path
else
flash[:error] = 'An error occurred please try again!'
redirect_to users_path
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
flash[:notice] = 'Profile updated'
redirect_to users_path
else
render 'edit'
end
end
def destroy
#user = User.find(params[:id])
if current_user == (#user)
flash[:error] = "Admin suicide warning: Can't delete yourself."
else
#user.destroy
flash[:notice] = 'User deleted'
redirect_to users_path
end
end
end
Messaages_controller.rb
class MessagesController < ApplicationController
before_filter :set_user
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
end
def new
#message = Message.new
if params[:reply_to]
#reply_to = User.find_by_id(params[:reply_to])
unless #reply_to.nil?
#message.recepient_id = #reply_to.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.readingmessage(params[:id],#user.id)
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
Since it's showing user_id => nil. Can you check if your session is not expired
I upgraded to rails 4 and now I am no longer able to register users on my app. It seems like my gallery (carrierewave) has broken down. I have inspected the code and can't notice anything that would stop it from working now. I get a undefined method `galleries' and it points to def setup_gallery: self.galleries << Gallery.create and under def create: if #user.save
Fresh eyes on my code would be great.
Users controller:
class UsersController < ApplicationController
respond_to :html, :json
def settings
#user = User.find(id_params)
end
def new
#user = User.new
end
def profile
#profile = User.profile
end
def create
#user = User.new(user_params)
if #user.save
UserMailer.registration_confirmation(#user).deliver
session[:user_id] = #user.id
redirect_to root_url, notice: "Thank you for signing up!"
else
render "new"
end
end
def show
#user = User.find(id_params)
end
def edit
#user = User.find(id_params)
end
def index
#users = User.all
end
def destroy
User.find(id_params).destroy
flash[:success] = "User deleted."
redirect_to users_url
end
def update
#user = if current_user.has_role?(:admin)
User.find(id_params)
else
current_user
end
#user.update_attributes(user_params)
respond_with #user
end
private
def user_params
params.require(:user).permit(:name, :email, :username, :password, :zip_code, :birthday, :role)
end
def id_params
params.require(:id).permit(:name)
end
end
User model:
# 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 unread_messages
received_messages.where('read_at IS NULL')
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
photos controller:
class PhotosController < ApplicationController
def new
#photo = Photo.new
end
def create
#photo = Photo.new(photo_params)
#photo.user = current_user
if #photo.save
flash[:notice] = "Successfully created photos."
redirect_to :back
else
render :action => 'new'
end
end
def edit
#photo = Photo.find(id_params)
end
def update
#photo = Photo.find(id_params)
if #photo.update_attributes(photo_params)
flash[:notice] = "Successfully updated photo."
redirect_to #photo.gallery
else
render :action => 'edit'
end
end
def destroy
#photo = Photo.find(id_params)
#photo.destroy
flash
[:notice] = "Successfully destroyed photo."
redirect_to #photo.gallery
end
private
def user_params
params.require(:user).permit(:name)
end
def id_params
params.require(:id).permit(:name)
end
end
After some trial and error I found that I had to change the private method in the user model.
What works is,
Gallery.create(user: self)
Thanks for those who responded to help!
I have a Question & Answer feature and I am just about finished with it. I have no idea how to do the code that would send a message to user when another user has asked them a question. For example, User A sends User B a question, a inbox message is sent to User B notifying them that they have a new question.
There's two ways I thought how to go about this.
Method #1
Inside the message it will link user to the page with the Question on it so it can be answered
Method #2
Inside the message it will include the question that was asked. User can reply to message which would submit as their answer.
Questions controller:
respond_to :js, :html
def index
#questions = Question.all
respond_with(#questions)
end
def show
#question = Question.find(params[:id])
#questions = Question.order("created_at DESC")
respond_with(#questions)
end
def new
#question = Question.new
respond_with(#question)
end
def create
#question = Question.new(params[:question])
if #question.save
redirect_to questions_path, notice: 'Your question was saved successfully. Thanks!'
else
render :new, alert: 'Sorry. There was a problem saving your question.'
end
end
end
Answers controller:
def new
#question = Question.find(params[:question_id])
end
def create
#question = Question.find(params[:question_id])
if #question.update_attributes(params[:question])
redirect_to questions_path
else
render :new
end
end
end
Messages controller:
before_filter :set_user
def index
if params[:mailbox] == "sent"
#messages = #user.sent_messages
elsif params[:mailbox] == "inbox"
#messages = #user.received_messages
#elsif params[:mailbox] == "archived"
# #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_sender_id(params[:reply_to])
unless #reply_to.nil?
#message.recipient_id = #reply_to.sender_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 model:
attr_accessible :subject, :body, :sender_id, :recipient_id, :read_at,:sender_deleted,:recipient_deleted
validates_presence_of :subject, :message => "Please enter message title"
has_many :notifications, as: :event
scope :unread, -> {where('read_at IS NULL')}
scope :not_deleted_by_recipient, where('messages.recipient_deleted IS NULL OR messages.recipient_deleted = ?', false)
scope :not_deleted_by_sender, where('messages.sender_deleted IS NULL OR messages.sender_deleted = ?', false)
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
def previous(same_recipient = true)
collection = Message.where('id <> ? AND created_at > ?', self.id, self.created_at).order('created_at ASC')
collection = collection.where(recipient_id: self.recipient_id) if same_recipient
collection = collection.not_deleted_by_recipient
collection.first
end
def next(same_recipient = true)
collection = Message.where('id <> ? AND created_at < ?', self.id, self.created_at).order('created_at DESC')
collection = collection.where(recipient_id: self.recipient_id) if same_recipient
collection = collection.not_deleted_by_recipient
collection.first
end
end
private
def send_notification(message)
message.notifications.create(user: message.recipient)
end
I have solved this.
Questions Controller:
def create
#question = Question.new(params[:question])
if #question.save
#message = Message.create(:subject => "Hey you have a message from #{#question.sender_id}",
:sender_id => #question.sender_id,
:recipient_id => #question.recipient_id,
:body => #question.question)
#question.message = #message
#question.save
redirect_to questions_path, notice: 'Your question was saved successfully. Thanks!'
else
render :new, alert: 'Sorry. There was a problem saving your question.'
end
end
Every time a notification is needed, you should create it. It would go for having a Notification model that takes at least the object for which the notification was created, the user that the notification goes to and a flag whether it has been read or not.
To display the notifications, the easiest way of course is to integrate that into your layout file and do something like this:
Notification.where(:user_id => #current_user).size > 0
<%= "You have #{Notification.where(:user_id => #current_user).size} notification(s)" %>
end
And to nicen things up you can create a scope inside of the Notification object which will give you the notifications for a specific user. Of course if you want all the magic like Stackoverflow has with updating the notifications through AJAX calls, you will have to do some JavaScript lifting.