Ruby On Rails in UA/Разработка на ROR/Несколько вопросов

12 сентября 2010, 16:08   Несколько вопросов
artyomst
artyomst
Живет: не указан
Сообщений: 22
Рейтинг: 0.0
Рег: 12 февр. 2010

  •  
Подскажите как грамотно реализовать следующее: Есть две модели вопрос-ответы:
class Question < ActiveRecord::Base
  has_many :answers
end
class Answer < ActiveRecord::Base
  belongs_to :question
end
Как огранизовать заполнение вопросов-ответов? Пытаюсь так: создал scaffold для Question, внутри формы хочу через аякс добавить необходимое количество ответов. Но пока не сохраню объект question я не могу добавить ответы, значит нужно хранить хеш ответов, а уже после сохранения вопроса, добавить ответы из хеша? Может, что-нибудь подскажете, где почитать, куда посмотреть?
12 сентября 2010, 17:50   RE: Несколько вопросов
artyomst
artyomst
Живет: не указан
Сообщений: 22
Рейтинг: 0.0
Рег: 12 февр. 2010

  •  
artyomst Нашел на railscasts.com в эпизодах 196 и 197. Пробую тоже самое на Ruby 1.9.2 + Rails 3, но есть проблема - ссылки "Add Answer", "remove" не работают. В чем может быть проблема? Частично решилась проблема путем копирвоания файлов из public/javascripts - "remove" заработало, а вот "Add Answer" не работает
12 сентября 2010, 18:01   RE: RE: Несколько вопросов
admin
Ruslan Voloshin
Живет: Odessa, UKR
Сообщений: 2973
Рейтинг: 782.0
Рег: 13 марта 2007
Его блог
  •  
artyomst Понимаешь очень сложно тебе помогать елси ты не приводишь кусокв кода,
12 сентября 2010, 18:16   RE: Несколько вопросов
artyomst
artyomst
Живет: не указан
Сообщений: 22
Рейтинг: 0.0
Рег: 12 февр. 2010

  •  
artyomst Контроллер Survey
class SurveysController < ApplicationController
  def index
    @surveys = Survey.all
  end
  
  def show
    @survey = Survey.find(params[:id])
  end
  
  def new
    @survey = Survey.new
    3.times do
      question = @survey.questions.build
      4.times { question.answers.build }
    end
  end
  
  def create
    @survey = Survey.new(params[:survey])
    if @survey.save
      flash[:notice] = "Successfully created survey."
      redirect_to @survey
    else
      render :action => 'new'
    end
  end
  
  def edit
    @survey = Survey.find(params[:id])
  end
  
  def update
    @survey = Survey.find(params[:id])
    if @survey.update_attributes(params[:survey])
      flash[:notice] = "Successfully updated survey."
      redirect_to @survey
    else
      render :action => 'edit'
    end
  end
  
  def destroy
    @survey = Survey.find(params[:id])
    @survey.destroy
    flash[:notice] = "Successfully destroyed survey."
    redirect_to surveys_url
  end
end

Модель Answer
class Answer < ActiveRecord::Base
  belongs_to :question
end
Модель Question
class Question < ActiveRecord::Base
  belongs_to :survey
  has_many :answers, :dependent => :destroy
  accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
Модель Survey
class Survey < ActiveRecord::Base
  has_many :questions, :dependent => :destroy
  accepts_nested_attributes_for :questions, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
_answer_fields.html.erb
<p class="fields">
  <%= f.label :content, "Answer" %>
  <%= f.text_field :content %>
  <%= link_to_remove_fields "remove", f %>
</p>
_form.html.erb
<% form_for @survey do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>
  <% f.fields_for :questions do |builder| %>
    <%= render "question_fields", :f => builder %>
  <% end %>
  <p><%= link_to_add_fields "Add Question", f, :questions %></p>
  <p><%= f.submit "Submit" %></p>
<% end %>
_question_fields.html.erb
<div class="fields">
  <p>
    <%= f.label :content, "Question" %>
    <%= link_to_remove_fields "remove", f %><br />
    <%= f.text_area :content, :rows => 3 %>
  </p>
  <% f.fields_for :answers do |builder| %>
    <%= render 'answer_fields', :f => builder %>
  <% end %>
  <p><%= link_to_add_fields "Add Answer", f, :answers %></p>
</div>
edit.html.erb
<% title "Edit Survey" %>

<%= render :partial => 'form' %>

<p>
  <%= link_to "Show", @survey %> |
  <%= link_to "View All", surveys_path %>
</p>
index.html.erb
<% title "Surveys" %>

<table>
  <tr>
    <th>Name</th>
  </tr>
  <% for survey in @surveys %>
    <tr>
      <td><%=h survey.name %></td>
      <td><%= link_to "Show", survey %></td>
      <td><%= link_to "Edit", edit_survey_path(survey) %></td>
      <td><%= link_to "Destroy", survey, :confirm => 'Are you sure?', :method => :delete %></td>
    </tr>
  <% end %>
</table>

<p><%= link_to "New Survey", new_survey_path %></p>
new.html.erb
<% title "New Survey" %>

<%= render :partial => 'form' %>

<p><%= link_to "Back to List", surveys_path %></p>
show.html.erb
<% title "Survey" %>

<p>
  <strong>Name:</strong>
  <%=h @survey.name %>
</p>

<ol>
<% for question in @survey.questions %>
  <li>
    <%=h question.content %>
    <ul>
    <% for answer in question.answers %>
      <li><%=h answer.content %></li>
    <% end %>
    </ul>
  </li>
<% end %>
</ol>

<p>
  <%= link_to "Edit", edit_survey_path(@survey) %> |
  <%= link_to "Destroy", @survey, :confirm => 'Are you sure?', :method => :delete %> |
  <%= link_to "View All", surveys_path %>
