[英]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.