Why Ruby template handler isn't called in Rails 4? - ruby-on-rails-4

What could be the reason that the following Ruby template handler isn't called in my Rails 4 application? The returned json contains all the fields that a Job has, instead of just id and date fields.
# app/controllers/jobs_controller.rb
...
def index
#jobs = Job.all
render json: #jobs
end
...
# app/views/jobs/index.json.ruby
jobs = #jobs.map |job| do
{
id: job.id,
date: job.created_at
}
end
jobs.to_json
I use Rails 4.0.0.rc1 and ruby 1.9.3p0.

You are actually not calling a template handler. Instead, what Rails does here is call #jobs.as_json which returns a Hash containing with the attributes of that model. On this hash, it then calls to_json and return the result to the client.
The normal course of action is to override as_json on your model instead of using a template. As said above, as_json should return a hash that contains only the information you'd like to return to the user. Rails will then just serialize this hash as JSON.

Related

DJANGO API REST FRAMEWORK: schema methods

Django 1.11.3, python 3.6
I have 2 classes in my view.py:
class ProductList(generics.ListAPIView):
class SampleList(generics.ListAPIView):
Please note the same superclass. Might be relevant: Product is an actual model, Sample is not, SampleList is just a method that calls Product.objects.all() (same code as in ProductList)
All the code inside those classes besides class names is IDENTICAL (including serializer) - I just copied the class and renamed the copy).
The client before it hits urls for those two gets the schema
schema = self.client.get(self.myAppApiUrl)
#works, returns the results
result1 = self.client.action(schema, ["products", "list"])
params = {"id" : some_id, }
#fails with this: coreapi.exceptions.LinkLookupError: Index ['samples']['list'] did not reference a link. Key 'list' was not found.
result2 = self.client.action(schema, ["samples", "list"], params)
When I print "schema", I see
products: {
list([page])
}
samples: {
read(id)
}
My questions are: what makes it to add "list" to schema in the first case and "read" in the second case? And how can I add "list" to the second case? Maybe some schema update needs to be done somehow? The API web server was restarted.
What does that message "Key 'list' was not found" mean? Does this failure have something to do with the params passed? Removing params from the client call does not change anything.
I am also somewhat curious about what is that "page" thing in list and what adds that and but that's not important.

Pass locals from controller to active model serializer

