Undefined method `user' in Posts>Show view - ruby-on-rails

Getting this error in posts>show when I try to load up a form.
The form is for users to send messages to each other. Grateful for any feedback!
Thanks.
NoMethodError in Posts#show
Showing /Users/fkhalid2008/loand/app/views/posts/show.html.erb where line #1 raised:
undefined method `user' for #<Post:0x12e2ae930>
Extracted source (around line #1):
1: <%= form_remote_tag (:update => 'message', :url => {:controller => 'main', :action => 'send_message', :user_id => #post.user.id}) do %>
2: <br>
3: <br />
4: <br />
POSTS>SHOW VIEW
<%= form_remote_tag (:update => 'message', :url => {:controller => 'main', :action => 'send_message', :user_id => #post.user.id}) do %>
<br>
<br />
<br />
<div class="field">
Hello! My name is <%= f.text_field :subject %> and I'm contacting you in response to your ad. I'm interested in learning more so get in touch! Here's my contact details: <%= f.text_field :body %>.
</div>
<button type="submit" class="btn span6 large">Submit</button>
<% end %>
POSTS CONTROLLER
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #post }
end
end
def edit
#post = Post.find(params[:id])
end
def create
#post = Post.new(params[:post])
respond_to do |format|
if verify_recaptcha && #post.save
format.html { redirect_to :action=> "index"}
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
MAIN CONTROLLER
class MainController < ApplicationController
def send_message
message = Message.new
message.subject = params[:subject]
message.body = params[:message]
message.sender = User.find session[:user]
message.recipient = User.find params[:user_id]
if message.save
ContactMailer.deliver_message_email message.recipient.email, message.id, request.host
return redirect_to "/posts"
else
render :text => "Hmm. Something seems to be wrong...let me look into it"
end
CONTACT MAILER
class ContactMailer < ActionMailer::Base
def message_email (recipient, id, host)
recipients [ recipient ]
subject "Weddoo: You have received a new message"
from "admin#weddoo.com"
bcc ["admin#weddoo.com"]
content_type "text/html"
body :message_id => id, :host => host
sent_on Time.now
end
end
end
ROUTES.RB
Mysalary::Application.routes.draw do
resources :users do
resources :messages
end
resources :profiles
resources :pages
resources :posts
get "pages/home"
get "pages/about"
get "pages/legal"
get "pages/feedback"
root :to => 'posts#new'
end
POST MODEL
class Post < ActiveRecord::Base
attr_accessible :title, :job, :location, :salary
validates :title, :job, :location, :salary, :presence => true
validates :salary, :numericality => {:greater_than_or_equal_to => 1}
default_scope :order => 'posts.created_at DESC'
end

The error is saying there is no method user on the Post model. It points you directly to the first line.
<%= form_remote_tag (:update => 'message', :url => {:controller => 'main', :action => 'send_message', :user_id => #post.user.id}) do %>
so I'd say
#post.user.id is your problem statement, that model doesn't have a method user but it's hard to know for sure without seeing the Post model.

I think you have missed to add relationship.
class Post < ActiveRecord::Base
belongs_to :user
end

Related

ActionController::ParameterMissing (param is missing or the value is empty: film):

So, I'm getting the following error when trying to visit the films page on my app:
ActionController::ParameterMissing (param is missing or the value is empty: film):
2014-07-24T22:04:44.622356+00:00 app[web.1]: app/controllers/saas_admin/films_controller.rb:54:in `permitted_params'
See my films controller code below
films_controller.rb
class SaasAdmin::FilmsController < SaasAdminController
inherit_resources
belongs_to :studio, :finder => :find_by_id!, :param => :studio_id, :class_name => Studio
before_filter :set_sort_fields, :only => :edit
before_filter :build_collections, :only => [:new, :create, :edit, :update]
def create
create! { parent_path(parent.id) } # Redirect to studio in case studio_id is changed
end
def update
#film = Film.find_by_permalink(params[:id])
respond_to do |format|
if #film.update(permitted_params)
format.html { redirect_to saas_admin_studio_path(#film.studio), notice: 'Film was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #film.errors, status: :unprocessable_entity }
end
end
end
def index
redirect_to parent_path(parent.id)
end
def show
#clips = resource.clips.paginate(:page => params[:page], :per_page => 30, :order => 'clips.position')
end
protected
def resource
# #film ||= end_of_association_chain.find_by_permalink!(params[:id])
#film ||= end_of_association_chain.find_by_permalink!(params[:id])
end
def collection
#films ||= end_of_association_chain.paginate(:page => params[:page], :per_page => 30, :order => 'films.created_at')
end
def set_sort_fields
resource.sort_name = '' if resource.name == resource.sort_name
end
def build_collections
#studios ||= Studio.find(:all)
end
def permitted_params
params.require(:film).permit(:name, :sort_name, :description, :short_description, :meta_data,
:poster, :amazon_link, :active, :trackable, :country_ids => [])
end
end
What might this be? I've been trying to figure it out for a bit but perhaps a fresh set of eyes will find it's something rather simple.
Cheers!
Edit
Here's the view code for films/new.html.erb
<h1><%= #page_title = "New #{resource_class}" %></h1>
<%= form_for resource, :url => collection_path, :html => { :multipart => true } do |f| -%>
<%= render :partial => "form", :locals => { :f => f } %>
<% end -%>
<% content_for :sidebar do %>
<%= render :partial => "saas_admin/shared/sidebar" %>
<% end %>
and films/edit.html.erb
<h1><%= #page_title = "Edit #{resource_class}" %></h1>
<%= form_for resource, :url => saas_admin_studio_film_path(parent, resource), :html => { :multipart => true } do |f| -%>
<%= render :partial => "form", :locals => { :f => f } %>
<% end -%>
<% content_for :sidebar do %>
<%= render :partial => "saas_admin/shared/sidebar" %>
<% end %>
Edit 2
For reference here is how the permitted params was defined when it was working:
def permitted_params
{:film => params.fetch(:film, {}).permit(
:name, :sort_name, :description, :short_description, :meta_data,
:poster, :amazon_link, :active, :trackable)}
end
I have got this problem too when I use Angular JS form to send data to backend Rails 4. When I did not fill anything in angular js form, the error will show ActionController::ParameterMissing (param is missing or the value is empty:.
I fix it by adding params.fetch(:film, {}) the strong parameter into:
params.fetch(:film, {}).permit(:name, :sort_name, :description, :short_description, :meta_data,
:poster, :amazon_link, :active, :trackable, :country_ids => [])
I refer to code example to avoid ActionController::ParameterMissing (param is missing or the value is empty: film)
I hope this will help you.
Why not use so:
def creation_params
params.permit(:film)
end
It working for me! ;)
This is happening because you have specified to require 'film' in your parameters through strong_params (specified above in your permitted_params code).
Whatever the view side is doing (whether its a link or a form/etc.), its not passing its parameters nested under 'film'
eg.) if you were to raise params.inspect in the controller action, you would see that there is no node for "film".
Most likely what is wrong is that the form code you have on the view side is not set to nest these parameters properly, are you using a form_tag for example?

First argument in form cannot contain nil or be empty (acts_as_commentable error)

So I'm trying to get the acts_as_commentable_with_threading gem working in my app. I would like to allow the users to comment on specific events (events/show.html). I don't think I've set it up properly as I'm getting the below error.
error:
Showing /Users/user/Sites/new_work/app/views/events/show.html.erb where line #36 raised:
First argument in form cannot contain nil or be empty
</div>
<div class="name"></div>
<div id="comments">
<%= form_for #comment do |f| %> <---- it's referring to this line
<div><%= f.hidden_field :event_id, value: #event.id %></div>
<div><%= f.text_field :body, row: 20, placeholder: "Leave a comment" %></div>
<%= f.submit "Post Comment" %>
comments_controller.rb
class CommentsController < ApplicationController
before_filter :load_commentable
def index
#comments = #commentable.current_user.comments
end
def new
#comment = #commentable.current_user.comments.new
end
def create
#comment = #commentable.current_user.comments.new(params[:comment])
if #comment.save
redirect_to #commentable, notice: "Comment created."
else
render :new
end
end
private
def load_commentable
resource, id = request.path.split('/')[1, 2]
#commentable = resource.singularize.classify.constantize.find(id)
end
end
comment.rb snippit only
class Comment < ActiveRecord::Base
attr_accessible :title, :body, :subject
acts_as_nested_set :scope => [:commentable_id, :commentable_type]
validates :body, :presence => true
validates :user, :presence => true
# NOTE: install the acts_as_votable plugin if you
# want user to vote on the quality of comments.
#acts_as_votable
belongs_to :commentable, :polymorphic => true
# NOTE: Comments belong to a user
belongs_to :user
event.rb
class Event < ActiveRecord::Base
attr_accessible :title, :description, :location, :date, :time, :event_date
acts_as_commentable
has_many :comments, as: :commentable
belongs_to :user
after_create :update_event_date
def update_event_date
date = self.date.to_s
time = self.time
hour = Time.parse(time).strftime("%H:%M:%S").to_s
event_date = (date + ' ' + hour).to_time
self.update_attributes(event_date: event_date)
end
end
comments/form.html.erb
<%= form_for [#commentable, #comment] do |f| %>
<% if #comment.errors.any? %>
<div class="error_messages">
<h3>Please correct the following errors.</h3>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
</ul>
</div>
<% end %>
<div class="field">
<%= f.text_field :body, rows: 10, placeholder: "Leave a comment" %>
</div>
<div class="actions">
<%= f.submit "Post comment", class: "btn" %>
</div>
<% end %>
events_controller.rb
class EventsController < ApplicationController
before_filter :authenticate_user!
def index
#user = current_user
#events = Event.all
end
def new
#event = Event.new
end
# def create
# #event = Event.new(params[:event])
# if #event.save
# redirect_to :action => 'index'
# else
# #events = Event.find(:all)
# render :action => 'new'
# end
# end
def create
#event = current_user.events.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to :back, notice: 'Event was successfully created.' }
format.json { render action: 'show', status: :created, location: #event }
format.js
else
format.html { render action: 'new' }
format.json { render json: #event.errors, status: :unprocessable_entity }
format.js
end
end
end
def show
#event = Event.find(params[:id])
end
def edit
#event = Event.find(params[:id])
end
def update
#event = Event.find(params[:id])
if #event.update_attributes(params[:event])
flash[:success] = "Event updated."
redirect_to #event
else
render 'edit'
end
end
def destroy
#event = Event.find(params[:id])
#event.destroy
respond_to do |format|
format.html {redirect_to :back}
format.js
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = Event.find(params[:id])
end
routes.rb
New_app::Application.routes.draw do
# get 'auth/:provider/callback', to: 'sessions#create'
# get 'auth/failure', to: redirect('/')
root to: "home#landing"
devise_for :users, :controllers => {:registrations => "users/registrations",
:sessions => "users/sessions",
:passwords => "users/passwords",
:omniauth_callbacks => "users/omniauth_callbacks"
}
get "welcome", to: "home#welcome", as: 'welcome'
devise_scope :user do
# get "edit/edit_account", :to => "devise/registrations#edit_account", :as => "account_registration"
get 'edit/edit_account' => 'users/registrations#account_registration', as: :edit_account
end
# patch '/users/:id', to: 'users#update', as: 'user'
get 'profile/:id' => "users#show", as: :profile
get 'disconnect' => 'users#disconnect'
resources :users do
resources :questions
end
resources :photos
resources :events do
resources :comments
end
post "/events/add_new_comment" => "events#add_new_comment", :as => "add_new_comment_to_events", :via => [:event]
resources :questions
end
rake routes for comments
event_comments GET /events/:event_id/comments(.:format) comments#index
POST /events/:event_id/comments(.:format) comments#create
new_event_comment GET /events/:event_id/comments/new(.:format) comments#new
edit_event_comment GET /events/:event_id/comments/:id/edit(.:format) comments#edit
event_comment GET /events/:event_id/comments/:id(.:format) comments#show
PATCH /events/:event_id/comments/:id(.:format) comments#update
PUT /events/:event_id/comments/:id(.:format) comments#update
DELETE /events/:event_id/comments/:id(.:format) comments#destroy
Is #comment defined in the "show" action in your Events controller? Can you post the Events controller code as well?
One thing to double check is to ensure that the action that renders the view for show.html.erb has the #comment variable defined. You seem to be getting the message because the #comment variable in
<%= form_for #comment do |f| %>
Is currently nil when you render the view.
In the "show" action for the events controller, try setting the #comment variable by adding:
#comment = #event.comments.new
Edit 2: Make sure you've setup your routes.rb file to handle comments on events, so assuming youre using RESTful routes, something like this below in your routes.rb. If you could post the routes file that would be helpful too.
resources :events do
resources :comments
end
The error is on app/views/events/show.html.erb which means that your Events controller's show action is missing the #comment variable
def show
#event = Event.find(params[:id])
#comment = ....what ever you need to pull in the comments....
end

NoMethodError when using paperclip for nested resource

Hi I am pretty new to Rails, and I managed to get a few classes working together until I tried to use Paperclip.
Everything works fine until I try to upload a picture. I get this error:
undefined method `business_locations_path' for #<#:0x4eecc88>
These are the 2 models:
class Business < ActiveRecord::Base
attr_accessible :bizName, :contact, :email, :ownerName, :signupDate, :website
has_many :businessLocations
end
class BusinessLocation < ActiveRecord::Base
belongs_to :business
attr_accessible :address1, :address2, :contact, :description, :email, :latitude, :longitude, :postal, :price, :mainpic
has_attached_file :mainpic, :styles => {:large => "640x640>", :medium => "320x320>", :thumb => "100x100>"}
end
To create a new location, the path would be something like:
http://localhost:3000/businesses/8/businessLocations/new
The form:
<%
if params[:action] == "new"
urlpath = business_businessLocations_path(#business)
else
if params[:action] == "edit"
urlpath = business_businessLocation_path(#business,#businessLocation)
end
end
%>
<%= form_for #businessLocation, :url=>urlpath, :html =>{ :multipart => true } do |f| %>
...
<div class="field">
<%= f.label :mainpic %><br />
<%= f.file_field :mainpic %>
</div>
The BusinessLocation Controller:
def create
respond_to do |format|
#business = Business.find(params[:business_id])
#businessLocation = #business.businessLocations.build(params[:business_location])
if #businessLocation.save
format.html { redirect_to(business_businessLocation_path(#business,#businessLocation),
:notice => 'Post was successfully created.') }
format.json { render :json => #businessLocation,
:status => :created, :location => #business }
else
format.html { render :action => "new" }
format.json { render :json => #businessLocation.errors,
:status => :unprocessable_entity }
end
end
end
There is no such path business_locations_path because BusinessLocation is nested in Business.
EDIT: here are my rake routes:
business_businessLocations GET /businesses/:business_id/businessLocations(.:format) businessLocations#index
POST /businesses/:business_id/businessLocations(.:format) businessLocations#create
new_business_businessLocation GET /businesses/:business_id/businessLocations/new(.:format) businessLocations#new
edit_business_businessLocation GET /businesses/:business_id/businessLocations/:id/edit(.:format) businessLocations#edit
business_businessLocation GET /businesses/:business_id/businessLocations/:id(.:format) businessLocations#show
PUT /businesses/:business_id/businessLocations/:id(.:format) businessLocations#update
DELETE /businesses/:business_id/businessLocations/:id(.:format) businessLocations#destroy
businesses GET /businesses(.:format)
businesses#index
POST /businesses(.:format)
businesses#create
new_business GET /businesses/new(.:format)
businesses#new
edit_business GET /businesses/:id/edit(.:format)
businesses#edit
business GET /businesses/:id(.:format)
businesses#show
PUT /businesses/:id(.:format)
businesses#update
DELETE /businesses/:id(.:format)
businesses#destroy
In your controller, you have the create action set to redirect to business_businessLocation_path. This is autogenerated by whatever you used to genereate your nested scaffold. Fixing this will probably fix all your problems.

Runtime error - called id for nil in Rails 3 project

I'm getting this error when I try to submit my form (/POSTS/SHOW):
RuntimeError in Posts#show
Showing /Users/fkhalid2008/loand/app/views/posts/show.html.erb where line #1 raised:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Extracted source (around line #1):
1: <%= form_remote_tag (:update => 'message', :url => {:controller => 'main', :action => 'send_message', :user_id => #post.user.id}) do %>
2: <br>
3: <br />
4: <br />
How do I fix this?
Relevant code is below:
/VIEWS/POSTS/SHOW
<%= form_remote_tag (:update => 'message', :url => {:controller => 'main', :action => 'send_message', :user_id => #post.user.id}) do %>
<br>
<br />
<br />
<div class="field">
Hello! My name is <%= f.text_field :subject %> and I'm contacting you in response to your ad. I'm interested in learning more so get in touch! Here's my contact details: <%= f.text_field :body %>.
Submit
<% end %>
POST MODEL
class Post < ActiveRecord::Base
belongs_to :user
attr_accessible :title, :job, :location, :salary
validates :title, :job, :location, :salary, :presence => true
validates :salary, :numericality => {:greater_than_or_equal_to => 1}
default_scope :order => 'posts.created_at DESC'
end
USER MODEL
class User < ActiveRecord::Base
has_many :posts
has_one :profile
has_private_messages
attr_accessible :email
validates_presence_of :email
validates_uniqueness_of :email, :message =>"Hmm, that email's already taken"
validates_format_of :email, :with => /^([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})$/i, :message => "Hi! Please use a valid email"
end
POSTS CONTROLLER
def show
#post = Post.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #post }
end
end
def new
#post = Post.new
#post.user = current_user
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #post }
end
end
def edit
#post = Post.find(params[:id])
end
def create
#post = Post.new(params[:post])
#post.user = current_user
respond_to do |format|
if verify_recaptcha && #post.save
format.html { redirect_to :action=> "index"}
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
def update
#post = Post.find(params[:id])
#post.user = current_user
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, :notice => 'Post was successfully updated.' }
format.json { head :ok }
else
format.html { render :action => "edit" }
format.json { render :json => #post.errors, :status => :unprocessable_entity }
end
end
end
APPLICATION CONTROLLER (this is where I am defining current_user)
class ApplicationController < ActionController::Base
protect_from_forgery
private
def current_user
#_current_user ||= session[:current_user_id] &&
User.find_by_id(session[:current_user_id])
end
end
MAIN CONTROLLER (send_message is defined here)
class MainController < ApplicationController
def send_message
message = Message.new
message.subject = params[:subject]
message.body = params[:message]
message.sender = User.find session[:user]
message.recipient = User.find params[:user_id]
if message.save
ContactMailer.deliver_message_email message.recipient.email, message.id, request.host
return redirect_to "/posts"
else
render :text => "Hmm. Something seems to be wrong...let me look into it"
end
end
You don't have a user assigned to the post record represented by the #post instance variable.
Presumably a user needs to be logged in to make a post?
Also presumably you have a current user defined somewhere?
Your controller actions that use this form need to assign the user to the post record
def new
#post = Post.new
#post.user = current_user # You will need to get the current user from somewhere
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #post }
end
end
UPDATE
To make sure that your current user is assigned you should add a check to ensure the user is logged in in the controller actions. This is normally done by adding a before filter to authorize the current user which will redirect back to the login page if the current use is logged out.
Have a look at this rails cast to explain logging in and out and redirecting on a before filter http://railscasts.com/episodes/250-authentication-from-scratch
There is a revised version of the cast here but you will need a subscription for that
http://railscasts.com/episodes/250-authentication-from-scratch-revised
well worth paying for IMO
End of update
You will need to / should also assign the current user in whatever actions update the post record - i.e. the create and update actions in EXACTLY the same way.
Also, because you have not got a user assigned to a post record then you need to handle this scenario in the form so that you don't get 500 errors
You can use the #post.user.blank? boolean check to help you with this
Something like
<% if #post.user.blank? %>
<h2>There is no user assigned to this post record! This should never happen ad you should never see this message, please contact support if etc... </h2>
<% else %>
<!-- Place all your current form code here -->
<% end %>
You are getting the error because #post.user is nil in :user_id => #post.user.id.
Make sure you define #post in your post controller's show action and that it has a valid user association.

Ruby on rails nested form model

I'm trying to use rails nested form_for helper, but I am getting the following error:
BlogPage(#49859550) expected, got Array(#31117360)
Here are my model objects:
class Blog < ActiveRecord::Base
# Table Configuration
set_table_name "blog"
# Model Configuration
belongs_to :item
has_many :blog_pages
accepts_nested_attributes_for :blog_pages, :allow_destroy => true
end
class BlogPage < ActiveRecord::Base
# Table Configuration
set_table_name "blog_page"
# Model Configuration
belongs_to :blog
end
Here is the form I generated (left out unnecessary HTML):
<% form_for :blog, :url => { :action => :create } do |blog_form| %>
<%= blog_form.text_field :title, :style => "width: 400px" %>
<% blog_form.fields_for :blog_pages do |page_fields| %>
<% #blog.blog_pages.each do |page| %>
<%= page_fields.text_area :content, :style => "width: 100%",
:cols => "10", :rows => "20" %>
<% end %>
<% end %>
<% end %>
Here are the parameters that are sent to the controller:
{"commit"=>"Save",
"blog"=>{"blog_pages"=>{"content"=>"This is the new blog entries contents."},
"title"=>"This is a new blog entry.",
"complete"=>"1"},
"authenticity_token"=>"T1Pr1g9e2AjEMyjtMjLi/ocrDLXzlw6meWoLW5LvFzc="}
Here is the BlogsController with the create action that gets executed:
class BlogsController < ApplicationController
def new
#blog = Blog.new # This is the line where the error gets thrown.
# Set up a page for the new blog so the view is displayed properly.
#blog.blog_pages[0] = BlogPage.new
#blog.blog_pages[0].page_number = 1
respond_to do |format|
format.html # Goes to the new.html.erb view.
format.xml { render :xml => #blog }
format.js { render :layout => false}
end
end
def create
#blog = Blog.new(params[:blog])
respond_to do |format|
if #blog.save
render :action => :show
else
flash[:notice] = "Error occurred while saving the blog entry."
render :action => :new
end
end
end
end
If anyone can help me with this I would greatly appreciate it. I'm still pretty new to ruby and the rails framework and couldn't solve the problem on my own by googling.
Thanks.
Have you seen this?
http://media.pragprog.com/titles/fr_arr/multiple_models_one_form.pdf
Change your form to this:
<% form_for :blog, :url => { :action => :create } do |blog_form| %>
<%= blog_form.text_field :title, :style => "width: 400px" %>
<% blog_form.fields_for :blog_pages do |page_fields| %>
<%= page_fields.text_area :content, :style => "width: 100%",
:cols => "10", :rows => "20" %>
<% end %>
<% end %>
If you use fields_for it iterates over blog_pages automaticaly. However I'm not sure if this caused errors.

Resources