Posting with Nested Resources - ruby-on-rails-3

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

Related

undefined method `before_action' for ActionMailer

Trying to attach file to mail via before_action filter:
class UserMailer < ActionMailer::Base
before_action :add_logo_attachment
layout 'mail'
default from: "\"Admin\" <admin#site.com>",
to: Proc.new {Admin.pluck(:email)}
def send_mail
mail(subject: 'Hello, admin!')
end
.
.
private
def add_logo_attachment
attachments.inline['logo.png'] = File.read(Rails.root.join('app/assets/images/logo.png'))
end
end
And I get this error: undefined method `before_action' for UserMailer:Class
There is the same example in Rails guides and I can't understand what's the difference between my code and the code in guides.
There's no callbacks for ActionMaler::Base in Rails 3
Check the beginning of your controller. Had a similar error where this...
before_action :set_org, only: [:show, :edit, :update, :destroy]
got moved to above this accidently...
class OrgsController < ApplicationController
Move it back inside the class.
Try to
include AbstractController::Callbacks
in your mailer class and use before_filter
See this topic

uninitialized constant ProfilesController

I have an error "uninitialized constant ProfilesController" on my Profiles controller. This is the profiles_controller.rb:
class ProfilesController < ApplicationController
def new
#profile = Profile.new
end
def create
#profile = Profile.new(params[:profile])
if #profile.save
redirect_to profile_path, notice: I18n.t('.profile.created')
else
render action: "new"
end
end
end
This is the routes.rb:
resources :profiles, only: [:new, :create]
And this the output of rake routes:
profiles POST /profiles(.:format) profiles#create
new_profile GET /profiles/new(.:format) profiles#new
When I click a link for "new_profile_path" I get the error, but to me everything seems OK? The controller name is plural,the routes are OK?
You most likely spelled your controller file wrong. Confirm that file is truly: `/app/controllers/profiles_controller.rb'
Really strange, I created a Books controller with a generator, renamed everything to Profiles and then it works as normal. As far as I can see the routes are identical. Strange....
I had the same problem when i checked the name of the controller was 'profile_controller.rb'(i had created it manually though). but inside the definition it was "ProfilesController".
class ProfilesController < ApplicationController
def index
end
def new
#profile = Profile.new
end
def create
end
end
So if your controller name is correct and you have added the route("resources :profiles") then it will work as expected

How to invoke a rails sweeper in this scenario?

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

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

NoMethodError - undefined method

I'm having problems displaying data from a separate controller. I have a number of users, each with many pages. I've followed this tutorial with a few minor adjustments.
The error that keeps appearing is:
NoMethodError in SitesController#show
undefined method `page' for #<ActionDispatch::Request:0x00000102452d30>
My routes.rb is as follows:
devise_for :users
resources :users, :only => [:index, :show] do
resources :pages, :shallow => true
end
match '/' => 'sites#show', :constraints => { :subdomain => /.+/ }
root :to => "home#index"
And I have a sites controller:
class SitesController < ApplicationController
def show
#site = Site.find_by_name!(request.page)
end
end
I've also tried:
def show
#site = Site.find_by_name!(params[:site])
end
Which gives a different error.
Am totally stuck trying to figure this out!
Looking forward to your assistance.
Bob
The problem is here: request.page
The request object is of the class ActionDispatch::Request, which does not have a page method.
To track down errors like this, you can try either looking at the docs or messing around in the debugger.
Try running your controller with --debugger enabled.
If you are running Ruby 1.8, install the ruby-debug gem.
If you are running Ruby 1.9, install the ruby-debug19 gem.
Add a debugger call here:
class SitesController < ApplicationController
def show
debugger
#site = Site.find_by_name!(request.page)
end
end
Run your server with the --debugger option.
See what p request.page does. I bet it will have an "undefined method" error, just you see when you try to view that controller action.
If you do a p request.class you can find out what class the object is, and then look up the docs to see how to use it.