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])
Related
In the comments controller, I am redirecting to the articles show page after both create and destroy.
So I decided to write an after_action which would do the redirect_to.
class CommentsController < ApplicationController
before_action :find_article
before_action :find_comment, only: [:destroy]
after_action :goto_articles_page, only: [:create, :destroy]
def create
#comment = #article.comments.create(comment_params)
end
def destroy
#comment.destroy
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
def find_article
#article = Article.find(params[:article_id])
end
def find_comment
#comment = #article.comments.find(params[:id])
end
def goto_articles_page
redirect_to article_path(#article) and return
end
end
But this gives me AbstractController::DoubleRenderError after both create and destroy.
Why am I getting this error?
By default, Rails will render views that correspond to the controller action. See Rails Guides.
So in your create and destroy actions, Rails is performing a render by default. Then your after_action (which happens after the action) is redirecting, so it's double rendering.
Instead of an after_action, you could call the goto_articles_page method in your controller actions.
For example:
def destroy
#comment.destroy
goto_articles_page
end
def goto_articles_page
redirect_to article_path(#article) #return not needed
end
I think using return when rendering any action but when redirect_to use then not need to use return then finally you can remove and return
Rails guide very nicely explained that you can follow this carefully
redirect_to explanation
Hope to help
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've been putting the finishing touches on my app all day with the help of some useful answers here and would like to know how this feature can be executed. I have an idea set up in my post_controller file where I want to show the top 10 most recent posts created based on the date that they were created. I also plan on doing this for my comments as well laster on. I am showing all users post in the views/post/index.html.erb file. I wrote this line of code in the posts_controller: posts = Post.order('created_at DESC').limit(10). I've searched here thoroughly but don't understand how some other users got this to work, any insight? Thanks in advance.
posts_controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :vote]
before_action :require_user, only: [:new, :create, :edit, :update, :vote]
before_action :require_creator, only:[:edit, :update]
def index
posts = Post.order('created_at DESC').limit(10)
#posts = Post.all.page(params[:page]).per_page(10)
end
def show
#comment = Comment.new
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.creator = current_user
if #post.save
flash[:notice] = "You created a post!"
redirect_to posts_path
else
render :new
end
end
def edit
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
flash[:notice] = "You updated the post!"
redirect_to post_path(#post)
else
render :edit
end
end
def vote
Vote.create(voteable: #post, creator: current_user, vote: params[:vote])
respond_to do |format|
format.js { render :vote } # Renders views/posts/vote.js.erb
end
end
private
def post_params
params.require(:post).permit(:url, :title, :description)
end
def set_post
#post = Post.find(params[:id])
end
def require_creator
access_denied if #post.creator != current_user
end
end
The posts variable you've declared in your index action will not be available in your view. What you need to do is update the line where you're retrieving the posts using instance variable as follows:
def index
#posts = Post.page(params[:page]).order('created_at DESC').per_page(10)
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.
If I generate a scaffold I get the standard actions index, new, show, create .... all of which contain a line e.g. like
#comment = Comment.find(params[:id])
Does it make sense to put this line in a seperate method into the controller like
def load
#comment = Comment.find(params[:id])
end
Is this an advantage? Thx for your time
Yes to the separate method, and also yes to using a before_filter.
class CommentsController < ApplicationController
# Whitelist your before_filter like this. Or you can blacklist it with :except => []
before_filter :load_comment, :only => [:edit, :update, :destroy, :show]
def show
end
def index
#comments = Comment.all
end
def new
#comment = Comment.new
end
# etc ...
protected
def load_comment
#comment = Comment.find(params[:id])
end
end