2015-10-23 2 views
2

В моей модели у меня есть метод работает as_json следующим образом:Как правильно совместить два метода as_json с одним?

def as_json(options = {}) 
    super(options.merge(include: [:user, comments: {include: :user}])) 
    end 

Этот метод предназначен для пользователей, в том числе в комментариях.

Теперь мне нужно добавить почти то же самое, в одной и той же модели для ответов:

def as_json(options = {}) 
    super(options.merge(include: [:user, answers: {include: :user}])) 
    end 

Как объединить эти два метода as_json, так что у меня есть один метод as_json?

Не смейтесь, но я борюсь с этим в течение 3 дней.

ответ

3

Это одна из причин, почему вы не должны использовать встроенный to_json для seria lize ActiveRecord.

Вместо этого вы должны делегировать задачу другому объекту с именем serializer. Используя сериализатор, вы можете иметь представления без отображения (сериализации) одного и того же объекта (полезно, если объект может иметь разные варианты, такие как с комментариями и т. Д.) И разделение проблем.

Создание собственного сериалайзер глупо просто, так просто, как

class ModelWithCommentsSerializer 
    def initialize(object) 
    @object = object 
    end 

    def as_json 
    @object.as_json(include: [:user, comments: {include: :user}])) 
    end 
end 

class ModelWithAnswersSerializer 
    def initialize(object) 
    @object = object 
    end 

    def as_json 
    @object.as_json(include: [:user, answers: {include: :user}])) 
    end 
end 

Конечно, это всего лишь пример. Вы можете извлечь эту функцию, чтобы избежать дублирования.

Есть также драгоценные камни, такие как ActiveModelSerializers, который обеспечивает эту функцию, однако я предпочитаю избегать их, поскольку они, как правило, обеспечивают намного больше того, что действительно нужно большинству пользователей.

+0

Правильно ли это назвать эту модель сериализатора в вашем примере выше? 'ModelWithCommentsSerializer.new (my_users_instance)' – BigRon

+0

'ModelWithCommentsSerializer.new (my_users_instance) .as_json' или это зависит от того, как вы определяете свой сериализатор. –

+0

ОК, я застрял в: «Создание собственного сериализатора просто глупо». где должен быть указан этот класс сериализатора из вашего примера? Если бы вы могли дать мне ссылку, это было бы неплохо. Я только нахожу ActiveModelSerializers. –

0
def as_json(other_arg, options = {}) 
    as_json(options.merge(include: [:user, other_arg: {include: :user}])) 
end 

И тогда вы можете позвонить:

MyModel.as_json(:comments) 
MyModel.as_json(:answers) 
+0

Где я могу это назвать? –

+0

можно назвать Model.as_json (: comments) или Model.as_json (: ответы), но я думаю, что решение от Rich Peck будет лучше –

0

Почему вы пытаетесь переопределить функциональность ядра Rails - не хорошая практика, если это абсолютно необходимо.

-

This говорит следующее:

Чтобы включить ассоциации использовать: включают:

user.as_json(include: :posts) 
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16, 
#  "created_at" => "2006/08/01", "awesome" => true, 
#  "posts" => [ { "id" => 1, "author_id" => 1, "title" => "Welcome to the weblog" }, 
#     { "id" => 2, "author_id" => 1, "title" => "So I was thinking" } ] } 

Вы могли бы назвать:

@answers.as_json(include :users) 

-

Ohhhhhhhh:

Второй уровень и выше ассоциации порядка работы, а также:

user.as_json(include: { posts: { 
         include: { comments: { 
             only: :body } }, 
         only: :title } }) 
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16, 
#  "created_at" => "2006/08/01", "awesome" => true, 
#  "posts" => [ { "comments" => [ { "body" => "1st post!" }, { "body" => "Second!" } ], 
#      "title" => "Welcome to the weblog" }, 
#     { "comments" => [ { "body" => "Don't think too hard" } ], 
#      "title" => "So I was thinking" } ] } 

Так выглядит, как вы могли бы назвать:

@answers.to_json(include: comments: { include: :users }) 
Смежные вопросы