uninitialized constant UrlsController::Url - ruby-on-rails

I'm new to Ruby and Rails, coming from Java and Playframework.
I'm following a tutorial http://www.sitepoint.com/building-your-first-rails-application-views-and-controllers/
I am getting an error on the line #shortened_url = Url.new
The error is :
NameError in UrlsController#new
uninitialized constant UrlsController::Url
I feel this is something like a ClassNotFoundError in Java ?? not sure ... does anyone know what I have to do. Is it basically a matter of using include or require, with the correct reference.
Apologies for the total newb question but I find it much easier to learn by doing and making mistakes, it sticks - and I reckon others will benefit too.
class UrlsController < ApplicationController
def new
#shortened_url = Url.new
end
def create
#shortened_url = Url.new(params[:url])
if #shortened_url.save
flash[:shortened_id] = #shortened_url.id
redirect_to new_url_url
else
render :action => "new"
end
end
def show
#shortened_url = Url.find(params[:id])
redirect_to #shortened_url.url
end
end

May or may not be the issue you're having, but Url is a reserved word in Rails.
Source: http://bparanj.blogspot.co.uk/2011/07/reserved-words-in-rails.html
Alternatively, it's weird that calling Url.new is calling new on your UrlsController instead of the Url model. This backs up my idea about using reserved words, it can often cause strange behaviour.
Edit: Oh and it looks like from another comment that you don't have a Url model. You'll need one of those before you can called .new on it. That said, don't create a model called Url, the reserved word thing will probably come back to bite you.

Related

Rails asking for "end", but everything has an end?

