Rabl/JSON view is not being rendered with ActionController::Live - ruby-on-rails

Simply when I include ActionController::live in my Appointments Controller my apptbook view which i request as appointments/apptbook.json is loaded (i can see the database loads on the terminal attached to my server) but nothing is returned to the browser, the browser hangs waiting for a response. Can't seem to work this out none of my usual html views in this same controller stall out like this, however i just tried my index json which I can confirm stalls out, so when i request /appointments I get a normal html response, however when i request /appointments.json or /appointments/apptbook.json I never see anything returned to the browser.
Is there an incompatibility with ActionController::Live??
I have tried only including it in my events method but it seems to need to be loaded at the top.
Is there a way of unloading it for a few of my methods??
Controller:
class AppointmentsController < ApplicationController
include ActionController::Live
def index
#appointments = Appointment.all
ActiveRecord::Base.include_root_in_json = false
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #appointments.to_json(:only => [:id, :start, :end], :methods => :title) }
end
end
def apptbook
#appointments = Appointment.last(2)
end
end
View:
collection #appointments
attributes :id
node(:start) { |appointment| appointment.start.iso8601}
node(:end) { |appointment| appointment.finish.iso8601}
node(:title) { |appointment| '<a class="patient-select-link" data-id="'+appointment.patient.id.to_s+'">'+appointment.patient.full_name+'</a>' }

Related

Rails default parems for id set to new?

