Conditional except, only, include in render json for Rails - ruby-on-rails

Can one have conditional except, only or include options when rendering? So, like in the example below:
render json: #post,
except: [:author]
Is it possible to have that except option or a similar option be conditional?
Ideally, something along the lines of a conditional way of doing this that allows me to deal with many different conditions and cases.
Like maybe something like:
render json: #post,
except: return_excluded_keys
return_excluded_keys function could return keys that need to be excluded.
I am using Rails 4.2.6 and Active Model Serializers 0.9.3.

Maybe:
render json: #post.as_json(except: [:author])

Conditional attributes in Active Model Serializers
https://github.com/rails-api/active_model_serializers/issues/825
I believe these should point you in the right direction. You can pass a condition to the serialiser and then manually construct the output.

Related

How to use multiple Serializers for the same model with ActiveModelSerializer rails 4

In my controller, i have two methods that render a json, i want to use differents serializer for each method. how can i do it.
i've tried : render json: response ,each_serialiser: SerializerName in every methods by it's doesn't work
you should create two serializer for each response use one of them and rename the response.
render json: #response, serializer: SerializerName
should do the trick.

How to create a Rails model without an HTML view

I have a model that I only want to ever return JSON, regardless of any conneg or file-like extensions on the URI (e.g. /app/model.json). Google-fu is coming up short and this can't be that difficult.
In your controllers you simple have to create a respond_to block that only responds to JSON:
respond_to do |format|
format.json { render :json => #model }
end
This is actually a decision made by the controller, not because there is/is not a model or view present. In your controller you can:
render json: #your_model
However you will quickly find that the default implementation of to_json (which is what is used internally, above) can be annoying hard to do exactly what you want. When you reach that point you can use RABL to create views that massage the JSON from your model(s) exactly as you want.

Implementing pagination in a Ruby on Rails 4 API

I'm building an API on Rails using ActiveRecordSerializer for serialization. When I want to render a list of resources I use:
render json: #resources
This automatically detects that there is a serializer for the resource, and uses it.
Now I want to implement pagination, and my idea is having a class called PaginatedResponse, instantiate it and render it as a json like this:
render json: PaginatedResponse.new(#resources, <more meta information of the page>)
The problem is that when I use this, everything works well but the resources are not rendered using ActiveRecordSerializer, but a default serializer. I suspect that this is happening because PaginatedResponse does not extend ActiveRecord.
Any clue how can I solve this?
Rails 4 has introduced a new concept jbuilder by default. So just create index.json.jbuilder and put the json syntex based code. Just refer the default scaffold index json jbuilder below,
json.array!(#users) do |user|
json.extract! user, :name, :email, :phone, :native_place
json.url user_url(user, format: :json)
end
This is for rendering all users with his name, phone, native_place.
So remove the line
render json: #resources
from your code and implement the the new jbuilder concept.
The solution was including ActiveModel::SerializerSupport in PaginatedResponse to indicate ActiveRecordSerializer that a serializer should be used.

respond_to with custom format aliasing json format, is this possible?

I have a situation where I'm returning json objects to my application which are built from YML files. Because to parse the yml file and return it as json I always have to do something like this:
format.json { render json: YAML.load(render_to_string :file => File.join(Rails.root,'app','views','home','icons.yml.erb'), :layout => false ) }
I would like to make this operation shorter, by creating a custom format that (however) result in a json, so I don't want to create a new mime type.
My idea is to write:
format.myformat
Which will automatically search for myaction.myformat.erb inside views/mycontroller directory, and will automatically parse the yaml file returning it as a json object.
Is this possible? If yes, how can I eventually do this?
Edit 1:
I found an important suggestion in config/mime_types.rb:
Mime::Type.register_alias "text/html", :iphone
So I can alias a mime type, now the biggest problem is: how to define the default render action for a given format, like format.html does?
If I write
format.html
current_action.html.erb will be automatically rendered, how can I choose the correct method to render a custom format?
Edit 2:
I managed to create this code (inside a controller, through some helper methods I built):
def icons
respond_to do |format|
format.extjson { render_to_extjson }
end
end
Is possible to make rails understand that if I write:
def icons
respond_to do |format|
format.extjson
end
end
it has to do:
format.extjson { render_to_extjson }
by default?
You could do something like:
respond_to do |format|
format.html { #foo = Foo.all(:limit => 10) }
format.any(:atom, :rss) { #foo = Foo.all }
end
A longer post going into the guts of the render actions can be found here: http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to/
While Josh's answer is a valid one, I would rather see your parsing code wrapped up into an object. If you put that object into app/models, it'll be testable and you can always verify any change to the logic with a test suite.
Another upside to this is that you can re-use the format.json call and make you controller that much simpler.
This is not doable at the moment, I read a lot of rails sources and there isn't a way to access that method, so isn't possible to customize it.
I'll write a rails plugin to support this and eventually I'll post it here, but for sure the answer actually is: this can't be done.

Rails 3 rendering template missing without file ending

I have an action in my controller as below:
def show
#post = Post.find_by_setitle(params[:setitle])
if !#post
render 'error_pages/404'
return
end
respond_to do |format|
format.html
end
end
If the render error_pages/404 I get a template missing. Switching it to render error_pages/404.haml.html works fine.
Why is this?
N.B. There is no actual error_pages controller or model. Just a convenient place to keep them.
Edit: I'm using mongoid and hence don't have access to ActiveRecord. Controller base can't be looking for a particular ActiveRecord exception?
From the documentation
The render method can also use a view that’s entirely outside of your application (perhaps you’re sharing views between two Rails applications):
Rails determines that this is a file render because of the leading slash character. To be explicit, you can use the :file option (which was required on Rails 2.2 and earlier):
You need either to pass the :file option, or to start the location string with a slash. Alternatively, you could use the Rails functionality to rescue from errors, and recover from ActiveRecord::RecordNotFound with a 404. See this post for details.
You should probably use render :template => 'error_pages/404'.
I think Rails is looking for a partial called _404.
Try it out 1:
render 'error_pages/404' (and name the file _404.html.erb)
Try it out 2:
render :template => 'error_pages/404' (and name the file 404.html.erb i.e. no leading underscore)

Resources