LINUX.ORG.RU

RoR: validates_presence_of :field_name


0

0

Для валидации на непустое поле надо всего лишь добавить в модель сабжевую строчку?

У меня «master-detail» модель - посты и коментарии к ним, в постах валидация работает подсвечивая, что необходимо, а добавление сабжа в модель коментария ни к чему не приводит. Вернее, пустой коментарий теперь не добавляется, хочу подсветку поля сделать.

Затрудняюсь определить, что именно надо показать здесь, телепаты, ау, скажите что надо, помогите добавить валидацию.

p.s. был бы очень признателен за IM координаты человека работающего с RoR, хотелось бы иногда вопросы задавать небольшие, много времени уходит с разбирательствами, когда спросить не у кого.

★★

Последнее исправление: Reaper (всего исправлений: 1)

запускай консоль, делай вывод создания комментария навроде:

c = Comment.new ; c.errors unless c.save

если все в порядке и ошибки выдает, значит в контроллере что-то накосячил или недописал, а может во view.

тогда показывай метод контроллера, где создаются комментарии. если это create в CommentsController, то куда он идет если комментарий не сохранен? в CommentsController#new? а может надо в PostsController#show?

а может все еще проще. допустим ты рендеришь все скопом, соответственно комментарии - вложенная форма. наверное стоит добавить в модель Post accept_nested_attributes_for :comments? Дальше примеры смотри на http://weblog.rubyonrails.org/2009/1/26/nested-model-forms , там есть секции и view, и подраздел валидации, которая just works в этом случае.

p.s. был бы очень признателен за IM координаты человека работающего с RoR, хотелось бы иногда вопросы задавать небольшие, много времени уходит с разбирательствами, когда спросить не у кого.

я бы вобщем и с радостью, но почти переключился на backend'ы, с самими рельсами меньше работаю, да и толку-то. stackoverflow или railsforum - там знающие люди. в русском сегменте ror2ru на google groups или rubyclub.com.ua.

volh ★★
()
Ответ на: комментарий от volh

В консоли вижу, валидация работает:

...
>> c.errors unless c.save
=> #<ActiveRecord::Errors:0xb708476c @base=#<Comment id: nil, post_id: nil, message: nil, created_at: nil, updated_at: nil>, errors{"message"=>["can't be blank"]}
>> 

контролер коментариев:

class CommentsController < ApplicationController
  
  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.create!(params[:comment])
    respond_to do |format|
      format.html { redirect_to @post }
      format.js 
    end
  end
end

кусок из views/posts/show.html.erb:

...
<h2>Comments</h2>
<div id="comments">
  <%= render :partial => @post.comments %>
</div>
...

view/comments/create.js.rjs:

page.insert_html :bottom, :comments, :partial => @comment
...

view/comments/_comment.html.erb

<% div_for comment do %>
  <p>
    <strong>Posted <%= time_ago_in_words(comment.created_at) %> ago</strong><br />
    <%= h(comment.message) %>
  </p>
<% end %>

добавление коментария, обновление списка коментариев используют AJAX.

Reaper ★★
() автор топика
Ответ на: комментарий от Reaper

хмык. ну еще бы ошибка не выводится, ты ведь именно это ему и говоришь - create! , и даже не обрабатываешь эксепшена RecordInvalid, который в этом случае поднимается ( ты этого не видишь, потому что ajax, но в лог-то можно было и заглянуть ).

почему бы не использовать обычную семантику метода create в контроллере, который создается генератором? то есть @comment = @post.comments.build(params[:comment]); if @comment.save ... else ... end

и в случае ошибки рендеришь @comment.errors или еще чего-нибудь, ну например свой partial => «errors», эге?

volh ★★
()

в моделе юзера например

validates_presence_of :login

в script/console:

user = User.new()

user.valid?

=> false

user.save!

выведет список ошибок, аля «login can't be blank»

user.login = 'Person'

user.valid?

=> true

user.save!

=> true

если лень делать user.save! то сразу пишем:

user = User.create(:login => 'Person')

Еще одна деталь интересная, если какое-то поле может быть пустым, но обязательно должно соответствовать длинне, то стоит внимательнее работать с такими полями.

В файле миграции например:

t.column :twitter

в файле модели:

validates_length_of :twitter, :in => 10..100, :allow_nil => true

не забывайте ставить :allow_nil => true

ну в общем в валидация много всяких тонкостей, как в общем и во всём ror.

ciss
()
Ответ на: комментарий от volh

я вот щас не помню правда, но вроде бы для того, чтобы показать ошибки валидации нужно обязательно указать в форме (или около)

errors_message_for :user

ciss
()
Ответ на: комментарий от ciss

камон, error_messages_for это просто хелпер, довольно неуклюжий и к тому же он не будет работать с ajax. есть @model.errors, дальше полная свобода действий, может какой-нибудь:

format.js { render :update do |page| page.visual_effect :bad_field_id end }

volh ★★
()
Ответ на: комментарий от ciss

это уже оффтоп, создавай новую тему)

вообще, в рельсах нету REST по Филдингу, есличто. планировали в этом summer of code, но им в gsoc отказали, может кто еще сделает.