</p>
application.js
function remove_fields(link) {
  $(link).previous("input[type=hidden]").value = "1";
  $(link).up(".fields").hide();
}

function add_fields(link, association, content) {
  var new_id = new Date().getTime();
  var regexp = new RegExp("new_" + association, "g")
  $(link).up().insert({
    before: content.replace(regexp, new_id)
  });
}
application_jquery.js
function remove_fields(link) {
  $(link).prev("input[type=hidden]").val("1");
  $(link).closest(".fields").hide();
}

function add_fields(link, association, content) {
  var new_id = new Date().getTime();
  var regexp = new RegExp("new_" + association, "g")
  $(link).before(content.replace(regexp, new_id))
}
Функция remove_fields работает, а вот add_fields видимо нет.
12 сентября 2010, 21:09   RE: Несколько вопросов
admin
Ruslan Voloshin
Живет: Odessa, UKR
Сообщений: 2973
Рейтинг: 782.0
Рег: 13 марта 2007
Его блог
  •  
artyomst Сразу же вопрос почему у тебя две функции с одним названием add_fields, и кажется что у тебя не правильно ссылка строится, что в логах видно по нажатию на ссылку добавить вопрос? И если можно исходник html на добавить поле, который вызывает add_fields
12 сентября 2010, 21:49   RE: RE: Несколько вопросов
demoversion
Ігор Касянчук
Живет: Ivano-Frankivsk,UKR
Сообщений: 416
Рейтинг: 189.0
Рег: 05 сент. 2007

  •  
Ruslan Voloshin я думаю он использует ту версию что для jquery если нет - то надо только ее брать потом запускать в ФФ и смотреть логи FireBug
kartaonline.com
13 сентября 2010, 11:17   RE: RE: Несколько вопросов
artyomst
artyomst
Живет: не указан
Сообщений: 22
Рейтинг: 0.0
Рег: 12 февр. 2010

  •  
Ruslan Voloshin Меня тоже смутили две функции, но я пробовал каждую отдельно. _form.html.erb
<% form_for @survey do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>
  <% f.fields_for :questions do |builder| %>
    <%= render "question_fields", :f => builder %>
  <% end %>
  <p><%= link_to_add_fields "Add Question", f, :questions %></p>
  <p><%= f.submit "Submit" %></p>
<% end %>
_question_fields.html.erb
<div class="fields">
  <p>
    <%= f.label :content, "Question" %>
    <%= link_to_remove_fields "remove", f %><br />
    <%= f.text_area :content, :rows => 3 %>
  </p>
  <% f.fields_for :answers do |builder| %>
    <%= render 'answer_fields', :f => builder %>
  <% end %>
  <p><%= link_to_add_fields "Add Answer", f, :answers %></p>
</div>
По нажатию Add_question Ошибка: syntax error Источник: http://localhost:3000/surveys/new Строка 1, символ 17 Исходный код: add_fields(this, "answers", "<p class=\"fields\">\n <label for=\"survey_questions_attributes_0_answers_attributes_new_answers_content\">Answer<\/label>\n <input id=\"survey_questions_attribute http://i9.fastpic.ru/big/2010/0913/26/6fb74c59cf7a2ff06c27a627ae283926.png
13 сентября 2010, 12:03   RE: RE: RE: Несколько вопросов
admin
Ruslan Voloshin
Живет: Odessa, UKR
Сообщений: 2973
Рейтинг: 782.0
Рег: 13 марта 2007
Его блог
  •  
artyomst У тебя link_to_add_fields метод хелпера, и он екпейпит текст, так как ты вероятно в третьих рельсах пытаешься воспроизвести пример для вторых. Тебе надо добавить в конце метода link_to_add_fields .html_safe что бы не эскейпился яваскриптовый код. Елси не получится тогда покажи сиходник этого метода link_to_add_fields
13 сентября 2010, 12:11   RE: RE: RE: RE: Несколько вопросов
artyomst
artyomst
Живет: не указан
Сообщений: 22
Рейтинг: 0.0
Рег: 12 февр. 2010

  •  
Ruslan Voloshin Как раз я пытаюсь в 3их рельсах запуская пример для 2ых ) link_to_add_fields("Add Question", f, :questions).html_safe - то же самое link_to_add_fields.html_safe "Add Question", f, :questions - wrong number of arguments (0 for 3)
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
  def link_to_remove_fields(name, f)
    f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
  end
  
  def link_to_add_fields(name, f, association)
    new_object = f.object.class.reflect_on_association(association).klass.new
    fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
      render(association.to_s.singularize + "_fields", :f => builder)
    end
    link_to_function(name, h("add_fields(this, '#{association}', '#{escape_javascript(fields)}')"))
  end
end
Какой-то код лишний добавил форум, Настоящий код тут 13 строк : http://s-c.me/8843/h http://i9.fastpic.ru/big/2010/0913/03/ebcb1cb826321e325d9f169d8f0ef503.png
13 сентября 2010, 13:12   RE: RE: RE: RE: RE: Несколько вопросов
admin
Ruslan Voloshin
Живет: Odessa, UKR
Сообщений: 2973
Рейтинг: 782.0
Рег: 13 марта 2007
Его блог
  •  
artyomst h( лишний.
link_to_function(name, "add_fields(this, '#{association}', '#{escape_javascript(fields)}'"))
или так
link_to_function(name, "add_fields(this, '#{association}', '#{escape_javascript(fields)}'".html_safe))
13 сентября 2010, 13:15   RE: RE: RE: RE: RE: RE: Несколько вопросов
artyomst
artyomst
Живет: не указан
Сообщений: 22
Рейтинг: 0.0
Рег: 12 февр. 2010

  •  
Ruslan Voloshin Большое спасибо, заработало!