I am getting a 404 error on my RoR app and i found that it was because one of the method in the controller, which should only triggers when the record is not new, triggered when the record is new.
I do by that checking if the id of that record nil in my controller.
before_action :create_record, if: proc { not params[:id].nil? }
I was confused by it was triggered so i went head and checked my front-end network, which show following:
Request
Parameters:
{"format"=>"json", "id"=>"new"} <----Set to new by default
My completely controller looks like this:
class Api::MyController < ApplicationController
before_action :create_recotrd, if: proc { not params[:id].nil? }
def show
end
def index
#my_model = MyModel.all
end
def create
#my_model = MyModel.new(my_model_params)
respond_to do |format|
if #my_model.save
format.json { render json: #my_model, status: :created}
else
format.json { render json: #my_model.errors, status: :unprocessable_entity}
end
end
end
def update
#my_model = MyModel.update
end
private
def create_record
#my_model = MyModel.find(params[:id])
end
def my_model_params
params.require(:my_model).permit(
:city,
:state,
:county,
:zip,
:telephone,
:email,
)
end
end
I cant seem to find out why the id in the parameters is set to "new" instead of "nil".
I tried in the console by doing MyModel.new, the default id was nil, but then when i do the GET request, the id was set to "new"
This is a really weird approach to set a new record. I think the problem lies in your routes. You are probably trying to access yoursite.com/your_model/new and your routes are configured to look for
get "your_model/:id" => "your_controller#show"
You are probably missing
get "your_model/new" => "your_controller#new"
So when you try to visit your_model/new the routes map the "new" as the :id param in your url.
I don't see a new action in your controller as well. You should read up on basic resource set up for rails here: http://guides.rubyonrails.org/routing.html.

How to render json for all actions from the after_action filter in ApplicationController?

Is it possible to create an after_filter method in the Rails ApplicationController that runs on every action and renders to JSON? I'm scaffolding out an API, and I'd like to render output to JSON for every action in the controller.
clients_controller.rb
def index
#response = Client.all
end
application_controller.rb
...
after_action :render_json
def render_json
render json: #response
end
The after_action is never executed, and the code aborts with:
Template is missing. Missing template clients/index, ...
If the render json: #response is moved into the controller action, it works correctly.
Is there a filter that will allow me to DRY up the controllers and move the render calls to the base controller?
You can't render after_action/ after_filter. The callback after_action is for doing stuff after rendering. So rendering in after_action is too late.
But your exception is just because you miss the JSON template. I recommend using RABL (which offers a lot of flexibility to your JSON responses and there is also a Railscast about it). Then your controller could look like:
class ClientsController < ApplicationController
def index
#clients = Client.all
end
def show
#client = Client.find params[:id]
end
end
And don't forget to create your rabl templates.
e.g. clients/index.rabl:
collection #clients, :object_root => false
attributes :id
node(:fancy_client_name) { |attribute| attribute.client_method_generating_a_fancy_name }
But in the case you still want to be more declarative you can take advantage of the ActionController::MimeResponds.respond_to like:
class ClientsController < ApplicationController
respond_to :json, :html
def index
#clients = Client.all
respond_with(#clients)
end
def show
#client = Client.find params[:id]
respond_with(#client)
end
end
Btw. beware if you put code in an after_action, this will delay the whole request.

Use a before_filter to filter list of products based on location

I have a Deals Rails app showing the list of products on home page.
Deals have a deal_country attribute.
My goal: I'd like to apply a before filter to filter the list of deals displayed to those whose deal.deal_country is the same as user's country (obtained through ip detection)
I tried the following but it does not work:
class StaticPagesController < ApplicationController
before_filter :filter_deals_based_on_visitor_country,
:only => [ :home]
def filter_deals_based_on_visitor_country
visitor_country = request.location.country
#deal = Deal.find_by(:deal_country => visitor_country)
end
def home
#deals = Deal.featured_on_homepage.to_a # deals that are now active given their start date
respond_to do |format|
format.html # home.html.erb
format.json { render json: #deals }
format.xml { render :xml => #deals }
# format.atom
end
end
end
I am not getting any error but it's not "filtering"/displaying deals based on user's country. It does nothing different as if I had not put anything more than the before filters. method.
How can I do this?
EDIT
To be sure it's not working I have created deals that are taking place in the US with deal.deal_country= US". But in local, i am seen as being in FRance and I can still see it.
Note: I have put to have in local /dev mode my French ip by doing this (i am sure it'w sorking because when i put in the homepage view: <%= Geocoder.search(request.remote_ip).first.country %> it displays France)
in application_controller.rb
def lookup_ip_location
if Rails.env.development?
Geocoder.search(request.remote_ip).first
else
request.location
end
end
in config/envrionment/development.rb
class ActionDispatch::Request
def remote_ip
"84.34.156.155" # fake ip for example
end
end
models/deal.rb
scope :featured_on_hp, lambda { default.where('date_launch_date <= ? AND date_end_date >= ?', Time.zone.now, Time.zone.now).where(featured: true) }
you forgot ! in def filter_deals_based_on_visitor_country, so its not getting called.
even if you correct this mistake, you will get an error in this line
#deal = Deal(:deal_country => visitor_country)
the correct syntax is
#deal = Deal.find_by(:deal_country => visitor_country)

Low-level caching error when storing database query

I'm trying to increase performance in my application by caching database queries. These are simple queries since I need to load and cache all objects.
Here's a shortened version of my application_controller.rb:
class ApplicationController < ActionController::Base
protect_from_forgery
def show_all
load_models
respond_to do |format|
format.json { render :json => {"items" => #items}
}
end
end
protected
def load_models
#items = Rails.cache.fetch "items", :expires_in => 5.minutes do
Item.all
end
end
end
But when I try and load this page I get this error:
ArgumentError in ApplicationController#show_all
undefined class/module Item
I've been following low-level caching guides by Heroku posted here: https://devcenter.heroku.com/articles/caching-strategies#low-level-caching
Any ideas what I can do here to get caching working? Is there a better way to accomplish this?
I fixed this issue by storing encoded JSON in Rails.cache.fetch instead of the raw ActiveRecord objects. I then retrieve the stored JSON, decode it, and render it for the view. The finished code looks like this:
def show_all
json = Rails.cache.fetch "Application/all", :expires_in => 5.minutes do
load_models
obj = { "items" => #items }
ActiveSupport::JSON.encode(obj)
end
respond_to do |format|
format.json { render :json => ActiveSupport::JSON.decode(json) }
end
end
def load_models
#items = Item.all
end

RAILS: Internet Explorer 8 not rendering actions, download popup instead

I have a controller and all of the actions are not render by IE8, in Firefox and Chromer works ok. The problem is only with this controller, i have another that work ok.
The code is:
class CustomersController < ApplicationController
auto_complete_for :customers, :name
def search
unless params[:q].nil?
#customers = Customer.find(:all, :conditions => ['name LIKE ?',
"%#{params[:q]}%"])
end
respond_to do |format|
format.xml { render :xml => #customers}
format.json { render :json => #customers}
end
end
def index
#customers = Customer.find_index
end
def show
#customer = Customer.find(params[:id])
end
For example the index action is not getting render and instead IE8 display a download dialog, but if i edit the index action like this:
def index
#customers = Customer.find_index // a find all but ordered.
respond_to do |format|
format.html
end
end
Any ideas what is happening?
UPDATE:
For all of you interested, the problem was the templates files names.
All the files with a name like "invoice.erb" was sent back to the browser as content "text/erb" while the files like "customers.html.erb" was sent back as "text/html".
Once i renamed all the file to "html.erb" everything works ok
ie8 doesn't know what to do with xml or json but does know what to do with html. If you really want the browser to display the xml you could add :content_type => 'text/plain' to the block so it knows how to respond to it.

Resources