I have just updated to Mailboxer 0.12.4 and followed the instructions in the Github Readme. I had two controllers for working with the Gem
Notifications
class NotificationsController < ApplicationController
before_action :signed_in_user, only: [:create]
def new
#user = User.find(:user)
#message = current_user.messages.new
end
def create
#recepient = User.find(params[:notification][:id])
current_user.send_message(#recepient, params[:notification][:body],params[:notification][:subject])
flash[:success] = "Message has been sent!"
redirect_to user_path #recepient
end
end
Conversations
class ConversationsController < ApplicationController
before_action :signed_in_user
def index
#conversations = current_user.mailbox.conversations.paginate(page: params[:page],:per_page => 5)
end
def show
#conversation = current_user.mailbox.conversations.find_by( :id => params[:id] )
#receipts = #conversation.receipts_for(current_user).reverse!
end
end
My users model has act_as_messagable. After the update this method in my users controller is throwing an error.
uninitialized constant UsersController::Notification
the code that is highlighted is
def show
#user = User.find(params[:id])
#message = Notification.new << this line
....
end
I have tried creating a Notification object in the console and I get the same error. I have read that the update has changed the namespacing but I don't know how to change my code to account for this.
This is the closest I have found to a solution but the guy doesn't say how he fixed it
Ok I got this working I need to figure out why but it seems to be related to namespaces that were introduced in the upgrade to 0.12.4.
Step 1: Change my controllers to
mailboxer_notification_controller.rb
class MailboxerNotificationsController < ApplicationController
before_action :signed_in_user, only: [:create]
def new
#user = User.find(:user)
#message = current_user.messages.new
end
def create
#recepient = User.find(params[:mailboxer_notification][:id])
current_user.send_message(#recepient, params[:mailboxer_notification][:body],params[:mailboxer_notification][:subject])
flash[:success] = "Message has been sent!"
redirect_to user_path #recepient
end
end
Note: that the param names needed to change
mailboxer_conversations_controller.rb
class MailboxerConversationsController < ApplicationController
before_action :signed_in_user
def index
#conversations = current_user.mailbox.conversations.paginate(page: params[:page],:per_page => 5)
end
def show
#conversation = current_user.mailbox.conversations.find_by( :id => params[:id] )
#receipts = #conversation.receipts_for(current_user).reverse!
end
end
Step 2: Anywhere I accessed a method belonging to theses controllers needed to be updated with the correct namespace
def show
#user = User.find(params[:id])
#message = Mailboxer::Notification.new
....
end
Step 3: Update your config/routes.rb
SampleApp::Application.routes.draw do
resources :mailboxer_conversations
resources :mailboxer_notifications, only: [:create]
match '/sendMessage', to: 'mailboxer_notifications#create', via: 'post'
match '/conversations', to: 'mailboxer_conversations#index', via: 'get'
match '/conversation', to: 'mailboxer_conversations#show', via: 'get'
....
end
I'm not sure of the exact reasons these fixes work, I need to spend more time reading about namespaces in rails. If anyone has a good explanation feel free to add to the answer
Related
I've made a very simple blog where users can Create, Edit and Delete posts however I want to add functionality where users can only Edit for a limited time (say 3 days). My understanding of Ruby is not strong enough to know how to do this so any help is appreciated.
This is my Notes (my name for Posts) controller
class NotesController < ApplicationController
before_action :find_note, only: [:show, :edit, :update, :destroy]
def index
#notes = Note.where(user_id: current_user)
end
def show
end
def new
#note = current_user.notes.build
end
def create
#note = current_user.notes.build(note_params)
if #note.save
redirect_to #note
else
render 'new'
end
end
def edit
end
def update
if #note.update(note_params)
redirect_to #note
else
render 'edit'
end
end
def destroy
#note.destroy
redirect_to notes_path
end
private
def find_note
#note = Note.find(params[:id])
end
def note_params
params.require(:note).permit(:title, :content)
end
end
I assume somewhere in the edit method I need to write a rule for restricting the ability to edit posts to only 3 days, using the created_at function somehow? I'm just at a loss as to exactly how to do this.
Any help is appreciated.
Perfect solution for that is :before_filter
class NotesController < ApplicationController
before_filter :check_time!, only: [:edit, :update]
def edit
end
def create
end
private
def check_time!
if Time.now() > #note.created_at + 3.days
flash[:danger] = 'Out of 3 days'
redirect_to note_path(#note)
end
end
end
I have been looking at other people's posts about this question. Unfortunately, still a while later I am stuck on it. I understand that a couple of the controller methods cannot find a story with the relevant 'ID' and render that to the views, hence my error.
However, I don't understand how I can edit my controller methods/routing so it can actually find the id of '1,2,3,4 etc'. I believe it is trying to look for a different from of ID. The 'create' and 'show' methods are creating the same error.
Error on screen:
ActiveRecord::RecordNotFound in StoriesController#create
Couldn't find Story with 'id'=
def find_story
#story = Story.find(params[:id])
end
Here, I have put in ID as the params for the story find method but it isn't finding it. Why?
class StoriesController < ApplicationController
before_action :find_story, only: [:destroy, :create, :show, :edit, :update]
def index
#stories = Story.order('created_at DESC')
end
def new
#story = Story.new
end
def create
#story = Story.new(story_params)
if #story.save
flash[:success] = "Your beautiful story has been added!"
redirect_to root_path
else
render 'new'
end
end
def edit
end
def update
if #story.update.attributes(story_params)
flash[:success] = "More knowledge, more wisdom"
redirect_to root_path
else
render 'edit'
end
end
def destroy
if #story.destroy
flash[:success] = "I think you should have more confidence in your storytelling"
else
flash[:error] = "Can't delete this story, sorry"
end
end
def show
#stories = Story.all
end
private
def story_params
params.require(:story).permit(:name, :description)
end
def find_story
#story = Story.find(params[:id])
end
end
My routes.rb:
Rails.application.routes.draw do
get 'stories/new/:id' => 'posts#show'
resources :stories
devise_for :users
root to: 'stories#index'
end
You want to change the ":find_story" to not include the create as that is what is telling it to look for an id, but there is no id when on the create page, you are creating a new one, not finding one that exists
so change the before_action to this
before_action :find_story, only: [:destroy, :show, :edit, :update]
Your issue with stories is the route you are trying to use. Show looks for an id, for the same reason I mentioned above, so the route need to be something like
stories/show/1
where "1" is the id of the story you want.
ActiveRecord::RecordNotFound in StoriesController#create
you have before_action :find_story with create method which is trying to find Story but there is no :id in params
So you need to remove :create action from the list of before_action and change it to
before_action :find_story, only: [:destroy, :show, :edit, :update]
I have got the same problem.
#table = Table.find(params[:id])
ActiveRecord::RecordNotFound - Couldn't find Table with 'id'=12222:
app/controllers/tables_controller.rb:27:in `edit'
Sol: Try this query
#table = Table.find_by_id(params[:id])
I'm building an app which consists on sharing résumés. I am using Devise gem. Each user is able to create only one résumé. I made the models and and their relations. Resume belongs_to User and User has_one 'Resume'.
After making the views, I wanted to test my app but I got the error: undefined methodbuild' for nil:NilClass`
Here is my ResumeController and my routes.rb
class ResumeController < ApplicationController
before_action :find_resume, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:show]
def show
# #resume = Resume.find_by(params[:id])
end
def new
#resume = current_user.resume.build
end
def create
#resume = current_user.resume.build(resume_params)
if #resume.save
redirect_to #resume, notice: "resume was successfully created"
else
render 'new'
end
end
def edit
end
def update
if #resume.update(pin_params)
redirect_to #resume, notice: "resume was successfully updated"
else
render 'edit'
end
end
def destroy
#resume.destroy
redirect_to root_path
end
private
def resume_params
params.require(:resume).permit(:title, :description)
end
def find_resume
#resume = resume.find(params[:id])
end
end
Routes.rb
Rails.application.routes.draw do
devise_for :users
resources :resume, except: [:index]
get 'static_pages/index'
root to: "static_pages#index"
end
I just want the user to be able to create only one Resume and then he will be able to share it.
Update: After following messanjah's answer there was another error coming from the _form.html.erb: undefined method resumes_path' for #<#<Class:0x00...>. Here is the gist with forms and model: goo.gl/XvW2LH So you can see all the files closely.
Without more knowledge of where the error is happening, I can only suggest some areas that might be suspect.
To build a has_one relationship, you must use the build_*association* constructor.
def new
#resume = current_user.build_resume
end
def create
#resume = current_user.build_resume(resume_params)
end
I am implementing blog app in ruby on rails where I want to restrict normal user( only admin can create) from creating new articles. For this purpose, I have put befor_filter in articles_controller.rb file which is following. I have hided create button from user in UI but still normal user can create new article by typing in address bar of browser.By using below code, normal user can not go on new article page but it gives me "undefined method `is_admin? when i type in address bar. For more info, I have implemented devise for user authentication.
class ArticlesController < ApplicationController
before_filter :is_user_admin, only: [:new, :create]
def is_user_admin
unless current_user.is_admin?
:root
return false
end
end
end
class ArticlesController < ApplicationController
before_filter :is_user_admin, only: [:new, :create]
def is_user_admin
unless current_user.is_admin?
:root
return false
end
end
def index
#articles = Article.all(:order => "created_at DESC")
end
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def create
#article = Article.new(params[:article])
#article.user_id = current_user.id
#article.save
redirect_to article_path(#article)
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to action: 'index'
end
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
#article.update_attributes(params[:article])
flash.notice = "Article '#{#article.title}' Updated!"
redirect_to article_path(#article)
end
end
applicaiton_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
def after_sign_in_path_for(user)
if current_user.is_admin?
dashboard_index_path
else
:root
end
end
end
Basically, I want to restrict normal user (other than admin) to create , update or delete articles either from UI(this is done) or typing address in address bar.
I have no idea why i am getting this and what can i do to avoid this. Should i write above method in application_controller.rb file.
You propably want to redirect users to login so they can't access the action in your controller, if they're not admins. Hence, you could do something like this:
def is_user_admin
redirect_to(action: :index) unless current_user.try(:is_admin?)
end
Your current_user is nil apparently.
You should put before_filter :authenticate_user!, :except => [:show, :index] at the top of your controller in order to authenticate user.
Make sure that at least there is an user before checking for the permission. You can do that adding this code to every controller that requires an authentication:
before_filter :authenticate_user!
Doing this, you will always have a current user and hence will be able to check for its permission the way you pointed on your question.
For some reason, I keep getting this error.
Couldn't find Album without an ID
But that doesn't make sense because in my debug.params it says:
{"utf8"=>"✓",
"authenticity_token"=>"os9DVVZS6//bs3Ne2Xfrh4VnKXNtDXkZaE4s/3iQagE=",
"video"=>{"url"=>"www.youtube.com/watch?v=yIRuri1AB0I",
"album_id"=>"1"},
"commit"=>"Next"}
Here is the controller:
class VideosController < ApplicationController
include AlbumsHelper
before_filter :signed_in_user, only: [:create, :destroy] #add update later
before_filter :correct_user, only: :destroy
def show
#video = Video.find(params[:id])
end
def new
if signed_in?
#album = Album.find(params[:album_id])
#video = #album.build_video
end
end
def create
#album = Album.find(params[:album_id])
#video = #album.build_video(params[:video])
if #video.save
flash[:success] = "Success!"
redirect_to new_small_reward_path(:album_id => #album)
else
render 'new'
end
end
end
I even added a hidden field to the form, which I didn't think I should have to do, but decided to try:
The URL says /videos/new?album_id=1 before you click submit.
This problem completely goes away if I write the controller with this:
def new
##album = Album.find(params[:album_id])
end
and then continue to use the class variable throughout the entire thing. But someone told me that using a class variable is discouraged. How do I do this correctly?
#album = Album.find(params[:video][:album_id])