В проекте Rails 2.2 я предлагаю пользователям собрать список проектов в объект портфолио (например: PortfolioHasManyProjects). На странице находится форма Rails для обычного текста, заголовков и т. д., А также 2 сортируемых списка; списки используются для перетаскивания проектов из глобального списка проектов в список проектов портфолио.
Это похоже на то, что сделано здесь: http://ui.jquery.com/latest/demos/functional/#ui.sortable.
У меня есть список портфолио (#drag_list), который обновляется при изменении и отправляет свои сериализованные данные через вызов AJAX. Это делается в файле application.js:
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
jQuery.fn.submitDragWithAjax = function() {
this.submit(function() {
$.post(this.action, $("#drag_list").sortable('serialize'), null, "script");
return false;
})
return this;
};
$(document).ajaxSend(function(event, request, settings) {
if (typeof(AUTH_TOKEN) == "undefined") return;
// settings.data is a serialized string like "foo=bar&baz=boink" (or null)
settings.data = settings.data || "";
settings.data += (settings.data ? "&" : "") + "authenticity_token = " + encodeURIComponent(AUTH_TOKEN);
});
/-------------------------------------------/
$(document).ready(function(){
$(".ajax_drag").submitDragWithAjax();
$("#drag_list").sortable({
placeholder: "ui-selected",
revert: true,
connectWith:["#add_list"],
update : function () {
$("#drag_list").submit();
}
});
$("#add_list").sortable({
placeholder: "ui-selected",
revert: true,
connectWith:["#drag_list"]
});
Здесь все стало сложно. Я не знал, как поступить с сериализованными данными и отправить их вместе с формой в контроллер в файле new.html.erb. Итак, что я сделал, так это то, что new.js.erb вставил скрытые поля формы в new.html.erb с данными, которые я извлекал в контроллер.
вот новый.js.erb:
$("#projects").html("");
<% r = params[:proj] %>
<% order=1 %>
<% for i in r %>
$("#projects").append("<input type=hidden name=proj[<%=order%>] value=<%=i%> />");
<% order=order+1 %>
<% end %>
который редактирует new.html.erb:
<h1>New portfolio</h1>
<h2>The List</h2>
<div class = "list_box">
<h3>All Available Projects</h3>
<%= render :partial => "projects/add_list" %>
</div>
<div class = "list_box">
<h3>Projects currently in your new portfolio</h3>
<%= render :partial => "projects/drag_list" %>
</div>
<div style = "clear:both"></div>
<br/>
<br/>
<h2>Portfolio details</h2>
<% form_for(@portfolio) do |f| %>
<%= f.error_messages %>
<h3>Portfolio Name</h3>
<p>
<%= f.text_field :name %>
</p>
<h3>URL</h3>
<p>
<%= f.text_field :url %>
</p>
<h3>Details</h3>
<p>
<%= f.text_area :details %>
</p>
<p>
<div id = "projects">
<input type = "hidden" name = "proj" value = "" />
</div>
<%= f.submit "Create" %>
</p>
<% end %>
Затем форма отправляется методу create в контроллере портфеля:
def new
@projects = Project.find(:all)
@portfolio = Portfolio.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @portfolio }
format.js
end
end
def create
@portfolio = Portfolio.new(params[:portfolio])
proj_ids = params[:proj]
@portfolio.projects = []
@portfolio.save
proj_ids.each {|key, value| puts "Key:#{key} , Value:#{value} " }
proj_ids.each_value {|value| @portfolio.projects << Project.find_by_id(value) }
respond_to do |format|
if @portfolio.save
flash[:notice] = 'Portfolio was successfully created.'
format.html { render :action => "index" }
format.xml { render :xml => @portfolio, :status => :created, :location => @portfolio }
else
format.html { render :action => "new" }
format.xml { render :xml => @portfolio.errors, :status => :unprocessable_entity }
end
end
end
Итак, наконец, мой вопрос:
Это правильный способ сделать это? По какой-то причине мне кажется, что это не так, в основном потому, что все остальное делать в Rails казалось намного проще и интуитивно понятным. Это работает, но добираться до этого было адом. Должен быть более способ элегантный отправки сериализованных данных в контроллер через вызовы AJAX.
Как мне вызвать разные действия AJAX на одной странице? Допустим, у меня был вызов AJAX с возможностью сортировки и автозаполнения, могу ли я использовать sortable.js.erb и autocomplete.js.erb и вызывать их из любого файла? Я не уверен, как настроить контроллеры на это.
Я не понимаю вопроса (и, к сожалению, есть глупое ограничение на количество повторений при комментировании, поэтому я отправлю это как ответ). Почему вы вставляете скрытые поля? Разве нельзя просто использовать идентификаторы в тегах & lt; li & gt; items, а затем вызвать toArray для сортируемого, а не сериализованного)? Вы можете добавить эту информацию в одно скрытое поле формы до ее отправки. Это предотвратит все вызовы Ajax после обновления списка проектов.

Это хорошее решение, если вы используете jQuery.
Из связанного блога:
I just wrote some sortable code for a Rails/jQuery app and figured I would blog just how little code it takes, and also the single MySQL query I used on the backend.
Вот мое решение, основанное на статье, упомянутой Сильвиу. Я сортирую части, принадлежащие урокам, отсюда и включение lessonID.
Это в представлении - я использую HAML, поэтому вам придется преобразовать его в erb.
#sorter
- @lesson.parts.each do |part|
%div[part] <- HAML rocks - this constructs a div <div id = "the_part_id" class = "part">
= part_screenshot part, :tiny
= part.swf_asset.filename
Js выглядит так:
$('#sorter').sortable({items:'.part', containment:'parent', axis:'y', update: function() {
$.post('/admin/lessons/' + LessonId + '/parts/sort', '_method=post&authenticity_token='+ AUTH_TOKEN+'&'+$(this).sortable('serialize'));
$('#sorter').effect("highlight");
}});
и вот метод, который вызывается в PartsController:
def sort
load_lesson
part_positions = params[:part].to_a
@parts.each_with_index do |part, i|
part.position = part_positions.index(part.id.to_s) + 1
part.save
end
render :text => 'ok'
конец
def load_lesson
@lesson = Lesson.find(params[:lesson_id])
@parts = @lesson.parts
конец
Требуется некоторая работа по предоставлению обратной связи пользователю, но помогает мне.
Вот мой взгляд на это: awesomeful.net/posts/47-sortable-lists-with-jquery-in-rails