How do I fix an unexpected nil object error? - ruby-on-rails

I have this error when I try to add a comment via AJAX:
ActionView::Template::Error (You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.to_key):
1: $("#<%= dom_id(#comment.comment_title) %>").parent().append('<%= escape_javascript(render(#comment)) %>');
2: $(".comment_form")[0].reset();
app/views/comments/create.js.erb:1:in `_app_views_comments_create_js_erb___503385093_2173588800_0'
app/controllers/comments_controller.rb:8:in `create'
The form to create the comment has an association option that should set the comment_title for the comment:
<%= simple_form_for([#video, #video.comments.new], :remote => true) do |f| %>
<%= f.association :comment_title, :collection => #video.comment_titles.map {|ct| [ct.title, comment_title_path(ct)] }, :label => "Comment Title:", :include_blank => false %>
<%= f.input :body, :label => false, :placeholder => "Post a comment." %>
<%= f.button :submit, :value => "Post" %>
<% end %>
Here's the create action in my comments controller:
def create
#comment = #video.comments.new(params[:comment].merge({:user_id => current_user.id}))
if #comment.save
respond_to do |format|
format.html { redirect_to :back }
format.js
end
else
respond_to do |format|
format.html { redirect_to :back, :alert => "Unable to add comment." }
format.js { render 'fail_create.js.erb' }
end
end
end
Why am I getting this error? How can I resolve this?

You can't use this:
dom_id(#comment.comment_title)
You can use this
dom_id(#comment)
Because you should pass a record, but not a string
http://apidock.com/rails/ActionController/RecordIdentifier/dom_id
UPD
as far as comment_title is a has_one association (but not an attribute, as I thought), so the problem is it isn't created so it passes nil into dom_id method

Related

Cant get validation erros to work in Rails

I cannot get validation errors to work. I have a create product page which has two form_for's One for products and one for photos. When a product doesnt upload you get sent to redirect_to new_product_path
product controller
def new
#product = Product.new
#photo = Photo.new
end
def create
check_for_image = Photo.where(:product_id => nil, :user_id => current_user)
if check_for_images == []
redirect_to products_new_path, :notice => "Add an image then press start before submit"
else
#product = current_user.products.create(params[:product])
if #product.save
Photo.where(:product_id => nil, :user_id => current_user).update_all(:product_id => #product.id)
render "show", notice: "Product created!"
else
redirect_to new_product_path #, :flash => { :error => "Test!" }
# render "new"
end
end
end
I tried to do render "new" instead of redirect_to but i get undefined method `model_name' for NilClass:Class with the error pointing to the photo form for
haml create product page
= form_for #photo, :html => { :multipart => true, :id => "fd" } do |f|
%span Add files...
= f.file_field :image
= form_for #product,:url => products_path, :html => { id: "fd", multipart: true } do |f|
- if #product.errors.any?
.error_messages
%h2 Form is invalid
%ul
- for message in #product.errors.full_messages
%li
= message
%p
= f.text_field :name, placeholder: "Name"
%p
= f.text_field :price, class: "auto", data: { a_sign: "$ " }, placeholder: "Price"
%p
= f.text_field :description, placeholder: "Description"
%p.button.start
= f.submit
product model
validates :user_id, presence: true
validates :name, presence: true, length: { minimum: 5 }
validates :price, presence: true, numericality: { greater_than_or_equal_to: 3.00 }
I think first you need to know difference between redirect_to & render
redirect_to :action => 'new' #It will call the method 'new' and then it will call
#respective file. In this case it is `new.haml`
render :action => 'new' #It will call `new.haml` directly without calling method 'new'
So when you used render :action => 'new' it will not get #photo and hence it is giving error undefined methodmodel_name' for NilClass:Classeither you have to handlenil` on view or
It will fixed when you
Change
redirect_to new_product_path
To
#photo = Photo.new
render :action => 'new'
render will render a particular view using the instance variables available in the action. For example if a render was used for the new action, when a user goes to /new, the new action in the controller is called, instance variables are created and then passed to the new view. Rails creates the html for that view and returns it back to the user’s browser. This is what you would consider a normal page load.
redirect_to will send a redirect to the user’s browser telling it to re-request a new URL. Then the browser will send a new request to that URL and it will go through the action for that URL, oblivious to the fact that it was redirected to. None of the variables created in the action that caused the redirect will be available to the redirected view. This is what happens when you click on ‘Create’ in a form and the object is created and you’re redirected to the edit view for that object.
so you had no validation errors because each time you did a redirect a new instance was created with no errors.
2 lines you have to change:
render "show", notice: "Product created!"
and
redirect_to new_product_path
not sure about this:
redirect_to products_new_path, :notice => "Add an image then press start before submit" it's not clear what it does and how your app should behave.
your controller:
def new
#product = Product.new
#photo = Photo.new
end
def create
check_for_image = Photo.where(:product_id => nil, :user_id => current_user)
if check_for_images == []
redirect_to products_new_path, :notice => "Add an image then press start before submit"
else
#product = current_user.products.create(params[:product])
if #product.save
Photo.where(:product_id => nil, :user_id => current_user).update_all(:product_id => #product.id)
redirect_to #product, notice: "Product created!"
else
render action: "new"
end
end
end
more:
Are redirect_to and render exchangeable?
http://blog.markusproject.org/?p=3313

Error handeling w/ form_for in associated resource

I can't seem to get the flow to work right here. I have a Ruby on Rails (2.3.9) application. For the purposes of this question we have only a couple of resources. Boxes and Messages.
Box has_many :messages
Message belongs_to :box
I have created a view located at /boxes/1/new_message where I have the below form_for code. I can successfully create a message from this view. The problem arrises when my validations kick in.
In this case, message.body can't be blank and is validated by message.rb. Once this validation happens, it kicks the user over to the Message.new action and upon successfully filling in the message.body the app can no longer find the #box.id to place in message.box_id.
I have tried just about everything I can think of by not sure how to allow a users to receive a validation and still successfully create a message for a box. See my code below for reference.
/views/boxes/new_message.html.erb
<% form_for [#box, Message.new] do |f| %>
<%= f.error_messages %>
<%= f.label :message_title %>
<%= f.text_field (:title, :class => "textfield-message grid_12 alpha") %>
<%= f.label :message_body %>
<%= f.text_area (:body, :class => "textarea-message grid_12 alpha ") %>
<%= f.submit "Add a Message", :class => 'input boxy' %>
<% end %>
messages_controller.rb
def create
#message = Message.new(params[:message])
#box = Box.find(params[:box_id])
#message = #box.messages.build(params[:message])
#message.user = current_user
respond_to do |format|
if #message.save
flash[:notice] = 'Message was successfully created.'
format.html {redirect_to #box }
else
format.html { render :action => "new" }
format.xml { render :xml => #flash.errors, :status => :unprocessable_entity }
end
end
end
def new
#message = Message.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #message }
end
end
I believe your
#box = Box.find(params[:box_id])
should be
#box = Box.find(params[:id])

Rails 3 form_for ajax call

I have method in my controller:
def work_here
#company = Company.find(params[:id])
current_user.work_apply(current_user, #company)
redirect_to company_path
end
On my view:
<%= render 'companies/work_form' if signed_in? %>
_work_form.html.erb:
<%= form_for company, :remote => true, :url => { :controller => "companies", :action => "work_here" } do |f| %>
<%= f.hidden_field :id, :value => company.id %>
<%= f.submit "I working here" %>
<% end %>
And I have a work_here.js.erb file:
$("#work_at_form").html("<%= escape_javascript("render('companies/works')") %>")
But my form works without ajax request(in other pages ajax forks fine), my js.erb file never use.
Can anyone give me advise?
Thanks.
The work_here.js.erb can't be read because you never call it. A redirect is allways do. render it when the request is js format.
def work_here
#company = Company.find(params[:id])
current_user.work_apply(current_user, #company)
respond_to do |format|
format.html { redirect_to company_path }
format.js { render }
end
end

Rails: Problem with routes and special Action

Sorry for this question but I can't find my error!
In my Project I have my model called "team".
A User can create a "team" or a "contest". The difference between this both is, that contest requires more data than a normal team.
So I created the columns in my team table.
Well... I also created a new view called create_contest.html.erb :
<h1>New team content</h1>
<% form_for #team, :url => { :action => 'create_content' } do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description %>
</p>
<p>
<%= f.label :url %><br />
<%= f.text_fiels :url %>
</p>
<p>
<%= f.label :contact_name %><br />
<%= f.text_fiels :contact_name %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
In my teams_controller, I created following functions:
def new_contest
end
def create_contest
if #can_create
#team = Team.new(params[:team])
#team.user_id = current_user.id
respond_to do |format|
if #team.save
format.html { redirect_to(#team, :notice => 'Contest was successfully created.') }
format.xml { render :xml => #team, :status => :created, :location => #team }
else
format.html { render :action => "new" }
format.xml { render :xml => #team.errors, :status => :unprocessable_entity }
end
end
else
redirect_back_or_default('/')
end
end
Now, I want on my teams/new.html.erb a link to "new_contest.html.erb".
So I did:
<%= link_to 'click here for new contest!', new_contest_team_path %>
When I go to the /teams/new.html.erb page, I get following error:
undefined local variable or method `new_contest_team_path' for #<ActionView::Base:0x16fc4f7>
So I changed in my routes.rb, map.resources :teams to map.resources :teams, :member=>{:new_contest => :get}
Now I get following error: new_contest_team_url failed to generate from {:controller=>"teams", :action=>"new_contest"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: ["teams", :id, "new_contest"] - are they all satisfied?
I don't think adding :member => {...} is the right way doing this. So, can you tell me what to do? I want to have an URL like /teams/new-contest or something.
My next question: what to do (after fixing the first problem), to validate presentence of all fields for new_contest.html.erb? In my normal new.html.erb, a user does not need all the data. But in new_contest.html.erb he does. Is there a way to make a validates_presence_of only for one action (in this case new_contest)?
UPDATE:
Now, I removed my :member part from my routes.rb and wrote:
map.new_contest '/teams/contest/new', :controller => 'teams', :action => 'new_contest'
Now, clicking on my link, it redirects me to /teams/contest/new - like I wanted - but I get another error called:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
I think this error is cause of #team at <% form_for #team, :url => { :action => 'create_content_team' } do |f| %>
What to do for solving this error?
I'm not sure about how your models work, but in my code I've always written;
#team.user_id = #current_user.id
instead of
#team.user_id = current_user.id
That would mean the id wasn't being passed to the controller giving you the error, wouldn't it?
Okay, I found my errors.
For the record:
First of all, I forgot to write the code inside my def new_contest. Here it is:
def new_contest
if #can_create
#team = Team.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #team }
end
else
redirect_back_or_default('/')
end
end
There were several typos, too, in my .erb file like text_fiels instead of text_field or create_content instead of create_contest.
current_user is working fine for me.

Rails does not display error messages on a form in a custom method

I've created a custom method called checkout in my app. I create an order (which is done my adding products to my "cart"), assign it to my client, and then I head to my checkout screen where I confirm the items and enter their customer order number and complete the order (submit).
Everything works great except that it doesn't display error messages. I'm able to display a flash error notice (seen in complete_order method) when things go wrong but it doesn't specify the details like a normal form would. The error messages should appear if the customer order number is not unique for that client.
Below is the custom method (checkout) related code.
Order Model:
validates_uniqueness_of :customer_order_number, :scope => :client_id
Orders_controller:
def checkout
#order = current_order
end
def complete_order
#order = current_order
respond_to do |format|
if #order.update_attributes(params[:order])
#order.complete #sets submitted datetime and state to 'complete'
flash[:notice] = 'Thank you! Your order is being processed.'
format.html { redirect_to( products_path ) }
format.xml { head :ok }
else
flash[:error] = 'Please review your items' #added to confirm an error is present
format.html { redirect_to( checkout_path ) }
format.xml { render :xml => #order.errors, :status => :unprocessable_entity }
end
end
end
And the form in the checkout view:
<% form_for #order, :url => { :controller => "orders", :action => "complete_order" } do |f| %>
<%= f.error_messages %>
<%= f.text_field :customer_order_number, :label => "Purchase Order Number" %>
<p>
<%= f.submit 'Complete Order', :confirm => 'Are you sure?' %> <small> or <%= link_to 'cancel', current_cart_path %></small>
</p>
<% end %>
Any idea how I can display the specific error messages?
Change redirect_to to render in else condition otherwise checkout method get called again & no error will displayed.
else
format.html { render :action => 'checkout' }

Resources