2010-09-21 8 views
30

Nie mam problemu z wykonywaniem typowych wywołań AJAX do iz Railsów (3) z obiektami JSON i jQuery-rails (biblioteka jQuery plus specjalny plik rails.js).Obsługa JSON w szablonie JS/ERB w Railsach 3

W jednym kontrolerze chcę jednak ZWRÓCIĆ JSON w szablonie erb (create.js.erb) po wywołaniu AJAX.

Próbowałem każdej kombinacji rzeczy w kontrolerze (@ object.to_json, "[{" content ":" hello world "}] ', itp.) Oraz w samym szablonie (JSON.parse() , apostrofów, cudzysłowy, itp), ale obiekt utrzymuje na renderingu tak:

'[{"groups":{},"created_at":"2010-09-21T03:49:34Z" ... 

iw rezultacie mój kod jQuery nie można analizować je i pojawiają się błędy.

Jak należy przygotować mój obiekt w kontrolerze i jaka składnia wiersza wymaga w widoku, aby renderował się jako poprawny obiekt JSON?

Dziękuję bardzo!

Odpowiedz

51

Nie jestem pewien, czy to jest przyczyna, ale można również spróbować odtwarzać za pomocą metody html_safe. ERB może uciekać z twojego JSON, ponieważ uważa, że ​​nie jest bezpieczny dla html. Spróbuj zadzwonić tej metody przy użyciu ciąg:

@object.to_json.html_safe 
+19

Uważaj: wywołanie html_safe bez ucieczki może prowadzić do podatności XSS jeśli” ponownie osadzić wynik w tagu skryptu. – John

+0

Sprawdź to [railscast] (http://railscasts.com/episodes/204-xss-protection-in-rails-3), aby zobaczyć, jak używać 'html_safe' bezpiecznie – Subtletree

+0

dzięki! To jest dla mnie pomocne. – rainstop3

1

Aby powrócić json trzeba napisać renderowania w kontroler następująco:

render :json => @object 

i .to_json zostanie automatycznie wywołana.

Jeżeli chcesz dołączyć jakieś relacje, można wykonać następujące czynności:

render :json => @post.to_json(:include => [:comments, :authors]) 

Nie jestem pewien, czy to działa, aby używać erb, aby uczynić swoją JSON.

0

Możesz wywołać render w kontrolerze, ale będzie to problem, jeśli potrzebujesz renderować więcej niż kilka części do późniejszego wstawienia domeny przez program obsługi. Musiałem ustawić wiele fragmentów html na hasz, i byłem w stanie zwrócić erb, który zasadniczo używa hash.to_json.html_safe, jak sugeruje to neutrino i pozwala mi renderować wiele części w procesie.

31

Samo użycie html_escape lub raw pozostawi Cię vulnerable to XSS.

Zamiast definiować sensowną wersję json_escape (a.k.a. j) pomocnika:

module ActionView::Base 
    def json_escape(s) 
    result = s.to_s.gsub('/', '\/') 
    s.html_safe? ? result.html_safe : result 
    end 

    alias j json_escape 
end 

używać go tak:

<script> 
    var Accounts = new Backbone.Collection; 
    Accounts.reset(<%=j @accounts.to_json.html_safe %>); 
    var Projects = new Backbone.Collection; 
    Projects.reset(<%=j @projects.to_json(:collaborators => true).html_safe %>); 
</script> 

Zobacz this post dla dalszych szczegółów.

Należy pamiętać, że istnieje naming conflict między j aliasem json_escape w ERB :: Util i j aliasem escape_javascript w actionView :: Pomocników :: JavaScriptHelper. Mam nadzieję, że alias JavaScriptHelper zostanie zmieniony na js.

+4

Ta odpowiedź powinna być akceptowana - to naprawdę szokujące, ile wpisów w internecie sugeruje używanie html_safe bez ucieczki. – Ralf

+1

Wierzę, że powinno to być 'class ActionView :: Base', a nie' module'. Czy jest jakiś powód, aby domyślnie nie używać html_safe? Nie mogę wymyślić żadnego przypadku, w którym chciałbyś json_escape, a następnie html_escape. – Ralf

+0

Szybkie pytanie: gdzie powinna znaleźć się definicja 'module ActionView :: Base ... end' w projekcie Rails? Czy istnieje standardowa ścieżka lub plik? –

0

Tylko to_json.html_safe jest potrzebne:

> `'<script>'.to_json` 
=> "\"\\u003cscript\\u003e\"" 

patch aby to_json reagować na html_safe? i powrócić true automatycznie:

# just use .to_json instead of .to_json.html_safe 
ActiveSupport::JSON.class_eval do 
    class << self 
    def encode_with_html_safe *args 
     self.encode_without_html_safe(*args).html_safe 
    end 
    alias_method_chain :encode, :html_safe 
    end 
end