Walidacja

Witam,
posiadam coś takiego: <%=hidden_field_tag 'notice[author]', @user.name + ' ' + @user.surname %>
I chciałbym to zabezpieczyć przed możliwością edycji źródła strony i podmianą wartości, jak najskuteczniej to zrobić ? I ewentualnie czy jest jakieś lepsze rozwiązanie odnośnie wysyłania do bazy danych autora ?

To zależy od tego czy Notice i User są ze sobą powiązane. Jeśli tak to zrób to w modelu Notice (after_initialize hook albo coś podobnego)

Jeśli nie są to zrób to w kontrolerze, w akcji gdzie tworzysz notice, np.

@notice = Notice.new(params[:notice])
@notice.author = @user.full_name

etc.

Hmm a mógłbyś to dokładniej opisać ? Bo nie do końca wiem co zrobić…

Wrzuć na gist.github.com kod:

  1. kontrolera ktory tworzy Notice
  2. modeli Notice i User

to opiszę dokładniej bo nie napisałeś czy są powiązane czy nie

Ok działa, dzięki wielkie :slight_smile:

Witam, podpinam się bo też mam problem z walidacją, a nie chce tworzyć oddzielnego wątku.

Mam taki kod:

I za nic nie chce działać… Po prostu da się bez problemu dodawać rekordy o takich samych nazwach i linkach. Zero reakcji.

Mam też taki formularz jeśli to coś rozjaśni.

[quote]<% form_for @story do |f| %>
<%= f.error_messages %>

<%= f.label :name %>
<%= f.text_field :name %>

<%= f.label :link %>
<%= f.text_field :link %>

<%= f.submit 'Create' %>

<% end %>[/quote]
I taką akcje w kontrolerze:

[quote]def create
@story = Story.new(params[:story])

if @story.save
  flash[:notice] = "Story was successfully created."
  redirect_to stories_path
else
  render :action => 'new'
end

end[/quote]

“validates_uniqueness_of” gdzie dokładnie siedzi? Możesz przesłać z kawałkiem klasy?

Oddzielny wątek chyba by nie zaszkodził.

Cała klasa Story wygląda tak:

[quote]class Story < ActiveRecord::Base
validates_presence_of :name, :link
validates_uniqueness_of :name, :link

has_many :votes do
def latest
find :all, :order => ‘id DESC’, :limit => 3
end
end

def to_param
“#{id}-#{name.gsub(/\W/, ‘-’).downcase}”
end
end[/quote]
To już nie pierwszy raz. Wcześniej robiłem Depot app z Agile Web Development i było to samo. Na stronie formularza jak zostawię wszystkie pola puste to wyskakują mi błędy, że nie mogą być, ale jak name dam takie jakie już mam w bazie to w błędach zostaje tylko, że link nie może być pusty.

ja bym zaczol od dodania do bazy do pol tych klucza uniq, wtedy jak rails nawali to i tak sie nie doda, i wtedy mozesz kombinowac, lepiej sie podwojnie zabezpieczyc. Wiec ze to sie czesto olew ale dobrze zaprojektowana baza danych to nawet wiecej niz polowa sukcesu ;]

Ja bym jednak został przy prawidłowym użyciu walidacji i słownika ortograficznego :slight_smile:

Nie chodzi mi o znalezienie obejścia bo jest pewnie pierdyliard sposobów na to. Chciałbym się dowiedzieć dlaczego taka podstawowa(?) walidacja mi nie działa.

Może zostało to w którejś wersji Railsów zamienione inną metodą?
Może chodzi o kodowanie w bazie danych lub coś podobnego? Chodzi mi o to, że mamy jakąś nazwę która została wpisana do formularza i jest ona porównywana z tymi w bazie danych i mimo, że są takie same to ta z bazy danych odczytywana jest jako różna/inna. Zaznaczę że nie używam polskich znaków. Kodowanie mam utf-8.

Może to coś rozjaśni:

[quote]Ruby version 1.8.6 (i386-mswin32)
RubyGems version 1.3.5
Rack version 1.0
Rails version 2.3.2
Active Record version 2.3.2
Action Pack version 2.3.2
Active Resource version 2.3.2
Action Mailer version 2.3.2
Active Support version 2.3.2
Application root C:/InstantRails/rails_apps/shovell
Environment development
Database adapter sqlite3
Database schema version 20091015121102[/quote]

Ja bym jednak został przy prawidłowym użyciu walidacji i słownika ortograficznego :)[/quote]
Słownik słownikiem, ale naprawdę sama walidacja w modelu nic nie załatwia poza tym, że ładnie możesz wypisać info co się dzieje, natomiast spokojnie możesz dodać dwa rekordy z tym samym polem, które ma być unikatowe. Można się zabezpieczyć przed tym inaczej niż indeksem unikatowym, ale kosztem dużych problemów z wydajnością.

To mi wygląda na problem typu “patrzę nad A od kilku godzin a problem leży w B”. validates_uniqueness_of była od zawsze w Rails i od zawsze działała poprawnie więć imho o coś po stronie bazy (widzę, że korzystasz z sqlite). Najlepiej sprawdż development.log, powinieneś zobaczyć SQl którego Rails wysyła do sprawdzenia czy rekord już istnieje. Wykonaj tego SQL’a samemu i zobacz czy działa poprawnie.

Sprawdziłem loga i podczas tworzenia rekordu o takiej samej nazwie dodaje mi takie coś:

[quote]Processing StoriesController#create (for 127.0.0.1 at 2009-10-15 21:08:55) [POST]
Parameters: {“commit”=>“Create”, “story”=>{“name”=>“Agito”, “link”=>""}, “authenticity_token”=>“U7AzqSQ21C6Z5SKmXBqPokNF0gBKHeApjEc48TjJ8OM=”}
e[4;36;1mStory Exists (0.0ms)e[0m e[0;1mSELECT “stories”.id FROM “stories” WHERE (“stories”.“name” = ‘’) LIMIT 1e[0m <= POGRUBIONE
e[4;35;1mStory Exists (0.0ms)e[0m e[0mSELECT “stories”.id FROM “stories” WHERE (“stories”.“link” = ‘’) LIMIT 1e[0m
Rendering template within layouts/application
Rendering stories/new
Completed in 31ms (View: 16, DB: 0) | 200 OK [http://localhost/stories][/quote]
Czy dobrze mi się wydaje, że w miejscu które pogrubiłem(3 linia) jest błąd? Czy dobrze mi się wydaje, że w tym miejscu sprawdza unikalność name i porównuje do pustego?

SELECT “stories”.id FROM “stories” WHERE (“stories”.“name” = ‘’) LIMIT 1

no tu szuka tylko id ktore maja name puste, i wybiera 1 z nich w sumie dla szybkosci, bo juz jeden to i tak za duzo

[quote=gotar]SELECT “stories”.id FROM “stories” WHERE (“stories”.“name” = ‘’) LIMIT 1

no tu szuka tylko id ktore maja name puste, i wybiera 1 z nich w sumie dla szybkosci, bo juz jeden to i tak za duzo[/quote]
No tak ale czy nie powinien tu szukać id z name = temu co wpisałem w formularzu?

IMHO powinien

ja bym jednak zmienił bazę danych :>

[quote=sevos]IMHO powinien

ja bym jednak zmienił bazę danych :>[/quote]
Nie wiem o co kaman, ale zacząłem robić drobną aplikację którą sobie wymyśliłem. Wszytko robię niby tak jak w tych aplikacjach z książek, a mimo to walidacja działa :expressionless: :slight_smile: