How to invoke a rails sweeper in this scenario? - ruby-on-rails-3

As you can see from code below. I am caching the show action. I also have the following method in the show action View.create_for(#song).
I would like to make it so, when View.create_for(#song) is called, it clears out the respective cache.
How would I go about this? Do I have to manually invoke the rails sweeper in the View model? If so, how?
My controller:
class SongsController < ApplicationController
caches_action :show, :cache_path => (proc do
song_path(params[:id], :user_id => user_signed_in? ? current_user.id : nil)
end)
# I tried with the following line, but this is not what I want. I only want to call the sweeper when `View.create_for(#song)` is called:
# cache_sweeper :views_sweeper, :only => [:show]
def show
#song = Song.find(params[:id])
View.create_for(#song)
end
end
My Sweeper:
class SongsSweeper < ActionController::Caching::Sweeper
observe Song
def after_save(song)
expire_fragment(/songs\/#{song.id}\/.*?/)
end
end

I think you should be referring to the songs_sweeper, not the views_sweeper:
cache_sweeper :songs_sweeper, :only => [:show]
I'm not sure of your requirements, but you could also be more specific in your SongsSweeper by changing after_save to after_create:
class SongsSweeper < ActionController::Caching::Sweeper
observe Song
def after_create(song)
expire_fragment(/songs\/#{song.id}\/.*?/)
end
end

Related

Issue with helper_methods from views rails

I have a very frustrating issue.
I can't call any helper method from my views in rails.This is what I have:
ApplicationController.rb
class ApplicationController < ActionController::Base
protect_from_forgery
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
helper_method :all
end
/app/views/welcome/_navi_bar.haml:
%ul.nav.nav-pills.pull-right
%li.pull-right
- if current_user
%a.btn-small{"data-toggle" => "modal", :href => log_out_path, :role => "button"}
%i.icon-user.icon-white
%strong
Log Out
- else
%a.btn-small{"data-toggle" => "modal", :href => "#LoginBox", :role => "button"}
%i.icon-user.icon-white
%strong
Login
This is what I get as error:
undefined local variable or method `current_user' for #<#<Class:0x007ff0a0544668>:0x007ff0a05414b8>
I really don't get what the problem is. Please help !
You have written your code in application controller instead of application helper
That is the reason why your method is not getting called
if you want to check if current user is logged in or not
you may just use before filter in application controller and call the method
whenever you dont need to check the method add skip before filter in that place

Devise: How to customize the registrations controller destroy method

I have my user and profiles in separate models. When a user is deleted the linked profile remains, which is the desired result. what I would like to do is flag the profile record as deleted.
I have added a deleted column(boolean) to my profile table, but can't figure out how I can add the set to true set to the devise destroy method?
app\controller\registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
def destroy
delete_profile(params)
end
private
def delete_profile(params)
profile = Profile.find(params[:id])
profile.deleted = true
end
end
but I can figure out how to get around this error
Couldn't find Profile without an ID
how can I pass in the correct params from the delete user in my views?
Devise doesn't use a params[:id] to destroy the current user (so it isn't provided through the route), but instead uses the current_user.
Here are the relevant parts of the controller:
class Devise::RegistrationsController < DeviseController
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy]
def destroy
resource.destroy
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
set_flash_message :notice, :destroyed if is_navigational_format?
respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
end
protected
def authenticate_scope!
send(:"authenticate_#{resource_name}!", :force => true)
self.resource = send(:"current_#{resource_name}")
end
end
So your alternative would be to do something like
class RegistrationsController < Devise::RegistrationsController
def destroy
current_user.deleted = true
current_user.save
#some more stuff
end
end

Rails 3 recursive polymorphic comments model, how to do redirect to top-most parent

I'm still earning my stripes in Rails and have ran into a problem I can use some help on. I'm building an app that has various models (stories, photos, artwork, etc.) that a user can comment on, as well as the comments themselves. I have 98-99% of the functionality working but am stuck on getting the redirect to redirect to the top-most parent (a story, photo, etc.) after the comment has been created.
My comment model look like this:
# /app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
has_many :comments, :as => :commentable
end
...I have several models that a user can comment on, for example a story model:
# /app/models/story.rb
class Story < ActiveRecord::Base
has_many :comments, :as => :commentable
end
My comments controller looks like this at this point:
# /app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def index
#commentable = find_commentable
#comments = #commentable.comments
end
def new
#commentable = find_commentable
end
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment])
if #comment.save
redirect_to :back
else
render :action => 'new'
end
end
protected
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
end
...And of course my routes look like this:
# /config/routes.rb
resources :comments do
resources :comments
end
resources :stories do
resources :comments
end
The particular line I need to change is the redirect_to :back line (everything else, the polymorphism, the recursion of comments, etc. works fine). The current code works as intended when a user is commenting on a story but it's not ideal when a user is commenting on a comment because the form for that functionality is not on the story "show" page (perhaps it needs to be?).
What I have tried to do (and what I suspect the solution might be) is a method that finds the parent object and recurses when that object is a comment. My previous attempts at doing this has not been clean at all and I have yet to get a working prototype working.
I used this railscasts episode to base the majority of my code but the redirect_to :id => nil doesn't work for me as the create comment method is somehow called and it results in a NilClass error when it attempts to build comments (perhaps something is wrong with my routing as I don't see how the index action would call create?).
So Rails experts, what am I doing wrong? What do I need to do here to get this working? I feel like I'm 99% there but that last 1% is driving me crazy.
Thanks in advance...
OK i had to read this a couple times...
#comment.commentable
would return an instance of Story or whatever object that did the comment.
Solved this...It's probably not the cleanest but it works:
I first added a method in comments controller...
def get_master
#parent = #comment.commentable
if #parent.respond_to?('commentable_type')
#comment = #parent
get_master
else
return #parent
end
end
Then I changed my redirect_to to call this method in the create controller.
The key was understanding that #object.respond_to? was what I needed to do check if a method is defined.
Here's a full example of how it works: http://t.co/N6WIGzuW

Posting with Nested Resources

I have nested my resources (see below) and when I try to create a new entity, I get the following error. Does anyone know why I'm getting this error and how to solve it?
undefined method `applications' for nil:NilClass
resources careers do
resources applications
end
Within the 'Applications' controller I have:
before_filter [[:authenticate, :except => :new], :load_career]
def create
# The following line is where the error originates
#application = #career.applications.new(params[:application])
respond_to do |format|
...
end
end
private
def load_career
#career = Career.find(params[:career_id])
end
The Career and Application models have has_many :applications and belongs_to :career respectively.
And the '*_create_applications' migration has a career_id field.
I have never seen before_filters defined that way. I just tried it in Rails 3 and it doesn't seem to do anything. I would give each callback it's own before_filter call:
before_filter :authenticate, :except => :new
before_filter :load_career

Call back to Application Controller error - NameError (undefined local variable or method

I'm upgrading an application from Rails 2 to 3. I use a Rights and Role approach for authentication that worked fine under Rails 2. In my Application Controller (application.rb) I have:
class ApplicationController < ActionController::Base
def check_authentication
unless session[:user]
session[:intended_resource] = request.request_uri
session[:intended_action] = action_name
session[:intended_controller] = controller_name
redirect_to :controller => "sessions", :action => "new"
return false
end
end
def check_authorization
user = User.find(session[:user])
unless user.roles.detect{|role|
role.rights.detect{|right|
right.action == action_name && right.controller == self.class.controller_path
}
}
flash[:notice] = "You are not authorized to view the page you requested"
request.env["HTTP_REFERER"] ? (redirect_to :back) : (redirect_to :controller => "sessions", :action => "new")
return false
end
end
end
In my other controllers I've included a before filter.
before_filter :check_authentication,:check_authorization
I'm getting the following error message, for example, when I go to my Dashboard Controller.
NameError (undefined local variable or method `check_authentication' for DashboardController:0x0000010291a0c0):
Is there something else I need to change or add to make this work in Rails 3?
Thanks,
Aaron
Make sure that your DashboardController is inheriting from ApplicationController i.e. DashboardController < ApplicationController.
Problem solved. Somehow during my upgrade I had a file named application.rb and application_controller.rb in my controllers folder. Both were defined as ApplicationController < ActionController::Base. The code for my "real" Application Controller was sitting in application.rb and not in application_controller.rb, which was empty. A simple copy-n-paste and things were fine. I don't know how that happened. Running the rails_upgrade plugin didn't go as smoothly as planned.