#ruby-on-rails
#ruby-on-rails
Вопрос:
Я новичок в ruby, мне нужно создать форму для регистрации пользователя, и пользователь должен иметь возможность регистрировать неограниченное количество друзей. Хочу сделать это вот так: начните с одной формы и add
кнопки. Если пользователь нажимает на add
кнопку, первая форма копируется и так далее. В итоге остается только одна кнопка отправки, которая отправляет все формы. Пытаюсь это сделать, но не могу понять, как передать неограниченное количество объектов в форму. Теперь просто передаем один объект:
participation_forms_controller.rb
:
class ParticipationFormsController < ApplicationController
def new
@participation_form = ParticipationForm.new
end
...
Проблема в том, что мне нужно создать некоторое количество ParticipationForm
объектов, но фактическое количество этих объектов определяет только пользователь. И, как я понимаю, мне нужно передать такое же количество объектов из ruby controller в мой html. Но я не знаю, сколько, поэтому я не могу выполнить какой-то цикл в контроллере подобным образом:
class ParticipationFormsController < ApplicationController
def new
@participation_forms = []
<dont_know_how_many>.times do
@participation_forms << ParticipationForm.new
end
end
Я думал о каком-то грязном взломе: скопируйте все данные из других форм в первую, а затем отправьте только первую. Но я хочу сделать это хорошим способом, как это делают обычные программисты. Что я могу сделать, если бы я использовал python
: просто создайте одну форму с именами полей, такими как username_1
, userdata_1
, username_2
, userdata_2
и так далее, затем просто проанализируйте их на серверной части. Но ruby несколько строг в отношении того, какие параметры я могу передавать контроллеру, я должен предопределять их, поэтому не могу выполнить этот трюк? Что такое мой create
контроллер:
def create
@participation_form = ParticipationForm.new(article_params)
@participation_form.save
render 'new'
end
private
def article_params
params.require(:participation_form).permit(
:name, :telephone, :email, :post, :image)
end
Итак, как я могу передать туда что-то вроде name_999
? Ни в коем случае, ruby является строгим.
Было бы здорово, если бы в ruby я мог использовать regexp для разрешения набора полей, просто мой фантастический код:
def article_params
params.require(:participation_form).permit(
:re.match('^name_d*$'))
end
Если это будет реально, я могу использовать одну форму для этой задачи.
фрагмент кода интерфейса «чего-я-хочу»
/* Latest compiled and minified JavaScript included as External Resource */jQuery(document).ready(function() {
var addFriendForm = function() {
$('.button-group__add-friend-btn').click(function() {
forms = $(".form-signin");
var first = forms.first();
var first_clone = first.clone();
first_clone_children = first_clone.children();
$(first_clone_children).each(function() {
if ($(this).hasClass('form-signin__file-upload')) {
file_upload_children = $(this).children();
file_upload_children.each(function() {
this.value = '';
});
}
else {
this.value = '';
}
});
var last = forms.last();
first_clone.insertAfter(last);
$('<hr class="container__hr">').insertAfter(last);
changeRegBtnText();
addDelBtn();
});
};
var changeRegBtnText = function(back_to_one=false) {
var one = 'register'
var plural = 'register with friends';
var btn = $('.button-group__add-reg-btn');
if (btn.text() == one) {
btn.html(plural);
}
else if (back_to_one) {
btn.html(one);
}
};
var addDelBtn = function() {
var del_btn = $("#friend_del_btn");
if (del_btn.hasClass("button-group__del-friend-btn_disabled")) {
del_btn.removeClass("button-group__del-friend-btn_disabled");
del_btn.addClass("button-group__del-friend-btn_active");
}
};
var deleteFriendForm = function() {
$('#friend_del_btn').click(function() {
forms = $(".form-signin");
hrs = $('.container__hr');
var last_fieldset = forms.last();
last_fieldset.remove();
var last_hr = hrs.last();
last_hr.remove();
if ($(".form-signin").length == 1) {
changeRegBtnText(back_to_one=true);
$("#friend_del_btn").addClass("button-group__del-friend-btn_disabled");
}
});
};
var submitForms = function() {
$(".button-group__add-reg-btn").on("click", function(e) {
$(".form-signin").each(function(){
$(this).trigger("submit");
console.log('submit');
});
});
}
addFriendForm();
deleteFriendForm();
submitForms();
});
.form-control {
margin-top: 10px;
margin-bottom: 10px;
height: auto;
padding: 10px;
font-size: 16px;
}
.form-signin {
max-width: 330px;
padding: 15px;
margin: 0 auto;
}
.container__hr {
background-color: #A9A9A9;
height: 1px;
width: 300px;
}
.form-signin__file-upload {
position: relative;
overflow: hidden;
margin-bottom: 10px;
height: 35px;
width: 100%;
}
.form-signin__file-upload-filename {
float: left;
color: #222;
margin-top: -3px;
}
.form-signin__file-upload-input {
position: absolute;
top: 0;
right: 0;
margin: 0;
padding: 0;
cursor: pointer;
opacity: 0;
filter: alpha(opacity=0);
}
.form-signin__file-upload-span {
line-height: 1.42;
color: black;
}
.button-group {
margin-left: auto;
margin-right: auto;
max-width: 330px;
padding-left: 15px;
padding-right: 15px;
}
.button-group__add-friend-btn,
.button-group__add-reg-btn {
margin-top: 10px;
margin-bottom: 10px !important;
width: 100%;
}
.button-group__del-friend-btn_disabled {
display: none !important;
}
.button-group__del-friend-btn_active {
margin-top: 10px;
margin-bottom: 10px !important;
width: 100%;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<h3 class="text-center">Register to conference</h3>
<form class="form-signin">
<input type="text" name="[participation_form]name" class="form-control" placeholder="Имя" required autofocus>
<input type="tel" name="[participation_form]telephone" class="form-control" placeholder="Телефон" required>
<input type="email" name="[participation_form]email" class="form-control" placeholder="Електропочта" required>
<input type="text" name="[participation_form]post" class="form-control" placeholder="Должность" required>
<div class="form-signin__file-upload btn btn-info" disabled="disabled">
<input class="form-signin__file-upload-filename">
<input type="file" name="[participation_form]image" class="form-control form-signin__file-upload-input" required>
<span class="form-signin__file-upload-span">аватар</span>
</div>
</form>
<div class="text-center button-group">
<button type="button" class="btn btn-default button-group__add-friend-btn">
<span class="glyphicon glyphicon-plus"></span> add friend
</button>
<button type="button" id="friend_del_btn" class="btn btn-default button-group__del-friend-btn_disabled">
<span class="glyphicon glyphicon-remove"></span> del friend
</button>
<button class="btn btn-lg btn-primary btn-block button-group__add-reg-btn" type="submit">register</button>
</div>
Комментарии:
1. Круто. итак … не могли бы вы, пожалуйста, включить свой код в свой вопрос? jsfiddle — это потрясающе, и здорово, что вы его предоставили, но мы также хотим, чтобы наши вопросы Stack Overflow выдержали испытание временем, а ссылки на jsfiddle довольно быстро устаревают. Во-вторых: с какой проблемой / error / problem вы столкнулись? т. е. что вы наблюдаете, и что вы ожидаете наблюдать вместо этого? Как вы думаете, почему вам нужно передавать неограниченное количество объектов в форму? разве в форме нет просто полей, а затем она передает эти поля вашему контроллеру, который выполняет фактическое создание объекта?
2. по сути, это почти весь код ruby, который у меня есть.
3. Код, который находится в вашей скрипке, тоже является кодом 🙂 Также — есть ли у вас частичные шаблоны в
html
илиhtml.erb
? включите их тоже — это часть того, что мы сделаем, чтобы помочь вам 🙂 Включите в свойQuestion
список все, что имеет отношение к вопросу, чтобы мы могли посмотреть и выяснить, что нужно изменить… (мы также поиграем с кодом в fiddle, чтобы разобраться в этом).4. У меня есть один базовый
application.html.erb
макет и другой html для формы — вы можете увидеть его в jsfiddle. Приложение состоит из одной страницы (регистрационной формы).5. Хорошо, я сделаю, скопируйте это
Ответ №1:
Итак, это, вероятно, не полное решение, но мое первое, на что следует обратить внимание, это… вам должен понадобиться всего один ParticipationForm
— вам не нужно добавлять несколько форм, просто несколько наборов полей сведений о пользователе.
Каждый набор пользовательских полей необходимо будет уникально сгруппировать и идентифицировать, например, конечный результат (после того, как javascript каждый раз добавит новые поля) будет примерно таким, как показано ниже (примечание: я только что добавил очень простую версию полей, а не ту, которую вы в конечном итоге будете использовать со всеми подробностями):
<form class="form-signin">
<div class="user-field-set">
<input type="text" name="[participation_form][1]name" class="form-control" placeholder="Имя" required autofocus>
<input type="tel" name="[participation_form][1]telephone" class="form-control" placeholder="Телефон" required>
<input type="email" name="[participation_form][1]email" class="form-control" placeholder="Електропочта" required>
</div>
<div class="user-field-set">
<input type="text" name="[participation_form][2]name" class="form-control" placeholder="Имя" required autofocus>
<input type="tel" name="[participation_form][2]telephone" class="form-control" placeholder="Телефон" required>
<input type="email" name="[participation_form][2]email" class="form-control" placeholder="Електропочта" required>
</div>
*** submit button for all sets of user details goes here ***
</form>
Комментарии:
1. Да, это один из способов сделать это, цените это. Но не могли бы вы, пожалуйста, также предоставить некоторый код в
create
контроллере для такого типа компоновки данных?2. Шаг 1) обновите свой javascript, чтобы вставить наборы полей с уникальными идентификаторами, подобными этому. Шаг 2) отправьте форму и посмотрите, какие параметры передаются вам в вашем контроллере, затем шаг 3) мы посмотрим, какой код нам нужен для анализа этого набора параметров 🙂
3. Обратите внимание, что стандартная практика Rails заключается в использовании
form_for
с несколькимиfields_for
, а затем использованииaccepts_nested_parameters_for :user
(или эквивалентной модели, добавляемой здесь) для приема нескольких пользовательских данных в контроллере… styart с фиксированным количеством пользователей (вместо их динамического добавления). Затем адаптируйте html, сгенерированныйfields_for
, для создания вашего javascript dynamic-field-adder… по крайней мере, так я делал это в прошлом4. О,
name="[participation_form][1]name"
это какой-то массив, заполняемый в html? Это действительно работает) Большое спасибо5. Да 🙂 это то, что rails часто делает с этими наборами полей. Затем вы можете просто выполнить итерацию по массиву в вашем контроллере (хотя часто бывает полезно увидеть точную форму параметров, которые вы получаете, прежде чем пытаться угадать, как это произойдет — избавляет от головной боли) 🙂