Messaging in Rails 3 - ruby-on-rails

I've been setting up a user to user messaging system using this rails tutorial http://www.novawave.net/public/rails_messaging_tutorial.html
I know its pretty old but I haven't really had a problem tweaking it to work now. My only problem is that the inbox is not displaying and the error that appears is "Couldn't find Folder without an ID" I'm not sure what I should do. My code is pretty much the same, besides some tweaks, with the code in that link until right before reply. Thats where I stopped.
My Folder Model looks like
class Folder < ActiveRecord::Base
acts_as_tree
belongs_to :user
has_many :messages, :class_name => "MessageCopy"
end
My Mailbox controller looks like
class MailboxController < ApplicationController
def index
redirect_to new_session_path and return unless signed_in?
#folder = current_user.inbox
show
render :action => "show"
end
def show
#folder ||= current_user.folders.find(params[:id])
#messages = #folder.messages.paginate :per_page => 10, :page => params[:page], :include => :message, :order => "messages.created_at DESC"
end
end
If any other code needs to be included let me know.

It looks like when you call show from within the index action that #folder is not set and so it calls current_user.folders.find(params[:id]) but because of the way you have called it params[:id] is nil.
This would cause an exception.
I suggest instead to change your index action to look like this:
def index
redirect_to new_session_path and return unless signed_in?
#folder = current_user.inbox
redirect_to :action => :show, :id => #folder.id
end
Instead of rendering the show action from within the index action, just redirect to the show method with the correct id parameter.

Related

How to use the same method in 2 controllers?

I have a Rails 2 app with an API. I versioned and optimised the controllers but there are duplicate methods. The goal is to have the common information in only one place. So I explored the following options:
redirect from routes the non-API controller, but each controller needs it's specific hooks
module inclusion. This is my favorite but there are like quite a lot of errors thrown out and very limited time to fix things up.
eval. Put all the code in one file and eval it in both places. Done this, it works but I am not pleased by this workaround.
What would be the best to go about this?
Might be some typos lurking in here but:
class GenericController < ApplicationController
def index
#objects = params[:controller].singularize.camelcase.constantize.all()
end
def show
#object = params[:controller].singularize.camelcase.constantize.find(params[:id])
end
def new
#object = params[:controller].singularize.camelcase.constantize.new
end
def edit
#object = params[:controller].singularize.camelcase.constantize.find(params[:id])
end
def create
model = params[:controller].singularize.downcase
#object = params[:controller].singularize.camelcase.constantize.new(params[model])
if #object.save
redirect_to '/'+params[:controller]
else
render :action => 'new'
end
end
def update
model = params[:controller].singularize.downcase
#object = params[:controller].singularize.camelcase.constantize.find(params[:id])
if #object.update_attributes(params[model])
redirect_to :controller => params[:controller], :action => 'index'
else
render :action => 'edit'
end
end
def destroy
if #object = params[:controller].singularize.camelcase.constantize.find(params[:id])
#object.destroy
end
redirect_to :controller => params[:controller], :action => 'index'
end
end
Specific controllers can override those implementations as needed, but:
class ProjectsController < GenericController
# done!
end
class ScenariosController < GenericController
# done!
end

Sweepers not working unless manually invoked, what is going on?