Ok, so I am trying to learn Rails by watching YouTube; so far I am having a better understanding as I go along.
Problem is, I am using Rails 4 whereas the vidoe uses Rails 3. No big deal. There was a problem with the video's code, so someone posted in the comments section some corrected code.
Problem is, I get this error:
SyntaxError in PostsController#create
/home/chris/blog/app/controllers/posts_controller.rb:43: syntax error, unexpected end-of-input, expecting keyword_end
Now I've gone through my code, looked it all over, and from what I do know of Rails so far, everything has an appropriate end. I have used comments and, for every beginning, there is an 'end'. But I have definitely messed something up. And yes this is Rails 4.0 I am using.
class PostsController < ApplicationController#main
def index#1
#posts=Post.all
end#1
def create#2
#post=Post.new(post_params)
if #post.save#2.1
redirect_to posts_path, :notice =>"Your post was successfully saved"
else
render "new"
end#2.1
end#2
def new#3
#post=Post.new
end#3
def edit#4
end#4
def show#5
#post=Post.find(params[:id])
end#5
def update#6
end#6
def destroy#7
end#7
private
def post_params#1
#allow = [:title, :content]
params.require(:post).permit(#allow)
end#1
end#main
There seems to be a stealth byte order mark character between end# and #1 near the end. Here's how it looks on my editor:
Deleting that line and typing it again fixed it for me.

Cached Controller Method?

I'm trying to make some changes to the show method in my events controller and noticed the changes making zero difference. I commented out the #event = Event.find_by_slug(params[:slug]) line and the show view still works and does not produce an error! I even deleted the entire show method and it still works. I thought for a moment I was working on a copy of the app, but it's definitely the correct one.
I've never had this problem before, but did recently upgrade my Rails version from 3.2.0 to 3.2.13. Wondering if there's a caching setting somewhere that's causing this. Has anyone experienced similar or got any pointers on where to look for a caching config setting perhaps?
EDIT - Code added
def show
#event = Event.find_by_slug(params[:slug])
#meta_title = "#{#event.headline} at #{#event.venue.name}, #{#event.venue.town} - #{#event.event_date.to_date.to_formatted_s(:my_format)}"
#meta_description = "#{#event.info.to_s.truncate(380, :separator => " ")}"
#facebook_image = "#{#event.event_image.url(:large)}"
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #event }
end
end
The view is quite large, but I would call fields using something like this:
<h2><%= #event.headline %> TEST</h2>
'TEST' is something I just added to see if that would be rendered and it is, so i'm definitely editing the correct version of the app.
EDIT - New development in finding this bug
After extensive searches for dupe actions etc I gradually started trying to manually find the cause. First by scaffolding a new model and seeing if the same behaviour occurred and it didn't. Then looking at what was different, top to bottom in my event controller I started to comment out lines/actions and then test behaviour. Anyway, commenting out load_and_authorize_resource which I am using to call the CanCan gem and it's ability model the caused my app to behave as it should do, obviously now without my role based code.
Can anyone think why CanCan could be causing this?
CanCan have both load_resource, authorize_resource and load_and_authorize_resource. They all do what they say, so in your example will load_resource set the #event instance variable #event = Event.find(params[:id]). authorize_resource will just call authorize! #event before each action. load_and_authorize_resource will fist load the resource and then authorize as before.
Here is another example from the CanCan documentation on github:
class ArticlesController < ApplicationController
load_and_authorize_resource
def show
# #article is already loaded and authorized
end
end

Rails Brakeman warning: Dynamic Render Path false alarm?

I'm just getting started with Rails, so I'm using Brakeman to learn about potential vulnerabilities in my newbie code. It's throwing a high-confidence "Dynamic Render Path" warning about the following code in my show.js.erb file:
$('#media-fragment').html('<%= escape_javascript(render(params[:partial])) %>');
I actually expected this was a problem, so no surprise there. So I changed it to the following:
# controller:
def show
if legal_partial?
#allowed_partial = params[:partial]
else
raise StandardError, "unexpected partial request: #{params[:partial]}"
end
end
private
def legal_partial?
%w(screenshots video updates).include? params[:partial]
end
# ...
# show.js.erb
$('#media-fragment').html('<%= escape_javascript(render(#allowed_partial)) %>');
Although I believe the code is now safe, Brakeman is still unhappy with this. Is there a more idiomatic way to control rendering of a partial based on user input?
Update (2/5/2016):
This has been fixed as of Brakeman 3.0.3.
If the legal_partial? method is inlined like this:
def show
if %w(screenshots video updates).include? params[:partial]
#allowed_partial = params[:partial]
else
raise StandardError, "unexpected partial request: #{params[:partial]}"
end
end
Brakeman will be able to detect the guard condition and will no longer warn about the later render call.
Original answer:
Unfortunately, Brakeman does not know that if legal_partial? is a proper guard. All it knows is that params[:partial] is assigned to #allowed_partial, and that is then passed to render.
You may be able to tell that #allowed_partial will always be a safe value. At that point, you have to consider whether or not it makes sense to add complexity in order to make a tool happy.
Just as an example, you could do this:
def show
render_allowed_partial params[:partial]
end
def render_allowed_partial name
if %w(screenshots video updates).include? name
#allowed_partial = name
else
raise StandardError, "unexpected partial request: #{params[:partial]}"
end
end
It's basically the same thing, except now you are hiding the assignment of #allowed_partial from Brakeman.
(Warning: Not necessarily "best" way of doing this.)
Using brakeman 4.2.0
I had a similar issue trying to render a specific hand-positioned-and-named template. Every product of my app required that specific named template. The template name came from the controller params as params[:a_particular_slug].underscore.
I solved with something like this:
def show
if #products = Product.where(a_slug: params[:a_particular_slug])
render template: lookup_context.find(params[:a_particular_slug].underscore, ["featured_products"])
else
render_404
end
end
Here I'm looking for a template. If you need to use a partial, be aware that lookup_context.find third params set to true allows to search for partials.
You can find more about lookup_context.find here
Hope this helps.

Rails 3.1 template handlers

I have a ruby gem, poirot, which enables the use of mustache templates in Rails. The template handler I have was extending from ActionView::Template::Handler, however this appears to be deprecated in Rails 3.1.
I have re-factored the handler to comply with the deprecation warnings. In doing this I am now unable to pass locals, or the view context, to the template. I can't seem to find out how to get this working with Rails 3.1.
module Poirot
class Handler
attr_reader :template
def initialize(template)
#template = template
end
def self.call(template, *args)
self.new(template).call
end
def call
view_path = "#{template.virtual_path}_view"
abs_view_path = Rails.root.join('app/views', view_path)
view_class = begin
view_path.classify.constantize
rescue NameError => e
Poirot::View
end
"#{view_class}.new(self, '#{template.source.gsub(/'/, "\\\\'")}').render.html_safe"
end
end
end
In my code above for the handler I get passed the template, which is an instance of ActionView::Template. But I'm not sure how to get the view context, which should include the locals etc
Can someone point me in the right direction?
Okay I have a solution, I'm not sure it is the best, it feels a little hacky to me!
In my view class I have managed to get access to the locals by doing the following:
locals = view_context.send(:view_renderer).send(:_partial_renderer).instance_variable_get("#locals") || {}
This feels a little messy as both view_renderer and _partial_renderer are private, and there is no proper accessor to the locals ivar.
I'm still hoping there is a better way to do this!
I spent about 4 hours investigating source code to find a solution, and now it's seems very simple:
just add "local_assigns" where you are want to eval it and use.
For example:
"#{view_class}.new(self, '#{template.source.gsub(/'/, "\\\\'")}', local_assigns).render.html_safe"
this string will be evaluted inside the module context - ActionView::CompiledTemplates and local_assigns will be accessible there.

Create method problem in Ruby on Rails

I have a rails app that involves users, essays, and rankings. It's pretty straightforward but I'm very new to rails. The part I'm having trouble with right now is the create method for the rankings.
The Essay class has_many :rankings and the Ranking class belongs_to :essay
in the rankings controller I have:
def create
#ranking = #essay.rankings.build(params[:ranking])
flash[:success] = "Ranking created!"
redirect_to root_path
end
but I get the error: undefined method `rankings' for nil:NilClass
I need each ranking to have an essay_id, and I believe build updates this for me.
I thought that rails give me the rankings method because of the relation I set, and why is #essay nil?
Thanks in advance
Build doesn't save. You should be using new and then save. I'd provide you sample code, but you haven't really given us a clear picture of what you have going on. That #essay instance variable is being used before it's defined, and I'm not really sure how your application is determining which essay the ranking belongs to.
You might wanna give Rails Guides a read.
I think this is what you intend to do:
# EssayController#new
def new
#essay = Essay.new(params[:essay])
#ranking = #essay.rankings.build(params[:ranking])
#...
end
Take a look at nested model forms , it should get you in the right direction.

Resources