in rails 4, I can not figure out how to fetch model and associated models together.
For example, I have a User model which has_many Message
The following code work properly.
#user = User.find 29, include: :messages
#messages = #user.messages
However, when I try to return #user with #messages in json
render :json #user
The returned result does not contain #messages, only the #user data is returned.
One workaround I can do is to construct a hash with
{user: #user, messages: #messages}
But the problem is messages are not nested or associated to user.
Is there a activemodel/activerecord buildin method to render associated data in a easier way?
as always, the documentation on the rails side is pretty bad. what you need to do is call either call to_json with options or override the models to_json method: http://apidock.com/rails/ActiveRecord/Serialization/to_json
Related
when my model is in a particular state, I need to render it with hiding some specific data.
my model knows the data I need to hide through a has_many relationship.
my idea is to retrieve the model, replace the content of the has_many relationship with a dummy, non persisted object, and then render it, without saving the model.
So that when rendering the data shown will be from the dummy object.
here's my code:
the model:
class Car < ActiveRecord::Base
....
has_many :owners
....
end
in the controller:
#car.owners = [ Owner.new(name: "", phone: "") ] if hide_owner?
it actually attempts to do the update on the DB and fails with this error:
*** ActiveRecord::RecordNotSaved Exception: Failed to replace owners because one or more of the new records could not be saved.
It feels like this would be easier if you were accessing a Decorator class instead of the model directly.
Then in the decorator you could define:
def owners
if hide_owner?
[ Owner.new(name: "", phone: "") ]
else
object.owners
end
end
... where object is the instance of Car.
Maybe look at the Draper gem or others.
I am working on a backend of an application written in Sinatra.
It has a route "/notifications"
which renders all the notifications in JSON.
I want to change the json structure and wrote some custom serializer and it is failing now.
the error i get is
"{"message":"undefined method `read_attribute_for_serialization' for nil:NilClass"}"
I have a file called webservice/notification.rb
which selects a notification serializer.
the code is something like this
serializer = NotificationSerializer
json serialize(notifications, root: :notifications, each_serializer: serializer)
The NotificationSerializer is something like this.
class NotificationSerializer < Serializer
attributes :id, :tag, :event, :time, :read
has_one :reference, polymorphic: true, include: true
The reference here can be a lot of things.
the notification model defines reference as
def reference
company || contact || deal || invitation || meeting || todo || reference_email || reference_user ||
contact_import_job
end
now all of these models in reference have there Serializer implements in directory Serializer/*
I want to make custom Serializers for all of these which will render limited information.
how can I call my custom Serializer for things inside reference.
I wrote a custom serializer for notifications and called it like this inside my refernce function and it worked.
...|| UserNotificationSerializer.new(reference_user) || ...
but if i do the same for my other models i get the error given above.
what would be the correct way to call my custom serializers.
A good way to do it is to write an instance method on the model:
class Notification < ActiveRecord::Base
def public_attributes # or call it whatever
attributes_hash = attributes
# in activerecord, the attributes method turns a model instance into a hash
# do some modifications to the hash here
return attributes_hash
end
end
then say you're returning json in a controller:
get '/some_route' do
#notifications = Notification.all # or whatever
serialized_notifications = #notifications.map(&:public_attributes)
# For a single record, you could do #notification.public_attributes
json_data = serialized_notifications.to_json # a serialized array of hashes
content_type :json
return json_data
end
Consider the follow:
#posts = Post.all
render json: { success: true, data: #posts }
Now, each post will have parameters that are not required to be sent in this particular scenario (although it'll be in others), so I'd like to restrict the parameters sent and I thought maybe I could use map like so:
#posts = Post.all.map { |user| [user.email, user.first_name, user.last_name] }
render json: { success: true, data: #posts }
As you can imagine that doesn't work. Its very likely I'm using - or intending to use - map in a completely incorrect way and I'd appreciate your comments on how to achieve the above.
Thanks in advance!
You can make use of Hash#slice method to do something like:
#posts = Post.all.map { |user| user.as_json.slice("email", "first_name", "last_name") }
The #posts will be an array of Hash in this case, with each hash containing three key-value pairs.
It may be more appropriate to use a serializer.
You'll have to install the active_model_serializers gem first.
An example serializer for your Post controller would be:
class PostSerializer < ActiveModel::Serializer
attributes :email,
:first_name,
:last_name,
end
You'll use the serializer in this manner (I'm assuming you'd call it in the index method):
def index
posts = Mentor.all
render(
json: ActiveModel::ArraySerializer.new(
posts,
each_serializer: PostSerializer,
root: 'posts'
)
)
end
I am trying to store my ruby object in couchdb with couchrest. I am extending my model from CouchRest::Model::Base But still i am unable to see the changes in db.
I've defined Server as CouchRest.new also mentioned in model to use_database 'players'
# Controller Method
get '/new/:name' do
DB = SERVER.database!('players')
#new_player = Player.new(params['name'])
#new_player.create
"success: #{#new_player.persisted?}" #shows true
# Model
class Player < CouchRest::Model::Base
use_database 'players'
property :name ,String
timestamps!
def initialize(arg)
#name=arg
end
end
How To Persist the object?
How can i retreive all persisted objects?
Is there any simple applications which i can refer to?
I have two Rails apps, one client using ActiveResource and one service. I am testing the following command via the console:
User.find(:all, :params => {:email_address => "myemail#domain.com"})
I get back all the records in my user table and not just the one specified in my email parameter.
When I go look at the log for my service app it shows as follows
Started GET "/users.json?email_address=myemail%40domain.com" for 127.0.0.1 at 2011-12-29 11:29:06 -0600
(0.4ms) SHOW search_path
Processing by UsersController#index as JSON
Parameters: {"email_address"=>"myemail#domain.com"}
User Load (0.7ms) SELECT "users".* FROM "users"
Completed 200 OK in 40ms (Views: 35.7ms | ActiveRecord: 3.3ms)
My parameter was not included in the SQL statement.
Any insight?
Based on your comment on the original question, your controller still looks like this:
class UsersController < ActionController::Base
def index
#users = User.all
respond_to do |format|
format.json { render json: #users }
end
end
#other methods down here
end
But in order to get your index view to render just the ones that match the email, you need to update the index method to:
class UsersController < ActionController::Base
def index
#users = User.find_all_by_email_address(email_address)
respond_to do |format|
format.json { render json: #users }
end
end
#other methods down here
end
Conditions are passed to ActiveRecord find method via :conditions option and not :params. So your find call should be like that:
User.find(:all, :conditions => { :email_address => "myemail#domain.com" })
or in more Rails 3 style:
User.where(:email_address => "myemail#domain.com").all
You can find full list of available parameters for find method in docs.