Why do I get this error? - ruby-on-rails

I'm getting this error:
ActiveRecord::RecordNotFound (Couldn't find Video without an ID):
app/controllers/videos_controller.rb:52:in `topic_update'
It's referring to this action in my videos controller:
def topic_update
#video = Video.find(params[:id])
respond_to do |format|
if #video.update_attributes(params[:video])
format.html { redirect_to(#video) }
format.js
else
format.html { render :action => "edit" }
end
end
end
The error is thrown after this form sends a PUT request:
<%= form_for #video, :url => {:action => "topic_update"}, :remote => true do |f| %>
<div class="field">
<%= f.text_field :topic_names, :class => "topic_field" %>
</div>
<%= f.submit "Add Topic", :id => 'topic_submit' %>
<% end %>
This is what happens according to my logs:
Started PUT "/topic/update.js" for 127.0.0.1 at Mon Apr 11 00:12:19 -0700 2011
Processing by VideosController#topic_update as JS
Parameters: {"video"=>{"topic_names"=>"eedefva"}}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 57 LIMIT 1
I have this in my routes.rb file:
resources :videos
match '/topic/update' => "videos#topic_update"

This is because your 'topic_update' method will treat as a 'GET' method where as you want it as a post method,
try this in your routes.rb
resources :videos do
member do
put 'topic_update'
end
end
I haven't tested this but :D
read here for more info (http://guides.rubyonrails.org/routing.html)
HTH
cheers
sameera

Basically, you are trying to update a non-existent (not saved before) object.
This method form_for #video would add id parameter if #video is referring to an existent record that was saved before.
Please make sure you're calling update procedure (showing "edit" form) only if #video corresponds to a stored record.

Related

Validation not working - param is missing or the value is empty carrierwave

I have search for my problem but I can't found any solution.
My model home with attributes such as : title, logo, description, keywords.
I'm using carrierwave + delayed job for upload a logo, the upload is works (create & update) but when file / input file is empty I got this error :
ActionController::ParameterMissing in SettingsController#home_update_b
param is missing or the value is empty: home
Extracted source (around line #99):
def home_update_b_params
params.require(:home).permit(:logo)
end
end
SettingsController
def index
## get one record without params
#home = Home.take
end
def home_update_b
#home = Home.find(params[:id])
if #home.update(home_update_b_params)
respond_to do |format|
format.html { redirect_to setting_home_path, :notice => "Logo successfully updated" }
format.json { head :no_content }
end
else
respond_to do |format|
format.html {
flash[:alert] = "There's Something Wrong"
render :action => :home
}
format.json { render json: #home.errors, status: :unprocessable_entity }
end
end
end
private
def home_update_b_params
params.require(:home).permit(:logo)
end
I'm sure on home model have validate
class Home < ActiveRecord::Base
mount_uploader :logo, LogoUploader
after_save :enqueue
validates_presence_of :logo
end
form
<%= form_for(#home, :url => logo_update_path(#home), :html => { :class => "form-horizontal", :role => "form", :method => :put}) do |f| %>
<div class="form-group">
<%= f.label :logo, "Logo", :class => 'col-sm-3 control-label no-padding-right ace-file-input' %>
<div class="col-sm-4">
<%= f.file_field :logo, "data-file-input" => "easy" %>
</div>
</div>
<div class="clearfix form-actions">
<div class="col-md-offset-3 col-md-9">
<%= f.submit %>
</div>
</div>
<% end %>
stack trace
Processing by SettingsController#home_update_b as HTML
Parameters: {"utf8"=>"V", "authenticity_token"=>"gmXtbe31vfSPqM1N5taM1ge92nRvr
SpY91Y8vAlEBmc=", "commit"=>"Update Home", "id"=>"2"}
←[1m←[36mHome Load (0.0ms)←[0m ←[1mSELECT "homes".* FROM "homes" WHERE "hom
es"."id" = $1 LIMIT 1←[0m [["id", 2]]
Completed 400 Bad Request in 4ms
ActionController::ParameterMissing (param is missing or the value is empty: home
):
app/controllers/settings_controller.rb:99:in `home_update_b_params'
app/controllers/settings_controller.rb:60:in `home_update_b'
When I add another attribute to form (e.g title), input file still empty and it's works to update, but validation not works for input file is empty.
FYI Rails 4.1.1 and Ruby 1.9.3
If you are accepting any type of file from the user using an input type of "file" and the user doesn't select it, you won't get a key for that field in the parameter hash.
In your case, you are accepting only a logo from the user, and if it's empty, the home key doesn't exist in your parameter hash, thus the require() method throws an exception because it didn't find the specified key.
Instead of require() you can use the fetch() method which can return an empty hash as default value if the specified key is not found. Like this:
params.fetch(:home, {}).permit(:logo)

rails POST on /objects calling index method

Normally in rails, sending a POST to a RESTful controller, say, /orders, calls the #create action. This is what I want to happen. Instead, the #index method gets called. How do I fix this?
The server log from a POST to /orders:
Started POST "/orders" for 173.8.132.62 at 2013-03-24 14:45:23 -0700
Processing by OrdersController#index as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"EcsAZxbyd5OVVo5oIJZM/CNoyP7Cz6dRVBU7I41xENY=", "order"=>{"order_lines_attributes"=>{"0"=>{"item_id"=>"", "qty"=>"", "_destroy"=>"false"}}, "customer_id"=>""}, "commit"=>"Create Order"}
Order Load (0.1ms) SELECT "orders".* FROM "orders"
Rendered text template (0.0ms)
Completed 200 OK in 5ms (Views: 1.1ms | ActiveRecord: 1.2ms)
The entire routes.rb:
Wines::Application.routes.draw do
match ':controller(/:action(/:id))(.:format)'
resources :customers do
resources :phones
resources :addresses
end
resources :distributors do
resources :distributor_phones
resources :distributor_addresses
end
resources :items do
post 'sample', :on => :member
end
resources :orders do
post 'place', :on => :member
post 'deliver', :on => :member
resources :order_lines
end
resources :db do
post 'query', :on => :collection
end
resources :images, :beverage_types, :grapes
end
Some possibly relevant lines routes from rake routes:
place_order POST /orders/:id/place(.:format) orders#place
deliver_order POST /orders/:id/deliver(.:format) orders#deliver
order_order_lines GET /orders/:order_id/order_lines(.:format) order_lines#index
POST /orders/:order_id/order_lines(.:format) order_lines#create
new_order_order_line GET /orders/:order_id/order_lines/new(.:format) order_lines#new
edit_order_order_line GET /orders/:order_id/order_lines/:id/edit(.:format) order_lines#edit
order_order_line GET /orders/:order_id/order_lines/:id(.:format) order_lines#show
PUT /orders/:order_id/order_lines/:id(.:format) order_lines#update
DELETE /orders/:order_id/order_lines/:id(.:format) order_lines#destroy
orders GET /orders(.:format) orders#index
POST /orders(.:format) orders#create
new_order GET /orders/new(.:format) orders#new
edit_order GET /orders/:id/edit(.:format) orders#edit
order GET /orders/:id(.:format) orders#show
PUT /orders/:id(.:format) orders#update
DELETE /orders/:id(.:format) orders#destroy
I'm using formtastic, and my _form.html.erb looks like this:
<%= semantic_form_for(#order) do |f| %>
<% if #order.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#order.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% #order.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.semantic_fields_for :order_lines do |builder| %>
<%= render 'order_line_fields', f: builder %>
<% end %>
<%= link_to_add_fields "Add Order Line", f, :order_lines %>
<%= f.inputs :customer %>
<%= f.actions %>
<% end %>
The generated html <form> tag looks like this:
<form accept-charset="UTF-8" action="/orders" class="formtastic order" id="new_order" method="post" novalidate="novalidate"><div style="margin:0;padding:0;display:inline">
The generated submit action looks like this:
<input name="commit" type="submit" value="Create Order" />
Relevant code from the controller is as follows. When I submit a POST to /orders, I get
this is the index method, called with URL http://w:3000/orders and
method POST.
def index
#orders = Order.all
respond_to do |format|
format.xml # index.xml.erb
format.html {render :text => "this is the index method, called with URL #{request.url} and method #{request.method}"}
end
end
# GET /orders/1.xml
def show
#order = Order.find(params[:id])
respond_to do |format|
format.xml { render xml: #order.to_xml }
end
end
# GET /orders/new.xml
def new
#order = Order.new
1.times {#order.order_lines.build}
respond_to do |format|
format.xml { render xml: #order.to_xml }
format.html {}
end
end
# POST /orders.xml
def create
#order = Order.new(params[:order])
respond_to do |format|
if #order.save
format.xml { render xml: #order.to_noko_doc }
format.html { redirect_to #order, notice: 'Order was successfully created.'}
else
format.xml { render xml: #order.errors }
format.html {render action: 'new'}
end
end
Your match ':controller(/:action(/:id))(.:format)' route is getting matched first for the POST to orders#create, move it to the bottom of your routes file
Routes are matched in the order they are defined, so if your index route /orders comes before your create route /orders :via => [:post], the former will be invoked. Try placing your post route first.
match "orders" => "orders#create", :via => [:post]
# then resources :orders

Create.js.erb Not Showing In AJAX with Rails

I am trying to get AJAX working on a form in my rails application and am about 75% of the way there. I have a form where a person can create an activity and tag that activity with skills. I would like to provide the ability for them to create a new skill right within the form. I can replace the "Create a New Skill" link with a form and then save the record without any problem. My issue is after the record is saved, rails keeps redirecting me back to the my home page rather than back to the page with the form. The redirect is normal behavior if the user was creating a skill through the typical HTML form.
The link on my page to create a new skill that turns into a form:
<%= link_to "Create A New Skill", new_skill_path, :id => "new-skill-link", remote: true %>
The new skill form that replaces the link:
<%= form_for Skill.new, :remote => true do |f| %>
<%= f.text_field :description %>
<%= f.submit "Save", :class => 'btn-large btn-primary' %>
<% end %>
My skills controller (the New and Create methods):
def new
#skill = Skill.new
#tags = current_user.tags
respond_to do |format|
format.html
format.js
end
end
def create
#skill = current_user.skills.new(params[:skill])
params[:skill][:tag_ids] ||= []
respond_to do |format|
if #skill.save
flash[:success] = "Skill was successfully created!"
format.html { redirect_to home_page_url }
format.js { render action: "create" }
else
flash.now[:error] = "There was an error saving your skill."
format.html { render action: "new" }
format.js { render action: "new" }
end
end
end
My new.js.erb:
$("#new-skill-link").hide().after('<%= j render("skills/remote_form") %>');
My create.js.erb:
$("#new-skill").remove();
$("#new-skill-link").show();
$(".skill-list ul").append('<%= j render(#skill) %>');
It seems that rails is interpreting the request as HTML so it is responding with the HTML page. I tried adding :format => :js to the skill form but rails just rendered the javascript in my browser without interpreting it.
When I look at the log on the web server, I don't see any errors. I get:
Started POST "/skills" for 127.0.0.1 at 2012-12-31 20:02:16 -0700
Processing by SkillsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"xxxxx", "skill"=>{"description"=>"Example Skill"}, "commit"=>"Save"}
User Load (62.8ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'xxxxx' LIMIT 1
(0.1ms) begin transaction
SQL (15.4ms) INSERT INTO "skills" ("created_at", "description", "updated_at", "user_id") VALUES (?, ?, ?, ?) [["created_at", Tue, 01 Jan 2013 03:02:16 UTC +00:00], ["description", "Example Skill"], ["updated_at", Tue, 01 Jan 2013 03:02:16 UTC +00:00], ["user_id", 1]]
(1.4ms) commit transaction
Redirected to http://localhost:3000/home_page
Completed 302 Found in 96ms (ActiveRecord: 79.7ms)
Any thoughts?
The reason is, you should not do redirects inside the create method, because the AJAX request is kind of lost in the middle (you could see this via Firebug/FF).
Following is a sample code:
Ex: assuming I have a scaffold called project
projects_controller.rb
class ProjectsController < ApplicationController
#project = Project.new(params[:project])
if #project.save
flash.now[:success] = ["#{#project.name} sucessfully created"]
else
flash.now[:errors] = #project.errors.full_messages
end
end
in view/projects
_form.html.erb
<div id="message"></div>
<%= form_for #project :remote => true, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.text_field :name, :class => 'span3', :placeholder => "Project name" %>
<%= f.submit nil, :class => 'btn btn-success' %>
<% end %>
create.js.erb
$("#message").html("<%= escape_javascript raw(flash_display) %>");
in helper
module ApplicationHelper
def flash_display
response = "<div class='alert #{alert_class}'>"
response += "<button type='button' class='close' data-dismiss='alert'>x</button>"
flash.each do |name, msg|
msg.each do |m|
response = response + content_tag(:p, m)
end
end
response += "</div>"
flash.discard
response
end
private
def alert_class
css_class = case flash.first[0]
when :errors then "alert-error"
when :success then "alert-success"
when :notifications then "alert-block"
end
css_class
end
end
So as you can see, I'm not redirecting from my create method, after saving I'm just passing the message of the status. So your page will not refresh and only update the messages.

Redirecting from polymorphic association

I have a comments model that belongs to two models: submissions and posts
class Comment < ActiveRecord::Base
attr_accessible :content, :show
belongs_to :commentable, :polymorphic => true
end
class Submission < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
end
Submissions is a nested route and post is not.
In my comments controller:
def create
#commentable = find_commentable
#comment = #commentable.comments.build(params[:comment])
#comment.user = current_user
if #comment.save
#CommentMailer.comment_email(#user, #comment, #commentable).deliver
flash[:notice] = "Successfully created comment."
if #commentable == #submission
redirect_to [#contest, #commentable]
else
redirect_to [#commentable]
end
else
render :action => 'new'
end
end
find_contest
def find_contest
#contest = Contest.find(params[:contest_id])
end
find_commentable:
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
The redirect to post via #commentable works fine, but the redirect to submissions is not finding the contest.
Started POST "/submissions/36/comments" for 127.0.0.1 at 2012-11-30 18:34:41 -0800
Processing by CommentsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"R62NH5/EE34FPapEqy7mfpa0wKz18GtSdhH8MGYq2Ec=", "comment"=>{"content"=>"test", "show"=>"true"}, "commit"=>"Create Comment", "submission_id"=>"36"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 ORDER BY users.created_at DESC LIMIT 1
Submission Load (0.3ms) SELECT "submissions".* FROM "submissions" WHERE "submissions"."id" = $1 ORDER BY submissions.created_at DESC LIMIT 1 [["id", "36"]]
Completed 500 Internal Server Error in 116ms
ActiveRecord::RecordNotFound (Couldn't find Contest without an ID):
app/controllers/comments_controller.rb:19:in `create'
Change to submission routes:
submissions GET /submissions(.:format) submissions#index
POST /submissions(.:format) submissions#create
new_submission GET /submissions/new(.:format) submissions#new
edit_submission GET /submissions/:id/edit(.:format) submissions#edit
submission GET /submissions/:id(.:format) submissions#show
PUT /submissions/:id(.:format) submissions#update
DELETE /submissions/:id(.:format) submissions#destroy
Submission form:
<%= simple_form_for #submission, :html => { :multipart => true } do |f| %>
<div class="span7 offset2 submission">
<fieldset class="well pleft80 edit">
<%= f.hidden_field :contest_id , :value => params[:contest_id] %>
<%= f.input :title %>
<%= f.input :description %>
<%= f.input :comment_show, :as => :hidden, :input_html => { :value => true } %>
</fieldset>
<fieldset class="well pleft80 noborder">
<%= f.fields_for :image do |img_field| %>
<h3>Upload Photo<%= img_field.file_field :source %></h3>
<% end %>
</fieldset>
<div class ="form-actions pleft80">
<%= f.submit nil, :class => 'btn btn-primary btn-large' %>
</div>
</div>
<% end %>
You don't need to instantiate or classify anything.
redirect_to #comment.commentable
If you can't do that then you will need to build a global helper module for it and include that into the controller.
module RouteHelpers
def comment_association_redirect_to(comment)
item = comment.commentable
case item.class.to_s
when 'Submission'
redirect_to submission_path(item)
end
end
end
And include it within the ApplicationController:
include RouteHelpers
Then you can call comment_association_redirect_to anywhere in your app (controllers and so on).
I stripped the nested routing out of the app and now it works fine and it's much simpler. Not sure I can think of a good reason to use nested routing when the views must relate the dependencies.

Update method "No route matches [POST]"

Having a bit of trouble with the following ruby on rails code snippet - I have books and would like to update a book's name, here is how I try to do it:
<h1>Edit the book "<%= #book.name %>"</h1>
<%= form_tag action: :update, id: #book do %>
<p>
<label for="book_name">Name</label>
<%= text_field :book, :name %>
<%= submit_tag 'Save changes' %>
</p>
<% end %>
This is what I do in the books controller:
def edit
#book = Book.find(params[:id])
end
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to :action => 'show', id => #book
else
#subjects = Subject.find(:all)
render :action => 'edit'
end
end
These are my routes:
root to: 'authors#index'
resources :books, :authors
When I click the submit button in the form, it gives me No route matches [POST] "/books/5" and directs to localhost:3000/books/5 instead of staying and localhost:3000/books/5/edit
What am I doing wrong here? Shouldn't there be a put method for updating stuff somewhere rather than a post method?
Updates should use put not post.
<%= form_tag( { :controller => :books, :action => :update, :id => #book.id }, { :method => :put } ) do %>
or better yet use form_for
<%= form_for #book do |f| %>
On your console run "rake routes" and it will print out all available routes.
Please try this:
We need to specify match in routes file.
match "/books/:id" => "books#update"
resources :books should do the job. you dont have to explicitly use "match".
def edit
#book = Book.find(params[:id])
end
form.html
form_for #book, :method => :put do |f|
def update
#book = Book.find(params[:id])
#book.update_attributes(params[:book])
end
this should do the job.
I had this issue before. Everything was right but still getting the error then I found out it was
gem 'rails-api'
Removed it and it all worked fine.

Resources