Cached Controller Method? - ruby-on-rails

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

Related

How to display errors in activeadmin forms after overriding controller

I have a situation where I need to override create in activeadmin. I autofill the fields and if the data already exists it should update otherwise create. Here is my create method:
def create
id = params[:company].dig(:id)
if id.present?
#company = Company.find(id)
if #company.update(permitted_params[:company])
redirect_to resource_url
flash[:notice] = 'Company created successfully'
else
#add errors to semantic errors
end
else
new_permitted_params = permitted_params[:company].except(:id)
#company = Company.new(new_permitted_params)
#company.save
if #company.errors.any?
#add this to semantic errors so that activeadmin handles and displays the errors
end
end
end
I want to display the errors which violate the validations so that the user knows if he/she has entered an invalid entry.
I found this but it looks like a workaround more than a solution. Please help me solve this.
Thanks in advance.
I created a new HTML file in views named new.html.arb and added insert_tag renderer_for(:new) in it. After that all I did was
if #company.errors.any?
render 'new'
end
I discovered it by seeing the default behavior of activeadmin. I hope this helps other people who are looking to do something similar. This is the result that I get and which was required by me.
I wonder if client side logic to submit to different URLs depending on id.present? might make things more restful.

uninitialized constant UrlsController::Url

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.

undefined method {....}_url when calling create in api controller

I'm working on a rails app that serves some json and I'm having hard time understanding what is going on in the code below (simplified for the purpose of understanding the issue).
module Api
class ProjectController < ApplicationController
respond_to :json
def show
x = {"id"=>17, "name"=>"abc", "version"=>1}
respond_with x.to_json, status: 200
end
def create
x = {"id"=>17, "name"=>"abc", "version"=>1}
respond_with x.to_json, status: 200
end
end
end
The show action works fine but when I call the create action I get
NoMethodError (undefined method '{"id":17,"name":"abc","version":1}_url' for
Api::ProjectsController:0x007fbb2294cd18)
Why do I get this error while show works just fine? is it because create makes a post instead of a get?
How can I solve it?
Thanks for your help and have a nice day.
The issue is that your controller is in a module (Api). That affects the namespace, and thus the routing; you must include that namespace as part of what you pass to respond_with.
Normally, I'd direct you to this stackoverflow answer (credit goes there). But since you are using a hash instead of a model, this answer might be more applicable.
Note how Rails is trying to call a ..._url method. The ... is your hash, in JSON format. You need to help Rails here on how to render.

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.

Loading a page into memory in Rails

My rails app produces XML when I load /reports/generate_report.
On a separate page, I want to read this XML into a variable and save it to the database.
How can I do this? Can I somehow stream the response from the /reports/generate_report.xml URI into a variable? Or is there a better way to do it since the XML is produced by the same web app?
Here is my generate_report action:
class ReportsController < ApplicationController
def generate_report
respond_to do |format|
#products = Product.all
format.xml { render :layout => false }
end
end
end
Here is the action I am trying to write:
class AnotherController < ApplicationController
def archive_current
#output = # get XML output produced by /reports/generate_report
# save #output to the database
respond_to do |format|
format.html # inform the user of success or failure
end
end
end
Solved: My solution (thanks to Mladen Jablanović):
#output = render_to_string(:file => 'reports/generate_report.xml.builder')
I used the following code in a model class to accomplish the same task since render_to_string is (idiotically) a protected method of ActionController::Base:
av = ActionView::Base.new(Rails::Configuration.new.view_path)
#output = av.render(:file => "reports/generate_report.xml.builder")
Perhaps you could extract your XML rendering logic to a separate method within the same controller (probably a private one), which would render the XML to a string using render_to_string, and call it both from generate_report and archive_current actions.
What I typically do in this type of situation is to create a separate module/class/model to generate the report (it could even potentially be right in the Product model). This separate component could be in app/models or it could be in lib. In any case, once you have it extracted you can use it anywhere you need it. The controller can call it directly. You can generate it from the console. You can have a cron job generate it. This is not only more flexible, but it also can help smooth out your request response times if the report becomes slow to generate.
Since you are using a template it's understandable that the controller route is convenient, but even if you have to include some kind of ruby templating system in your auxiliary lib, it's still probably going to be less hassle and more flexible then trying to go through the controller.
#output = Product.all.to_xml
I'm sorry, is you question about Xml or about sessions? I mean is the fact that your action generates Xml material to the question? Or do you just want to save the output of the action for latter use?
You said on a "separate" page - you mean on another request? (like after user approved it?)
Why do you want to save the output? Because it should be saved exactly as rendered? (for example user can get frustrated if he clicked to save one report and you saved another)
Or is this thing expensive to generate?
Or may be, I got it wrong and it's about refactoring?

Resources