I want my visitors to be able to edit or delete their comment up too 5-10 min after they created it.
How should I authenticate this with a session or cookie?
My comment controller:
class CommentsController < ApplicationController
# GET /comments
# GET /comments.xml
# GET /comments/new
# GET /comments/new.xml
def new
#comment = Comment.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #comment }
end
end
# GET /comments/1/edit
def edit
#comment = Comment.find(params[:id])
end
# POST /comments
# POST /comments.xml
def create
#blog = Blog.find(params[:blog_id])
params[:comment][:ip] = request.remote_ip
#comment = #blog.comments.create!(params[:comment])
redirect_to #blog
end
# PUT /comments/1
# PUT /comments/1.xml
def update
#comment = Comment.find(params[:id])
respond_to do |format|
if #comment.update_attributes(params[:comment])
format.html { redirect_to(admin_comments_path, :notice => 'Comment was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #comment.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.xml
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to(admin_comments_url, :notice => 'Indlæg slettet') }
format.xml { head :ok }
end
end
end
store the saved comment's id in the session and then at the time of delete or update, check the session for the comment's id and compare the current-time with the comment's created_at... this can go in a filter method.
Also, you can move the code of finding the comment with id in a filter and can follow DRY.
Here it goes:
class CommentsController < ApplicationController
before_filter :get_blog
before_filter :get_comment, :only => [:edit, :update, :destroy]
before_filter :authorize_comment, :only => [:edit, :update, :destroy]
private
def get_blog
#blog = Blog.find(params[:blog_id])
end
def get_comment
#comment = Comment.find(params[:id])
end
def authorize_comment
unless #comment
flash[:error] = "Comment Not Found"
redirect_to #blog and return
else
# checks whether the comment is there in sessions' recent_comments
# if true, it means, this comment was created by the same visitor who is now attempting to delete/update it again
if session[:recent_comments].include?(#comment.id)
# now check if the comment is editable w.r.t time or not
if #comment.created_at < 10.minutes.ago
# if true, it means comment can no longer be updated/deleted
# if you wish you can now remove this from the session's recent_comments
session[:recent_comments].delete(#comment.id)
flash[:error] = "Sorry, you can not change this comment now"
redirect_to #blog and return
else
# it means comment can be edited/updated
return true
end
else
flash[:error] = "Sorry, you can not change this comment now"
redirect_to #blog and return
end
end
end
public
def new
#comment = Comment.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #comment }
end
end
def edit
end
def create
params[:comment][:ip] = request.remote_ip
#comment = #blog.comments.create!(params[:comment])
unless session[:recent_comments].is_a?(Array)
session[:recent_comments] = []
end
session[:recent_comments] << #comment.id
redirect_to #blog
end
def update
respond_to do |format|
if #comment.update_attributes(params[:comment])
format.html { redirect_to(admin_comments_path, :notice => 'Comment was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #comment.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#comment.destroy
respond_to do |format|
format.html { redirect_to(admin_comments_url, :notice => 'Indlæg slettet') }
format.xml { head :ok }
end
end
end
Related
I was coding my Devise/CanCan combo authorization setup and running some debugging.
I keep encountering this statement everytime I refresh my browser.
Processing by Admin::UsersController#index as HTML
DEPRECATION WARNING: Relation#first with finder options is deprecated. Please bu
ild a scope and then call #first on it instead. (called from C:in `first':)
The deprecation warning says that it comes from the C:in 'first'.
But what does that supposed to mean?!?
Where am I supposed to find that in my RoR environment? Looks like it's to be found on a C folder. But my ROR project is on the D drive, not C!
Has anybody seen this warning before?
class Admin::UsersController < Admin::AdminController
load_and_authorize_resource
#def get_user
# #current_user = current_user
#end
# GET /users
# GET /users.json
def index
#users = User.all
##users = User.accessible_by(current_ability, :index).limit(20)
respond_to do |format|
format.json { render :json => #users }
format.xml { render :xml => #users }
format.html
end
end
# GET /users/1
# GET /users/1.json
def show
#user = User.find(params[:id])
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
end
# GET /users/new
def new
#user = User.new
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:json, :xml, :html)
end
# GET /users/1/edit
def edit
#user = User.find(params[:id])
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:json, :xml, :html)
end
# POST /users
# POST /users.json
def create
#user.attributes = params[:user]
#user.role_ids = params[:user][:role_ids] if params[:user]
#user = User.new(params[:user])
respond_to do |format|
if #user.save
flash[:notice] = flash[:notice].to_a.concat #user.errors.full_messages
format.html { redirect_to root_url, notice: 'Signed Up!' }
format.json { render action: 'show', status: :created, location: #user }
else
flash[:notice] = flash[:notice].to_a.concat #user.errors.full_messages
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
#user = User.find(params[:id])
if params[:user][:password].blank?
[:password,:password_confirmation,:current_password].collect{|p| params[:user].delete(p) }
else
#user.errors[:base] << "The password you entered is incorrect" unless #user.valid_password?(params[:user][:current_password])
end
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:js, :xml, :html)
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:json, :xml, :html)
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
##user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:username, :password, :password_confirmation)
end
end
In my Rails app, I have a comments scaffold which lets users comment on a movie.
I am faced with two problems.
The first problem is that anyone can create a comment, even if they are not signed in, how would I assign a comment to a user, so if there is a current_user, they can create a comment and I would be able to assign the user to the comment so <%= comment.user.first_name %>, and if they are not signed in, they cant create a comment. How would i do this? ( I am using devise )
The second problem is that when I create a comment, it takes me to this path (where 12 is :movie_id)
localhost:3000/movies/12/comments/new
This is fine but when i am creating the comment, I have to specify the movie_id (12), how this be done automatically, so rails sees that the movie_id for the comment is 12.
My Comments Controller, incase needed
class CommentsController < ApplicationController
# GET /comments
# GET /comments.json
before_filter :load_movie
def index
#comments = #movie.comments.all
#search = Movie.search(params[:q])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #comments }
end
end
# GET /comments/1
# GET /comments/1.json
def show
#comment = Comment.find(params[:id])
#search = Movie.search(params[:q])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #comment }
end
end
# GET /comments/new
# GET /comments/new.json
def new
#comment = Comment.new
#search = Movie.search(params[:q])
respond_to do |format|
format.html # new.html.erb
format.json { render json: #comment }
end
end
# GET /comments/1/edit
def edit
#comment = Comment.find(params[:id])
#search = Movie.search(params[:q])
end
# POST /comments
# POST /comments.json
def create
#comment = Comment.new(params[:comment])
#search = Movie.search(params[:q])
respond_to do |format|
if #comment.save
format.html { redirect_to :back }
format.json { render json: #comment, status: :created, location: #comment }
else
format.html { render action: "new" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# PUT /comments/1
# PUT /comments/1.json
def update
#comment = Comment.find(params[:id])
#search = Movie.search(params[:q])
respond_to do |format|
if #comment.update_attributes(params[:comment])
format.html { redirect_to (#movie), notice: 'Comment was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
# DELETE /comments/1
# DELETE /comments/1.json
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
respond_to do |format|
format.html { redirect_to comments_url }
format.json { head :no_content }
end
end
private
def load_movie
#movie = Movie.find_by_id(:movie_id)
end
end
First:
using devise, you can request that a user is signed in by saying at the top of your controller:
before_filter :authenticate_user!, only: [:new,:create]
so if someone not signed in tries to access these actions, they are redirected to the sign in page and after sign in forwarded to the original request.
Second:
As you can see from the routes, 12 is assigned to params[:movie_id]. So in your controllers new action write:
#movie = Movie.find(params[:movie_id])
#comment = #movie.comments.new
#comment.user=current_user
I have a simple blog application. When posts are added, i want the users id to be added to the post so that when a user is logged in, he can only see his posts. The id i want to add to the post, is the id of the user currently logged in.
How and where could the id attribute be added to the posts model?
Session controller:
class SessionsController < ApplicationController
def new
end
def create
user = User.authenticate(params[:username], params[:password])
if user
session[:user_id] = user.id
redirect_to blog_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => "Logged out!"
end
end
Application controller:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :authenticate
helper_method :current_user
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def authenticate
redirect_to log_in_path unless session != nil
end
end
Posts controller:
class PostsController < ApplicationController
# GET /posts
# GET /posts.json
def index
#posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #posts }
end
end
# GET /posts/1
# GET /posts/1.json
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
# GET /posts/new
# GET /posts/new.json
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
end
# GET /posts/1/edit
def edit
#post = Post.find(params[:id])
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(params[:post])
post.user_id = session
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PUT /posts/1
# PUT /posts/1.json
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post = Post.find(params[:id])
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url }
format.json { head :no_content }
end
end
end
Thanks in advance!
In PostsController
def create
#post = current_user.posts.build(params[:post])
...
end
I am working on a project and im very new to rails,
I can't figure out what is wrong exectly.
I get this error.
NoMethodError in Products#index
uninitialized constant ProductsController::Offer
Esentially I have a feature im trying to implement.
in my products table I have a column called reserve price, I want a userto submit a number on the form on the products page which then validates it againts the reserve price, if accepted it gets added to cart , if not flash please enter higher offer,
the problem is I just can't seem to figure out how to get the model and controllers to work in tandem.
Iv'e been at this all week and I still don't have a clue.
I wondered if anyone could look at my code and see what im missing as for the view page I am getting the error that the undefined method `model_name' for NilClass:Class and I was sure I inputed the right model for the form, if I can get that working I can get the rest done quick but I dunno what im missing.
offer controller.rb
class OffersController < ApplicationController
attr_accessible :product, :offer , :reserve_price
def new
#offer = Offer.new
end
end
offer model.rb
class Offer < ActiveRecord::Base
belongs_to :product
has_many :reserve_prices
attr_accessible :product, :offer , :reserve_price
validates_presence_of :offer
validate :ensure_meets_reserve_price
private
def ensure_meets_reserve_price
if amount < self.product.reserve_price
errors.add(:amount, "does not meet reserve price")
end
end
private
def reserve_price
product.reserve_price
end
def your_offer
#your_offer = Offer.new
end
def new
#offer = Offer.new = :your_offer
end
end
Products index view file
class ProductsController < ApplicationController
before_filter :authenticate, :except => [:index, :show]
# GET /products
# GET /products.xml
def index
#offer = Offer.new
#products = Product.search(params[:search_query])
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #products }
end
end
# GET /products/1
# GET /products/1.xml
def show
#product = Product.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #product }
end
end
# GET /products/new
# GET /products/new.xml
def new
#product = Product.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #product }
end
end
# GET /products/1/edit
def edit
#product = Product.find(params[:id])
end
# POST /products
# POST /products.xml
def create
#product = current_user.products.new(params[:product])
respond_to do |format|
if #product.save
format.html { redirect_to(#product, :notice => 'Product was successfully created.') }
format.xml { render :xml => #product, :status => :created, :location => #product }
else
format.html { render :action => "new" }
format.xml { render :xml => #product.errors, :status => :unprocessable_entity }
end
end
end
# PUT /products/1
# PUT /products/1.xml
def update
#product = Product.find(params[:id])
respond_to do |format|
if #product.update_attributes(params[:product])
format.html { redirect_to(#product, :notice => 'Product was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #product.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.xml
def destroy
#product = Product.find(params[:id])
#product.destroy
respond_to do |format|
format.html { redirect_to(products_url) }
format.xml { head :ok }
end
end
end
Products controller.rb
class ProductsController < ApplicationController
before_filter :authenticate, :except => [:index, :show]
# GET /products
# GET /products.xml
def index
#products = Product.search(params[:search_query])
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #products }
end
end
# GET /products/1
# GET /products/1.xml
def show
#product = Product.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #product }
end
end
# GET /products/new
# GET /products/new.xml
def new
#product = Product.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #product }
end
end
# GET /products/1/edit
def edit
#product = Product.find(params[:id])
end
# POST /products
# POST /products.xml
def create
#product = current_user.products.new(params[:product])
respond_to do |format|
if #product.save
format.html { redirect_to(#product, :notice => 'Product was successfully created.') }
format.xml { render :xml => #product, :status => :created, :location => #product }
else
format.html { render :action => "new" }
format.xml { render :xml => #product.errors, :status => :unprocessable_entity }
end
end
end
# PUT /products/1
# PUT /products/1.xml
def update
#product = Product.find(params[:id])
respond_to do |format|
if #product.update_attributes(params[:product])
format.html { redirect_to(#product, :notice => 'Product was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #product.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.xml
def destroy
#product = Product.find(params[:id])
#product.destroy
respond_to do |format|
format.html { redirect_to(products_url) }
format.xml { head :ok }
end
end
end
any help?
much appricated ive been at this a while and have not figured it out!
If I understand your question correctly:
the error shows when accessing products#show
you want to include an offer form in the product#show page
In that case, you need to initialize the #offer variable in the ProductsController show action like so:
#offer = Offer.new
ADDITION
to next Problem: ProductsController::Offer is unknown, which it should not be as you have a Offer model. I've just tried including your Offer form into a show action, and it rendered it ok, apart from that you initialize the field with a new instance of Offer. (maybe an amount rather?). Anyway, I can't see from your code snippets why the Offer model is not available in your controller. can you provide the complete source?
I first suspected your strange private methods in Offer
def your_offer
#your_offer = Offer.new
end
def new
#offer = Offer.new = :your_offer
end
to be the cause, but I've included them and the form renders fine. But I what the heck are they supposed to do?
I get this error when trying to register a new user.
NoMethodError (undefined method save' for nil:NilClass):
app/controllers/users_controller.rb:49:increate'
app/controllers/users_controller.rb:48:in `create'
class UsersController < ApplicationController
before_filter :require_no_user, :only => [:new, :create]
before_filter :require_user, :only => [:show, :edit, :update]
#filter_resource_access
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
end
end
def show
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #user }
end
end
def new
##user = User.new
#carriers = Carrier.find(:all)
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #user }
end
end
def edit
end
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = "Account registered!"
redirect_back_or_default account_url
else
render :action => :new
end
end
def profile
#user = User.find(params[:id])
end
def update
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to(#user, :notice => 'User was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to(users_url) }
format.xml { head :ok }
end
end
def delete
#user = User.find(params[:user_id])
#user.destroy
redirect_to :users
end
end
without seeing your view code, its hard to say, but since you have commented out the #user object that is sent to the new view, perhaps the params coming back from the view are not defined as key value pairs from the form as user attributes?
The error is happening because the #user variable is nil, so calling (nil).save will fail. This means that User.new(params[:user]) is returning nil, which should never happen. User.new should always return a record, even if it is invalid.
So, since the controller looks pretty ordinary, I'll take a shot in the dark and suggest checking your User model for a 'new' method. You might be overriding ActiveRecord's 'new' method with some logic that returns nil and breaks your controller. If so, you must replace 'def new' with a different method name.
If that doesn't help, please provide us with the code in your User model.