I have the following setup: A model called Categories. These categories are managed using ActiveAdmin. I want to cache the categories using page caching.
This is how I've setup my app/admin/categories.rb
ActiveAdmin.register Category do
controller do
cache_sweeper :category_sweeper
end
end
This is my sweeper:
class CategorySweeper < ActionController::Caching::Sweeper
observe Category
def after_save(category)
expire_cache(category)
end
def after_destroy(category)
expire_cache(category)
end
def expire_cache(category)
expire_page :controller => 'categories', :action => 'index', :format => 'json'
end
end
And here is my controller:
class CategoriesController < ApplicationController
caches_page :index
cache_sweeper :category_sweeper
respond_to :json
def index
#categories = Category.all
respond_with(#categories)
end
def show
CategorySweeper.instance.expire_cache(#category)
respond_with('manually sweeped!')
end
end
So the idea is when there is a change in the active admin the sweeper should get invoked. I set up debug.log and turns out it's working. But for some reason the cache does not expire!
But, if I do the show action (i.e. go to /categories/1.json then my manual sweeper kicks in and it works fine). So why is the sweeper only working when I invoke it and not when there is a change in the admin?
Thanks in advance,
-David
Your ActiveAdmin controller located in different namespace, see this SO question.
Shortly:
Add slash into cache expiration url code:
def expire_cache(category)
expire_page :controller => '/categories', :action => 'index', :format => 'json'
end

Pass Error Messages When Using form_tag?

How can you pass an error messages coming from a model --> controller to view?
= form_tag :controller => "article", :action => "create" do
/ how to retrieve error messages here?
%p
= label_tag :article, "Article"
= text_field_tag :article
= submit_tag "Submit Article"
I have this model:
class Article < ActiveRecord::Base
attr_accessible :article
validates :article, :presence => true
end
In my controller:
def create
#article = Article.new(params[:article])
if ! #article.save
# how to set errors messages?
end
end
I'm using Rails 3.0.9
The errors messages are stored in your model. You can access through the errors methods, like you can see in http://api.rubyonrails.org/classes/ActiveModel/Errors.html.
An easy way to expose the error message is including the follow line in your view:
%span= #article.errors[:article].first
But, I belive you have to change your controller to be like that:
def new
#article = Artile.new
end
def create
#article = Artile.new params[:article]
if !#article.save
render :action => :new
end
end
In the new action you don't need to try save the article, because the creation action already do that job. The new action exists, (basically) to call the new view and to provide support for validations messages.
The newmethod shouldn't save anything. create method should.
def create
#article = Article.new(params[:article])
if ! #article.save
redirect_to root_path, :error => "ops! something went wrong.."
end
end

Destroy method has stopped working

I have two models: page and authors, when i choose the destroy method it just returns the show page. The models are linked by telling the model that the author has_many :pages and the page belongs to many :author.
this is the code for my page controller:
class PagesController < ApplicationController
def index
#pages = Page.find(:all, :order => 'created_at DESC')
end
def show
#page = Page.find(params[:id])
end
def new
#page = Page.new
end
def edit
#page = Page.find(params[:id])
end
def create
#page = Page.new(params[:page])
if #page.save
redirect_to(#page, :notice => 'Page was successfully created.')
else
render :action => "new"
end
end
def update
#page = Page.find(params[:id])
if #page.update_attributes(params[:page])
redirect_to(#page, :notice => 'Page was successfully updated.')
else
render :action => "edit"
end
end
def destroy
#page = Page.find(params[:id])
#page.destroy
end
def author
#pages = #author.pages
end
end
Where should I be looking to solve this problem, when i hit destroy it semds me to the page to destroy but nothing more, no :notice appears it just seems to not have the destroy method.
Thank you
I don't know what you mean by
choose the destroy method
But I'm assuming you're just accessing the pages/:id url in your browser? This is the show action as you said.
In order to actually destroy your model (ie. access the destroy action in the controller) you need to send a DELETE to /pages/:id.
This is usually accomplished using something like:
<%= link_to 'Destroy', #page, :confirm => 'Are you sure?', :method => :delete %>
Note the :method => :delete. This will actually send a DELETE to the controller (assuming you've got your rails.js included to take care of this) and thus map to the destroy action instead of the show action
Have you disabled JavaScript in your browser? :)
A couple of things to look at:
It's not clear what type of HTTP request you are sending to your application. The fact that the show action seems to be triggered makes me think that your request is an HTTP GET method. If you want the destroy action to be invoked, make sure it is an HTTP DELETE method.
Have you checked your database to see if the ActiveRecord had been destroyed? It could be that you are not seeing any notice simply because you are not setting a flash notice message. For example:
def destroy
#page = Page.find(params[:id])
flash[:notice] = "Page successfully removed"
#page.destroy
# You may also want to have a redirect here, e.g. redirect_to #pages
end
On a separate note, not sure what you are trying to achieve with the author method in your controller but it doesn't look right. It's not restful and it seems to return an array of pages rather than an author.

Ordering by Sum from a separate controller part 2

Ok, so I had this working just fine before making a few controller additions and the relocation of some code. I feel like I am missing something really simple here but have spent hours trying to figure out what is going on. Here is the situation.
class Question < ActiveRecord::Base
has_many :sites
end
and
class Sites < ActiveRecord::Base
belongs_to :questions
end
I am trying to display my Sites in order of the sum of the 'like' column in the Sites Table. From my previous StackOverflow question I had this working when the partial was being called in the /views/sites/index.html.erb file. I then moved the partial to being called in the /views/questions/show.html.erb file and it successfully displays the Sites but fails to order them as it did when being called from the Sites view.
I am calling the partial from the /views/questions/show.html.erb file as follows:
<%= render :partial => #question.sites %>
and here is the SitesController#index code
class SitesController < ApplicationController
def index
#sites = #question.sites.all(:select => "sites.*, SUM(likes.like) as like_total",
:joins => "LEFT JOIN likes AS likes ON likes.site_id = sites.id",
:group => "sites.id",
:order => "like_total DESC")
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #sites }
end
end
I think it should be
#sites = #question.sites.all(:select => "sites.*, SUM(likes.like) as like_total",
:joins => "LEFT JOIN likes AS likes ON likes.site_id = sites.id",
:group => "sites.id",
:order => "SUM(likes.like) DESC")
Ah...turns out that I had move the #sites controller code from the SitesController to the QuestionsController Show action. I then had to change my partial in the /views/questions/show.html.erb page from
<%= render :partial => #question.sites %>
to
<%= render :partial => #sites %>

Resources