I am trying to pass locals(prod: #product.id) to AMS in my controller, as follows:
#options_json = ActiveModel::SerializableResource.new(#option_types, prod: #product.id)
#options_json = #options_json.to_json(serialization_context: ActiveModelSerializers::SerializationContext.new(request), serialization_options: {prod: #product.id})
I am not sure whether to pass it during initialization or during call to to_json. Moreover I am unable to read this passed param in my OptionTypeSerializer. I've tried using options[:prod], serialization_options[:prod], serialization_opts[:prod] and a few different solutions that I found on stackoverflow, but none worked.
My AMS is pointed to master and in my gemfile.lock AMS version is active_model_serializers (0.10.0.rc5)
Also tried using:
#options_json = ActiveModel::SerializableResource.new(#option_types, serialization_context: ActiveModelSerializers::SerializationContext.new(request), prod: #product.id).to_json
but getting the value of instance_options[:prod] as null, although it is not null
Whenever I need to pass options into a serializer I do something like this:
# Controller
class CatalogPagesController < ApplicationController
# GET /catalog_pages/event/:id
def event
#catalog_pages = #event.catalog_pages
render json: #catalog_pages, index: true, each_serializer: Adm::CatalogPageSerializer
end
end
# Serializer
class CatalogPageSerializer < Adm::FormSerializer
attributes :id, :body, :catalog_page_templates
def include_catalog_page_templates?
return true unless #options[:index].present?
end
end
In this example I want to conditionally not return certain elements of JSON when coming from the index route.

around_action for render view in controller rails

I have the following method in my controller
around_action :wrap_in_transaction_and_begin, only: :update
def wrap_in_transaction_and_begin
ActiveRecord::Base.transaction do
begin
render json: yield
rescue => e
ActiveRecord::Rollback
render json: { error: e.to_s }
end
end
end
but the problem is raising an error:
Missing template topics/update...
because rails expected "render" in method update itself, not in action_around.
But I need use render json with the returned value of my method update.
exemple:
def update
hash = { foo: :bar }
topic.update(hash)
hash
end
I want render in json the hash object.
how can I do that?
thx.
There's a bunch of things wrong here, mostly because you're diverging from how Rails is supposed to work into really unsupported work-flows.
First, the return value from an action isn't useful. Rails doesn't expect your action to return anything, and it doesn't do anything with the return value. Rails expects output from your action to be either a render or a redirect, and if you don't do either of those things, you're implicitly asking Rails to do the rendering for you. This is why Rails is attempting to render topics/update.
You're also misusing around filters. Their purpose is to transform the output of your action, not to by the sole generator of output.
The way you should be rendering JSON is using respond_with from your action. First, use respond_to to define the kinds of data that your controller can output...
class MyController < ApplicationController
respond_to :json
end
Then, respond with the value you want to respond with.
def update
hash = { foo: :bar }
topic.update(hash)
respond_with hash
end

magic suggest returns POST 404 error

I'm trying to get autocomplete working in my rails application using Magic Suggest.
I think this is the correct question: How can I get MagicSuggest to grab the JSON that is at the URL I give it?
This is the error that console returns when I type letters:
POST http://localhost:3000/search_foods 404 (Not Found) jquery.js:8706
Uncaught Could not reach server
Here's the magic suggest code:
input.magicSuggest({
data: "/foods/search/",
placeholder: "Search Foods...",
valueField:'idFood',
displayField:'foodName'
});
The Routes
resources :search_foods
The Controller and Action
class SearchFoodsController < ApplicationController
def index
render json: %['Crack', 'Cocain', 'Gorilla Test', 'Horse Test']
end
end
When I visit the /search_foods url directly I get
'Crack', 'Cocain', 'Gorilla Test', 'Horse Test'
as my code is designed to do.
I think the issue is in that MagicSuggest, by default, sends a POST request, although I'm not sure if that's entirely relevant:
You can pass the url from which the component will fetch its JSON data.Data will be fetched
* using a POST ajax request that will * include the entered text as 'query' parameter. The results
* fetched from the server can be:
* - an array of JSON objects (ex: [{id:...,name:...},{...}])
* - a string containing an array of JSON objects ready to be parsed (ex: "[{id:...,name:...},{...}]")
* - a JSON object whose data will be contained in the results property
* (ex: {results: [{id:...,name:...},{...}]
Try this:
input.magicSuggest({
data: "http://localhost:3000/search_foods",
placeholder: "Search Foods...",
valueField:'idFood',
displayField:'foodName'
});
The doc states that the component expects one of the following:
* - an array of JSON objects (ex: [{id:...,name:...},{...}])
* - a string containing an array of JSON objects ready to be parsed (ex: "[{id:...,name:...},{...}]")
* - a JSON object whose data will be contained in the results property
* (ex: {results: [{id:...,name:...},{...}]
When you visit /search_foods you get
'Crack', 'Cocain', 'Gorilla Test', 'Horse Test'
This does not fit any of the 3 supported cases.
My suspicions about the POST request was correct.
My friend helped out so that's why I was able to fix this.
This is what I did..
Eliminated the FoodSearch Controller, because that's not needed at all.
Created a search action in my Food Controller like so:
def search
render json: ['cocain', 'crack', 'gorilla testosterone']
end
Edited my routes to a POST request instead of a get *This was the key:
resources :foods do
collection do
post :search
end
end
--- Another option, as karlipoppins suggests, is to simply change the type of request that magicSuggest makes by including the method attribute like so:
input.magicSuggest({
method: 'get',
data: "/foods/search/",
placeholder: "Search Foods...",
valueField:'idFood',
displayField:'foodName'
});
Then I wouldn't need to change the route to post.
Added this path to the data attribute in the js
data: "/foods/search/"
This will be a huge help to anyone trying to get magicSuggest to work in rails. It's a pretty damn easy setup to be honest. That one bit and the JSON formatting was the only thing that was tripping me up here.

Expected format for validation errors in Ember Data (using ActiveModel::Serializers)

Unfortunately, ActiveModel::Serializers does not currently support validation errors, though they're scheduled for 1.0. Until then, I've got to hack a solution of my own. The big problem? I have no idea what format Ember Data's ActiveModelAdapter expects these errors to be in. I tried simply passing in the errors property, but Ember Data didn't pick up on it:
class MySerializer < ActiveModel::Serializer
attributes :errors
end
So what should I pass in instead?
I use this method to render validation errors (note that you don't use the serializer at all):
def render_validation_errors errors
render json: {errors: errors.to_h}, status: 422
end
You would use it like this:
def create
model = Model.new model_params
if model.save
respond_with model
else
render_validation_errors model.errors
end
end
The format expected by ActiveModelAdapter is:
{"errors":{"title":"should begin with a capital letter"}}