Rails 4 — Как заполнить пользовательскую модель из JSON API?

Во-первых, я новичок в рельсах, поэтому извините, если есть что-то, что я не понимаю правильно. Мне интересно, как я могу заполнить модель выборкой данных через API.

Контекст: я использую аутентификацию OAuth2 с omniauth/devise.

На стороне клиента моего пользовательского контроллера (напротив провайдера) я извлек всех пользователей, которые хотя бы раз вошли в систему, это «клиентское приложение», и я хочу их отобразить. Очевидно, каждый раз, когда новый пользователь входит в клиентское приложение, я не сохраняю всю его информацию в клиентской базе данных, чтобы избежать дублирования. Все, что я храню, это user_id вместе с его токеном доступа.

Поэтому я подумал, что после извлечения всех данных пользователей я мог бы заполнить их пользовательской моделью, прежде чем передавать их в представление. Как лучше всего это сделать? Я изучал именованную область, но мне не ясно, как применить ее к моему конкретному сценарию. Например, было бы здорово иметь возможность заполнять всех пользователей в моей модели, используя что-то вроде этого:

# ApiRequest is a container class for HTTParty
get = ApiRequest.new.get_users(User.all) // here "get" is a JSON array of all users data
response = get.parsed_response['users']
User.populate(response).all # would something like this possible? If yes, is Named Scope the appropriate solution?

Заранее большое спасибо за помощь.


person user3099958    schedule 13.12.2013    source источник
comment
Именованная область — это всего лишь ярлык для различных условий запроса, что-то вроде: scope :only_active, where(active: true) используется при вызове MyModel.only_active, который возвращает список объектов MyModel, соответствующих условию active = true. Это не имеет ничего общего с присвоением атрибутов.   -  person MrYoshiji    schedule 20.12.2013


Ответы (4)


Предположим, что response — это массив хэшей атрибутов:

[{'id' => 1, 'name' => 'Dave'}, {'id' => 2, 'name' => 'Bill'}]

Вы можете сопоставить это с массивом User с помощью:

users = response.map{|h| User.new(h)}
person pguardiario    schedule 17.12.2013
comment
+1 мой ответ не учитывал, что данные содержат несколько пользователей, теперь исправлено, вдохновленное этим. - person fguillen; 17.12.2013
comment
+1 && Я бы добавил сюда функцию безопасности, поскольку она использует API, который может привести к неправильному вводу данных пользователем: users = response.map{ |h| User.new( h.slice(*User.column_names) ) } -> Это разрешает только атрибуты модели пользователя. - person MrYoshiji; 20.12.2013

Если вы не хотите трогать базу данных, а также хотите заполнить виртуальные атрибуты, я думаю, что единственный способ - реализовать свой собственный метод populate:

# The User class
def self.populate(data)
  data.map do |user_json|
    user = User.find(user_json[:id])
    user.assign_attributes(user_json)
    user
  end
end

Советы по безопасности см. в assign_attributes документации.

person fguillen    schedule 16.12.2013
comment
Спасибо. Быстрый вопрос, в чем смысл массива, поскольку он будет переопределяться при каждом вызове метода заполнения? - person user3099958; 16.12.2013
comment
Пользователи заполняются временно, возвращается массив с временно заполненными пользователями, поэтому вы можете использовать их в представлении. assign_attributes не касается базы данных. - person fguillen; 17.12.2013
comment
Я собираюсь предположить, что вы имели в виду temporarily и что вы не предлагаете никакого решения для путешествий во времени :) - person pguardiario; 17.12.2013

Самый простой способ — использовать active_resource http://railscasts.com/episodes/94-activeresource-basics< /а>

P.S. В Rails 4 это гем https://github.com/rails/activeresource.

person itsnikolay    schedule 17.12.2013

Я не нахожу прямого способа сделать это, самое короткое решение, которое я могу предложить, — использовать метод update:

ids = get.map{ |e| e["id"] }
User.update(ids, get)
person fguillen    schedule 13.12.2013
comment
Спасибо. Проблема в том, что я хочу заполнить виртуальные атрибуты, которые не требуют изменения или обновления базы данных. - person user3099958; 16.12.2013