Ruby NoMethodError - undefined method `blah_url' for BlahController - sql

I am calling this js from a link:
function createNewTopLevelEntry(){
var user_id = $("#user").val();
var header = prompt("Enter the name");
$.ajax( '/users/' + user_id + '/entries', {
data: {
entry: { header: header,
user: user_id } },
type: 'POST',
cache: false,
dataType: 'json',
success: displayTopLevelEntries
});
}
It hits this controller:
def create
#entry = Entry.new(params[:entry])
respond_to do |format|
if #entry.save
format.html { redirect_to #entry, notice: 'Entry was successfully created.' }
format.json { render json: #entry, status: :created, location: #entry }
else
format.html { render action: "new" }
format.json { render json: #entry.errors, status: :unprocessable_entity }
end
end
end
This is the response on the server:
Started POST "/users/1/entries" for 127.0.0.1 at 2013-03-25 21:50:36 -0700
Processing by EntriesController#create as JSON
Parameters: {"entry"=>{"header"=>"Hi", "user"=>"1"}, "user_id"=>"1"}
(0.1ms) begin transaction
SQL (0.5ms) INSERT INTO "entries" ("completed", "created_at", "endtime", "header", "parent", "starttime", "starttimeset", "text", "totaltime", "updated_at", "user") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["completed", nil], ["created_at", Tue, 26 Mar 2013 04:50:36 UTC +00:00], ["endtime", nil], ["header", "Hi"], ["parent", nil], ["starttime", nil], ["starttimeset", nil], ["text", nil], ["totaltime", nil], ["updated_at", Tue, 26 Mar 2013 04:50:36 UTC +00:00], ["user", "1"]]
(2.5ms) commit transaction
Completed 500 Internal Server Error in 10ms
NoMethodError - undefined method `entry_url' for #<EntriesController:0x007fb22b9f7fd8>:
(gem) actionpack-3.2.11/lib/action_dispatch/routing/polymorphic_routes.rb:129:in `polymorphic_url'
(gem) actionpack-3.2.11/lib/action_dispatch/routing/url_for.rb:150:in `url_for'
(gem) actionpack-3.2.11/lib/action_controller/metal/rendering.rb:60:in `_process_options'
(gem) actionpack-3.2.11/lib/action_controller/metal/streaming.rb:208:in `_process_options'
(gem) actionpack-3.2.11/lib/action_controller/metal/renderers.rb:34:in `block in _handle_render_options'
What is the entry_url? Why is it looking for it? Do i need to include something in the model. Its just has attr_accessors for the vars.
class Entry < ActiveRecord::Base
attr_accessible :completed, :endtime, :header, :starttime, :starttimeset, :totaltime, :user, :text, :parent
end
Heres is my routes file:
Tasks::Application.routes.draw do
match '/users/:id/projects' => 'users#show_projects_for_user'
authenticated :user do
root :to => 'home#index'
end
root :to => "home#index"
devise_for :users
resources :users do
resources :entries
end
end
Thanks for the help.

The entry_url is what it's asking you to redirect to when you say redirect_to #entry
You don't have an entries resource in the routes file. You do have one nested within user, but then you need to pass as well as the entry.
redirect_to [ #user, #entry ]
just saw your comment - if it's doing this on the JSON path similarly you need to have
location: [#user, #entry]
Basically anywhere you're asking rails to build a url for an entry you need to pass the entry's user in because you have entry nested within user in the routes and not as a standalone resource routing.
Adding an edit to respond to the comment because there's no formatting in comments:
Yes, this it will work to delete the location as it will no longer call the helper to build that location in the json, but I am presuming you want that. So try this to make the location work:
format.json { render json => { :entry => #entry, :status => created, :location => [#user, #entry] }}
from your comment... if that's not working then let's try calling the url helper directly
format.json { render json => { :entry => #entry, :status => created, :location => user_entry_url(#user, #entry) }}

If you are using Rails3, this might case because with rails3, the url has become path
Ex:
#rails2
entry_url
#rails3
entry_path
So try entry_path instead of entry_url

Related

Failing RSpec test with strong parameters

I am migrating my Rails 4 app (still using protected attributes gem) to Rails 5.1.4. In the course of this action, I need to rewrite a lot of code to replace protected attributes with strong parameters.
I am currently stuck on one specific controller where my RSpec tests fail, and I don't know how to implement the controller and test logic such that things are correct and tests pass.
The app has an admin backend where users can add (and thus upload) photos to an album. The respective Admin::PhotosController handles the photos of an album.
Here's the relevant exerpt from my app:
def create
# #organizer_account is set by an before_filter
#album = #organizer_account.albums.find_by_id(params[:album_id])
#photo = #album.photos.new(photo_params)
#photo.organizer_account_id = #organizer_account.id
authorize! :create, #photo
respond_to do |format|
if #photo.save
format.html {
render :json => [#photo.to_jq_file].to_json, :content_type => 'text/html', :layout => false
}
format.json {
files = [ #photo.to_jq_file ]
render :json => {:files => [#photo.to_jq_file] }, :status => :created, :location => admin_album_photo_path(#album, #photo)
}
else
format.html {
render action: "new"
}
format.json {
render json: #photo.errors, status: :unprocessable_entity
}
end
end
end
I have defined the following strong parameters:
private
def photo_params
params.require(:photo).permit(:id, :album_id, :organizer_account_id, :file)
end
The failing RSpec test is as follows:
require 'spec_helper'
describe Admin::PhotosController, :type => :controller do
render_views
describe "post 'create'" do
describe "with valid parameters" do
before(:each) do
#organizer_account = FactoryBot.create(:organizer_account)
#user = FactoryBot.create(:user)
#user.organizer_account_id = #organizer_account.id
#user.add_role :admin, #organizer_account
#user.save
sign_in #user
#album = #organizer_account.albums.create(:title => "Album 1")
#photo_attrs = FactoryBot.attributes_for(:photo)
request.env["HTTP_REFERER"] = new_admin_album_path
controller.request.host = #organizer_account.subdomain + ".lvh.me"
end
it "should create a new photo record", :focus => true do
lambda {
post :create, params: {:photo => #photo_attrs, :album_id => #album.id }
}.should change(#organizer_account.albums.find_by_id(#album.id).photos, :count).by(1)
end
end
end
end
I strongly assume that the issue is in parameters are a) passed
post :create, params: {:photo => #photo_attrs, :album_id => #album.id }
and then processed
#photo = #album.photos.new(photo_params)
While the params hash passed by the test has all the required entries
params: {"photo"=><ActionController::Parameters {"file"=>[#<ActionDispatch::Http::UploadedFile:0x00000010dd7560 #tempfile=#<Tempfile:C:/Users/PATRIC~1/AppData/Local/Temp/RackMultipart20180520-11424-avge07.gif>, #original_filename="image6.gif", #content_type="image/gif", #headers="Content-Disposition: form-data; name=\"photo[file][]\"; filename=\"image6.gif\"\r\nContent-Type: image/gif\r\nContent-Length: 46844\r\n">]} permitted: false>, "album_id"=>"1561", "controller"=>"admin/photos", "action"=>"create"}
the photo_params is empty:
photo_params: {}
Update #1: Definition of factory for photo
FactoryBot.define do
factory :photo, :class => Photo do
file Rack::Test::UploadedFile.new(Rails.root + 'spec/fixtures/photos/apfelkuchen.jpg', "image/jpg")
end
end
Update #2: Photo model with file attachment and image processing config
class Photo < ActiveRecord::Base
require 'rmagick'
include Magick
belongs_to :album
belongs_to :organizer_account
before_destroy { |photo| photo.file.destroy }
validates :album_id, :presence => true
validates :organizer_account_id, :presence => true
has_attached_file :file,
# The following tyles and convert options lead to breaking RSpec tests. If commented, RSpec tests pass.
:styles => {
:mini => "50x50#",
:thumb => "160x160#",
:large => "1200x1200>"
},
:convert_options => {
:mini => "-quality 75 -strip",
:thumb => "-quality 75 -strip"
}
validates :file, :presence => true
end

Rails: nested resources and routing errors

I've got a Template model, and a Doc model. They're nested resources, with the Templates being the parent, thus:
resources :templates do
get "/documents/lock/:id" => "docs#lock", :as => :lock_doc
get "/documents/unlock/:id" => "docs#unlock", :as => :unlock_doc
get "/documents/pdf/:id" => "docs#pdf", :as => :pdf_doc
resources :docs, :path => :documents
end
That part, I think, all works fine. When I try to submit the form for creating a doc the record exists but I get routing errors, thus:
ActionController::RoutingError (No route matches {:action=>"edit", :controller=>"docs", :template_id=>nil, :id=>#<Doc id: 2, user_id: "admin", cover: "1209hpnl", message: "The world economic outlook is improving, albeit slo...", created_at: "2013-01-07 03:54:05", updated_at: "2013-01-07 03:54:05", issue_code: "1209hpnl", title: "January 2013", locked: nil, retired: "active", template: nil>}):
app/controllers/docs_controller.rb:134:in `block (2 levels) in create'
app/controllers/docs_controller.rb:132:in `create'
The lines correspond to the create method:
def create
#doc = Doc.new(params[:doc])
respond_to do |format|
if #doc.save
format.html { redirect_to share_url(#doc), notice: "Saved. You may from here #{view_context.link_to('edit', edit_template_doc_url(#doc))} it further, #{view_context.link_to('finalise', template_lock_doc_url(#doc))} it, or return #{view_context.link_to('home', root_url)}.".html_safe }
format.json { render json: #doc, status: :created, location: #doc }
else
format.html { render action: "new" }
format.json { render json: #doc.errors, status: :unprocessable_entity }
end
end
end
I think the problem lies somewhere in here, but I can't for the life of me figure it out.
Cheers for any help!
EDIT: with rake routes
template_lock_doc GET /templates/:template_id/documents/lock/:id(.:format) docs#lock
template_unlock_doc GET /templates/:template_id/documents/unlock/:id(.:format) docs#unlock
template_pdf_doc GET /templates/:template_id/documents/pdf/:id(.:format) docs#pdf
template_docs GET /templates/:template_id/documents(.:format) docs#index
POST /templates/:template_id/documents(.:format) docs#create
new_template_doc GET /templates/:template_id/documents/new(.:format) docs#new
edit_template_doc GET /templates/:template_id/documents/:id/edit(.:format) docs#edit
template_doc GET /templates/:template_id/documents/:id(.:format) docs#show
PUT /templates/:template_id/documents/:id(.:format) docs#update
DELETE /templates/:template_id/documents/:id(.:format) docs#destroy
templates GET /templates(.:format) templates#index
POST /templates(.:format) templates#create
new_template GET /templates/new(.:format) templates#new
edit_template GET /templates/:id/edit(.:format) templates#edit
template GET /templates/:id(.:format) templates#show
PUT /templates/:id(.:format) templates#update
DELETE /templates/:id(.:format) templates#destroy
The problem is in your call to edit_template_doc_url(#doc) inside the notice string. You need to supply the template as well, like this:
edit_template_doc_url(params[:template_id], #doc)

storing complex records in rails database with form_tag

I'm trying to save records in a database. Many of the column values will be taken from a http request to an api.
I have a text field and some check boxes along with the session_id in the form which will be persisted. this is posted from another controller (form_tag('results#store'))to an action called store in the results controller.
Store action:
def store
query = query_preprocesser(params[:query]) # this is in a helper
## example of resArray ##
#resArray = [[{:engine => "bing, :results => [{:Description => "abc", :Title => "def"}, {:Description => "ghi", :Title => "jkl"}]}, {etc},{etc} ],[{:eng...}]]
resArray = getResults(query) # Also a helper method returning an array of up to 3 arrays
resArray.each do |engine|
db_name = engine[:engine]
engine[:results].each do |set|
res = Result.new(
:session_id => params[:session_id],
:db_name => db_name,
:query => query,
:rank => set[:Rank],
:description => set[:Description],
:title => set[:Title],
:url => set[:Url] )
res.save!
end
end
res.each do |res|
res.save
end
#Result.new(:session_id => params[:session_id], :db_name => "Bing", :query => "Whats the story", :query_rank => 1, :title => "The Title", :description => "descript", :url => "www.google.ie",:query_number => 1)
respond_to do |format|
format.html { redirect_to pages_path }
format.json { head :no_content }
end
end
My routes are resources :results
Server logs:
[2012-07-10 23:30:48] INFO WEBrick 1.3.1
[2012-07-10 23:30:48] INFO ruby 1.9.3 (2012-04-20) [x86_64-linux]
[2012-07-10 23:30:48] INFO WEBrick::HTTPServer#start: pid=15584 port=3000
Started POST "/results" for 127.0.0.1 at 2012-07-10 23:31:36 +0100
Connecting to database specified by database.yml
Processing by ResultsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"/nTJOF5Ab+XnL+jxRBHnTJz45YRVmgbf55bmn5/iz8E=", "query"=>"search term", "button"=>"", "searchType"=>"Seperate", "bing"=>"1", "session_id"=>"e08c13a99f21a91520fcc393e0860c94"}
(0.2ms) begin transaction
(0.2ms) rollback transaction
Rendered results/_form.html.erb (13.9ms)
Rendered results/new.html.erb within layouts/application (23.6ms)
Completed 200 OK in 213ms (Views: 78.4ms | ActiveRecord: 2.9ms)
Form:
<%= form_tag('results#store') do %>
Rake routes:
store POST /pages(.:format) results#store
results GET /results(.:format) results#index
POST /results(.:format) results#create
new_result GET /results/new(.:format) results#new
edit_result GET /results/:id/edit(.:format) results#edit
result GET /results/:id(.:format) results#show
PUT /results/:id(.:format) results#update
DELETE /results/:id(.:format) results#destroy
store POST /pages(.:format) results#store
pages GET /pages(.:format) pages#index
I keep getting redirected to the new action in Results controller. The helper methods aren't even being executed. I'm a past master at over complicating things, can anyone help unravel this for me?
Do you have a route set up for the store action? If you do then you should use the url helper for it in your form tag:
form_tag( results_store_url )

Rails3 and Rspec2 controller testing with a namespace

I'm trying to test a controller with a name space, following is my controller (/admin/sites_controller.rb):
class Admin::SitesController < AdminController
def create
#site = Site.new(params[:site])
respond_to do |format|
if #site.save
format.html { redirect_to(#site, :notice => 'Site was successfully created.') }
format.xml { render :xml => #site, :status => :created, :location => #site }
else
format.html { render :action => "new" }
format.xml { render :xml => #site.errors, :status => :unprocessable_entity }
end
end
end
end
and following is my routes.rb file
namespace :admin do
resources :sites
end
I'm using rspec2 to test my controller and following is my controller spec
describe Admin::SitesController do
describe "POST create" do
describe "with valid params" do
it "creates a new Site" do
expect {
post :create, :site => valid_attributes
}.to change(Site, :count).by(1)
end
end
end
end
But when I run the spec it gives me the following routing error
Admin::SitesController POST create with valid params creates a new Site
Failure/Error: post :create, :site => valid_attributes
NoMethodError:
undefined method `site_url' for #<Admin::SitesController:0xb5fbe6d0>
# ./app/controllers/admin/sites_controller.rb:47:in `create'
# ./app/controllers/admin/sites_controller.rb:45:in `create'
# ./spec/controllers/admin/sites_controller_spec.rb:78
# ./spec/controllers/admin/sites_controller_spec.rb:77
I guess its because of the 'admin' name space I'm using, but how can I fix that?
I'm using
Rails3
Rspec2
Linux
When you namespace the route, you're creating URL and path helpers that look like this:
HTTP Verb Path action helper
GET /admin/sites index admin_sites_path
GET /admin/sites/new new new_admin_site_path
POST /admin/sites create admin_sites_path
GET /admin/sites/:id show admin_site_path(:id)
GET /admin/sites/:id/edit edit edit_admin_site_path(:id)
PUT /admin/sites/:id update admin_site_path(:id)
DELETE /admin/sites/:id destroy admin_site_path(:id)
So you can either use those directly in your code (i.e. redirect_to admin_site_path(#site) ), or you can do something like:
redirect_to([:admin, #site])

server error with uploadify in ruby on rails 3.1

I'm trying to upload a video using uploadify and paperclip on rail 3.1
When i upload a video with uploadify, the server returns an 500 error.
The development.log says:
Started POST "/videos" for 127.0.0.1 at Tue Oct 04 14:46:05 +0200 2011
Processing by VideosController#create as HTML
Parameters: {"Filename"=>"prova.mov", "folder"=>"/public",...}
WARNING: Can't verify CSRF token authenticity
#<Video id: nil, source_content_type: nil, source_file_name: nil, source_file_size:nil, state: nil, created_at: nil, updated_at: nil>
[paperclip] Saving attachments.
Completed 500 Internal Server Error in 29ms
ActionView::MissingTemplate (Missing template videos/create, application/create with {:locale=>[:en, :en], :handlers=>[:builder, :coffee, :erb], :formats=>[:html]}. Searched in:
* "($mypath)/workspace/Video_Api/app/views"):app/controllers/videos_controller.rb:48:in `create'.
This is my controller:
def create
logger.info(params.inspect)
#video = Video.new(params[:video])
logger.info(#video.inspect)
respond_to do |format|
if #video.save
format.html
format.json { render :json => #video, :status => :created, :location => #video }
else
format.html { render :action => "new" }
format.json { render :json => #video.errors, :status => :unprocessable_entity }
end
end
end
And this is my uploader:
<input id="upload" type="file" name="upload" />
<!--div class="button" id="send_button">SEND FILE</div -->
</div>
<script>
<%- session_key = Rails.application.config.session_options[:key] -%>
$('#upload').uploadify({
'uploader' : 'uploadify.swf',
'script' : '/videos',
'cancelImg' : 'images/cancel.png',
'folder' : '/public',
'buttonText' : 'Add video!',
'multi' : true,
'auto' : true,
'scriptData' : {"<%= key = Rails.application.config.session_options[:key] %>" :"<%= cookies[key] %>",
"<%= request_forgery_protection_token %>" : "<%= form_authenticity_token %>",
},
onError : function (event, id, fileObj, errorObj) {
alert("error: " + errorObj.info);
}
});
Any ideas?
The error is pretty straightforward -- it is saying that you are missing a template to render videos/create -- if you're trying to render HTML here, you'll need to create this template. If you're expecting your JSON response instead, you need to figure out why that isn't being triggered. Changing the 'script' parameter to be '/videos.json' should take care of that, although it might be smarter to use the Rails helper url_for.