Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing RJS to replace innerHTML with a real live instance variable
    primarykey
    data
    text
    <p>I can't for the life of me get RJS to replace an element's innerHTML with an instance variable's attribute, i.e. something like <code>@thing.name</code></p> <p>I'll show all the code (simplified from the actual project, but still complete), and I hope the solution will be forehead-slap obvious to someone...</p> <p>In RoR, I've made a simple page displaying a random Chinese character.</p> <p>This is a <code>Word</code> object with attributes <code>chinese</code> and <code>english</code>.</p> <p>Clicking on a link titled "What is this?" reveals the <code>english</code> attribute using RJS. Currently, it also hides the "What is this?" link and reveals a "Try Another?" link that just reloads the page, effectively starting over with a new random character.</p> <p>This is fine, but there are other elements on the page that make their own database queries, so I would like to load a new random character by an AJAX call, leaving the rest of the page alone.</p> <p>This has turned out to be harder than I expected: I have no trouble replacing the html using link_remote_to and page.replace_html, but I can't get it to display anything that includes an instance variable.</p> <p>I have a Word resource and a Page resource, which has a home page, where all this fun takes place. In the PagesController, I've made a couple ways to get random words. Either one works fine...</p> <p>Here's the code:</p> <pre><code>class PagesController &lt; ApplicationController def home all_words = Word.find(:all) @random_word = all_words.rand @random_words = Word.find(:all, :limit =&gt; 100, :order =&gt; 'rand()') @random_first = @random_words[1] end end </code></pre> <p>As an aside, the SQL call with <code>:limit =&gt; 100</code> is just in case I think of some way to cycle through those random words. Right now it's not useful. Also, the 'rand()' is MySQL specific, as far as I know.</p> <p>In the home page view (it's HAML), I have this:</p> <pre><code>#character_box = render(:partial =&gt; "character", :object =&gt; @random_word) if @random_word #whatisthis = link_to_remote "☝ what is this?", :url =&gt; { :controller =&gt; 'words', :action =&gt; 'reveal_character' }, :html =&gt; { :title =&gt; "Click for the translation." } #tryanother.{:style =&gt; "display:none"} = link_to "try another?", root_path </code></pre> <p>Note that the #'s in this case represent divs (with the given ids), not comments, because this is HAML.</p> <p>The "character" partial looks like this (it's erb, for no real reason):</p> <pre><code>&lt;div id="character"&gt; &lt;%= "#{@random_word.chinese}" } %&gt; &lt;/div&gt; &lt;div id="revealed" style="display:none"&gt; &lt;ul&gt; &lt;li&gt;&lt;span id="english"&gt;&lt;%= "#{@random_word.english_name}" %&gt;&lt;/span&gt;&lt;/li&gt; &lt;/ul&gt; &lt;/div&gt; </code></pre> <p>The reveal_character.rjs file looks like this:</p> <pre><code>page[:revealed].visual_effect :slide_down, :duration =&gt; '.2' page[:english].visual_effect :highlight, :startcolor =&gt; "#ffff00", :endcolor =&gt; "#ffffff", :duration =&gt; '2.5' page.delay(0.8) do page[:whatisthis].visual_effect :fade, :duration =&gt; '.3' page[:tryanother].visual_effect :appear end </code></pre> <p>That all works perfectly fine.</p> <p>But if I try to turn <code>link_to "try another?"</code> into <code>link_to_remote</code>, and point it to an RJS template that replaces the "character" element with something new, it only works when I replace the innerHTML with static text. If I try to pass an instance variable in there, it never works.</p> <p>For instance, let's say I've defined a second random word under Pages#home...</p> <p>I'll add <code>@random_second = @random_words[2]</code> there.</p> <p>Then, in the home page view, I'll replace the "try another?" link (previously pointing to the <code>root_path</code>), with this:</p> <pre><code>= link_to_remote "try another?", :url =&gt; { :controller =&gt; 'words', :action =&gt; 'second_character' }, :html =&gt; { :title =&gt; "Click for a new character." } </code></pre> <p>I'll make that new RJS template, at app/views/words/second_character.rjs, and a simple test like this shows that it's working:</p> <pre><code>page.replace_html("character", "hi") </code></pre> <p>But if I change it to this:</p> <pre><code>page.replace_html("character", "#{@random_second.english}") </code></pre> <p>I get an error saying I fed it a nil object:</p> <blockquote> <p>ActionView::TemplateError (undefined method `english_name' for nil:NilClass) on line #1 of app/views/words/second_character.rjs: 1: page.replace_html("character", "#{@random_second.english}")</p> </blockquote> <p>Of course, actually instantiating @random_second, @random_third and so on ad infinitum would be ridiculous in a real app (I would eventually figure out some better way to keep grabbing a new random record without reloading the page), but the point is that I don't know how to get any instance variable to work here.</p> <p>This is not even approaching my ideal solution of rendering a partial that includes the object I specify, like this:</p> <pre><code>page.replace_html 'character', :partial =&gt; 'new_character', :object =&gt; @random_second </code></pre> <p>As I can't get an instance variable to work directly, I obviously cannot get it to work via a partial.</p> <p>I have tried various things like:</p> <pre><code>:object =&gt; @random_second </code></pre> <p>or</p> <pre><code>:locals =&gt; { :random_second =&gt; @random_second } </code></pre> <p>I've tried adding these all over the place -- in the <code>link_to_remote</code> options most obviously -- and studying what gets passed in the parameters, but to no avail. It's at this point that I realize I don't know what I'm doing.</p> <p>This is my first question here. I erred on the side of providing all necessary code, rather than being brief. Any help would be greatly appreciated.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload