简体   繁体   English

从has_many关联中加载Ajax实例

[英]Ajax load instances from a has_many association

I have a scenario where a Game has many Achievements . 我有一个Game有很多Achievements的场景。 Setup as a todo app I have a form where users create a list of achievements they would like to complete. 设置为待办事项应用程序我有一个表单,用户可以在其中创建他们想要完成的成就列表。 They first choose the game from and from their the achievements for that game populate below. 他们首先从下面填充的游戏成就中选择游戏。

The challenge I'm facing is asynchronously gathering the achievements that belong_to that particular game. 我面临的挑战是异步收集belong_to该特定游戏的成就。 So if the user selects Halo then all the achievements would load from that select box's change event. 因此,如果用户选择Halo,那么所有成就都会从该选择框的change事件加载。

I have a general idea on writing the change event but was wondering how the ajax would be written for this to work to load the achievements. 我对编写change事件有一个总体思路,但想知道如何编写ajax以使其能够加载成就。

Models 楷模

class User
  has_many :tasks
end

class Task < ActiveRecord::Base
  has_many_and_belongs_to_many :achievements
  belongs_to :user
  belongs_to :game
end

class Game < ActiveRecord::Base
  has_many :tasks
  has_many :achievements
end

class Achievements < ActiveRecord::Base
  has_and_belongs_to_many :tasks
  belongs_to :game
end

Task Form 任务表

<%= simple_form_for(@task) do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.input :title %>
    <%= f.input :game_id, as: :select, collection: @games, include_blank: "Select a game", input_html: {class: "game-select"} %>
    <%= f.input :achievement_ids, as: :select, collection: @achievements, include_blank: "Select achievements", input_html: {multiple: true, class: "achievement-select"} %>
  </div>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>
<% end %>

JS JS

$(function() {
  $(".game-select").on("change", function() {
    // Load and insert achievements for game into ".achievement-select" select box
  });
});

Achievements Controller 成就负责人

class AchievementsController < ApplicationController
  def index
    @achievements = Achievement.all
  end

  def show
    @achievement = Achievement.find(params[:id])
  end
end

The select options should, in their value attribute, store the game id. 选择选项应在其value属性中存储游戏ID。 Build this like 建立像这样

<% game_options = [["",""]] + Game.order("name").all.collect{|game| [game.name, game.id]} %>
<%= select_tag "game_id", options_for_select(game_options), :class => "game-select" %>

The game_options variable could be moved into a class method in the Game class, eg called "select_options" or something. 可以将game_options变量移至Game类中的类方法中,例如,称为“ select_options”之类的东西。

Now when this changes, you can read the game id out of it's value. 现在,当这种情况改变时,您可以从游戏的值中读取游戏ID。 You could do it like so: 您可以这样做:

$(function() {

  $(".game-select").on("change", function() {
    if($(this).val() != ""){
      $.getJSON("/achievements", {"game_id": $(this).val()})
        .done(function(data){
          $.each( data.items, function( i, item ) {
            //do something with the json for this achievement
          });
        });
    }
  });

});

EDIT: I made the view code use the more modern rails find syntax, and also made the javascript not do anything if the select is changed to the blank option. 编辑:我使视图代码使用更现代的rails find语法,并且如果将select更改为blank选项,还使javascript不执行任何操作。

EDIT2: like i said, if we want to send params[:game_id], and get back all the json data just for achievements with that game id, then the controller will need to take those params into account. EDIT2:就像我说的那样,如果我们要发送params [:game_id],并只获取具有该游戏ID的成就的所有json数据,则控制器将需要考虑这些参数。 There's various ways you could do this, some dryer than others. 您可以通过多种方式做到这一点,有些干衣机比其他干衣机。 I'm going to do the simplest possible thing, rather than the most extensible thing. 我将做最简单的事情,而不是最可扩展的事情。

#in Achievements controller
def index
  if params[:game_id]
    @achievements = Achievement.where(:game_id => params[:game_id]).all
  else
    @achievements = Achievement.all
  end
  respond_to do |format|
    format.html { render :action => "index"}
    format.json { render :json => @achievements.to_json }
  end
end

So ...such as we have 'simple_form_for(@task)', it is view form for Task Model. 所以...例如我们有'simple_form_for(@task)',它是任务模型的视图形式。

In my opinion, You could write next in Task Model: 我认为,接下来可以在任务模型中编写:

class Task < ActiveRecord::Base
  belongs_to :user
  belongs_to :game
  has_many :achievements, through: :game
end

and after this in TasksController You could use: (updated) 然后在TasksController中可以使用:(更新)

def update
  @task = Task.find(params[:id])    
  @achievements = @task.achievements
  @achievement_ids = @achievements.map { |a| [a.name, a.id] }
end

for use into form. 用于形式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM