Rails 4和Jbuilder,如何为一组模型调用to_builder方法

时间:2015-10-28 21:04:16

标签: ruby-on-rails jbuilder

我在to_builder模型上定义了Location方法。这是方法:

class Location < ActiveRecord::Base
  def to_builder
    Jbuilder.new do |json|
      json.(self, :id, :latitude, :longitude, :name, :description)
    end
  end
end

如果我从数据库中选择Location,我可以将其转换为JSON,如下所示:

Location.first.to_builder.target!

这很有效。如何为Location模型集合做同样的事情?例如,如果我通过关系(Area has_many :locations)从数据库中获取多个。

locations = Area.first.locations

有没有一种简单的方法可以使用Jbuilder将locations转换为json?我目前的解决方案是定义一个帮助方法,将模型或集合转换为json。例如:

def json_for(object)
  if object.is_a? ActiveRecord::Relation
    a = object.map do |o|
      o.to_builder.target!
    end
    "[#{a.join(',')}]".html_safe
  else
    object.to_builder.target!.html_safe
  end
end

然后我会打电话给json_for locations。但这并不是处理它的正确方法。

更新

我还没有找到一个很好的解决方案。目前我正在使用我编写的帮助器来呈现JSON视图的内容。这是助手的样子:

def json_for(view, locals_hash = {})
  render(template: view, formats: [:json], locals: locals_hash).html_safe
end

然后,我在视图中使用这样的帮助器,传入视图中使用的任何变量:

<%= json_for 'locations/index', { locations: @locations } %>

我也有部分帮手:

def json_for_partial(partial, locals_hash = {})
  render(partial: partial, formats: [:json], locals: locals_hash).html_safe
end

总而言之,我根本没有使用to_builder方法。相反,我正在创建实际的jbuilder视图文件,然后使用帮助器在我的应用程序中的任何地方呈现它们生成的JSON。

1 个答案:

答案 0 :(得分:0)

您可以将集合呈现为一个利用to_builder覆盖的数组,如下所示:

public class AlarmReceiver extends BroadcastReceiver {

  @Override public void onReceive(
      final Context context,
      final Intent intent) {

    // Sanity check on the received intent.
    if ((intent == null) || (intent.getAction() == null)) {
      Log.v(TAG, "Alarm received but the extra doesn't contain valid informations");
      return;
    }

      if (!validAlarmReceived(alarm)) {
        //try to set alarm again, use the same request code to cancel the pending intent
        AlarmManager.rescheduleCurrentAlarm(alarm, context);
        return;
      }
    }
  }

  /**
   * Sanity check to see if alarm has been prematurely triggered
   * due to odd behavior with PowerSave on some devices.
   */
  private boolean validAlarmReceived(
      final Alarm alarm) {

    if (alarm.isSnoozed()) {
      //avoid time check for snoozed alarms
      return true;
    }

    final long alarmMillis = alarm.getCurrentTriggerTime();
    final long currentMillis = System.currentTimeMillis();
    final long difference = (currentMillis - alarmMillis);
    final long THRESHOLD = TimeUnit.MINUTES.toMillis(1);

    // Allow the notification to show under the following scenarios:
    // 1. The alarm triggered late (i.e. current millis > alarm millis)
    // 2. OR the alarm triggered within the threshold value
    if (difference > 0 || Math.abs(difference) < THRESHOLD) {
      return true;

    } else {
      // otherwise reschedule the alarm
      return false;
    }
  }
}

https://github.com/rails/jbuilder/issues/139

https://github.com/rails/jbuilder/issues/75