volh ★★
()
Ответ на: комментарий от volh

>format.js { render :update do |page| page.visual_effect :bad_field_id end }

конечно же format.js { render :update do |page| page.visual_effect :shake «some_bad_field_id» end } , но несущественно. я ровно такое поведение для комментариев делал - никаких «заполните это поле», просто подсветка и мигание text_field, все сразу понятно и ни один пользователь не жаловался.

anonymous
()
Ответ на: комментарий от volh

да кому тут кроме нас троих нужна эта тему? :D

да с рестом в вебе как-то тяжко, я очень много статей разных людей на эту тему прочел. не без костылей. та же валидация аккаунта через отправку уникального ключа на email. чтобы было все по тру-рэсту то получается вот как:

юзар нажимает на ссылку (get) выходит на страницу с кнопкой и нажимает ее (подтверждает) (post)

и таких вещей много =)

Для меня основной проблемой в ресте стала генерация url; вручную прописывать

map.page '/page/:id'

или просто

map.resources :posts

ciss
()
Ответ на: комментарий от volh

почему бы не использовать обычную семантику ...

«Agile Web Development» + отдельные примеры как сделать что-то конкретное, не создали у меня целостной картины, я пока опираюсь на опыт работы с другими языками / системами, до конца многого просто не понимаю, как что-то работает только догадываюсь. Я вообще с трудом понял, как создавать detail-сущности (не знаю как оно правильно называется), а если быть более точным, не понял нифига, всилу оставшихся за кадром многих деталей при простом повторении примера.

  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.new(params[:comment])

    respond_to do |format|
      if @comment.save
        format.html { redirect_to @post }
        format.js
      else
?
      end
    end
  end

тут в else для js что надо сделать? У меня есть только примеры с xml:

format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }

у меня же здесь create.js.rjs, использование которого не понимаю. Можно на пальцах сxему объяснить? Найти нигде не могу понятное описание.

сорри за сумбур.

Reaper ★★
() автор топика
Ответ на: комментарий от Reaper

а при else обычно redirect_to :back

я иногда ставил просто return и оно кидала на эту же страницу.

вопрос можно глупый к знатокам? зачем на каждый екш делать respond_to :xml? неужели это так нужно? разве это не только для rss ленты например.

ciss
()
Ответ на: комментарий от ciss

> а при else обычно redirect_to :back

Если я правильно понял совет изменить семантику, всё затеялось ради строки аналогичной

format.xml { render :xml => @post.errors, :status => :unprocessable_entity }

в секции else, чтобы именно рендеринг ошибки сделать.

зачем на каждый екш делать respond_to :xml?

Насколько я заметил, рендеринг xml добавляется, когда ajax вводим.

Reaper ★★
() автор топика
Ответ на: комментарий от Reaper

под «обычной семантикой» я имел в виду не то, как оно в Agile web dev написано ( книжка кстати довольно устаревшая, лучше идти на guides.rubyonrails.org сначала), а то, как create работает в только что созданном с помощью ./script/generate контроллере.

В else для js ты можешь сделать как я написал ранее - трясти id пустого элемента в форме комментария, или что-нибудь вроде format.js { render :partial => «create_error» }, тогда в views/comments/_create_error.js.rjs можешь сказать page.insert_html :bottom, :comments, «You have an error: #{@comment.errors.full_messages}», а потом если хочешь сделать что-нибудь с этим блоком с помощью спецэффектов и может быть убрать через 5 сек, чтобы не мозолил глаза, но это уже твое дело.

Но общий смысл понятен? есть @comment.errors, он доступен во view, где ты рендеришь эти ошибки как душа пожелает. Можешь наверное обновить всю форму комментария с error_messages_for :comment, т.е. точно так же как и для неаяксовых форм.

Если комментарии создаются и всегда будут создаваться исключительно аяксом, можно вообще убрать весь этот блок respond_to.

У меня есть только примеры с xml:

Пример с xml используется там, где клиент получает голый xml, т.е. - в API вебсервиса. Таким же образом ты можешь вместо render :xml сказать render :json. Но это не наш случай.

у меня же здесь create.js.rjs, использование которого не понимаю. Можно на пальцах сxему объяснить? Найти нигде не могу понятное описание.

Какую именно схему? Тебе приходит запрос в формате url.format, в зависимости от формата ты рендеришь определенные файлы и/или совершаешь определенные действия. Для запроса в формате js вызывается action.js.rjs, если специально не указано другого. точно так же как и с action.html.erb

volh ★★
()
Ответ на: комментарий от volh

приведу полный код метода create для случая,когда используется исключительно ajax.

 
def create
  @post = Post.find(params[:post_id])
  @comment = @post.comments.build(params[:comment])
  if @comment.save
    render_update { |page| page.insert_html :bottom, :comments, :partial => @comment }
  else
    render_update { |page| page.insert_html :bottom, :comments, error_messages_for('comment') } 
  end
end

тут я не использую отдельных файлов .rjs. писал вслепую и не знаю точно работает ли, но доложно быть наглядно.

volh ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.