<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jen Wendling</title>
	<atom:link href="http://jenwendling.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://jenwendling.com</link>
	<description>"... it's me ..."</description>
	<lastBuildDate>Tue, 05 Jul 2011 21:24:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Sencha Touch Resource Routing</title>
		<link>http://jenwendling.com/sencha-touch-resource-routing/</link>
		<comments>http://jenwendling.com/sencha-touch-resource-routing/#comments</comments>
		<pubDate>Wed, 18 May 2011 16:49:24 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Sencha Touch]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=265</guid>
		<description><![CDATA[{EAV_BLOG_VER:c29f605782f81784} In MVC architecture, one of the great perks of routing is once you create the resourceful route, you usually don&#8217;t have to think about it again. Set up your actions and views, and you&#8217;re ready to go. Sencha Touch &#8230; <a href="http://jenwendling.com/sencha-touch-resource-routing/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>{EAV_BLOG_VER:c29f605782f81784}</p>
<p>In MVC architecture, one of the great perks of routing is once you create the resourceful route, you usually don&#8217;t have to think about it again. Set up your actions and views, and you&#8217;re ready to go. Sencha Touch has brought the power of routing to their mobile JS framework, giving you an easy way to declare &#8220;URLs&#8221; which point to controllers and actions, but it does more than that, including abstracting History logic into the Dispatcher so that any Ext.redirect will automatically set the URL in the Ext.History space. You can read all you want about the Router and Dispatcher on <a href="http://dev.sencha.com/deploy/touch/docs/" target="_blank">Sencha&#8217;s site</a>, but one thing I missed was the ability to declare a resourceful route. With Rails (3) you get to simply say &#8220;resources :transfers&#8221; and it will automagically recognize your index, create, and other routes for you. Thus, I added this handy little patch with 2 helpful methods (resources and alias), which allow me to do more than just &#8220;connect&#8221;, as so:</p>
<p><code> </code></p>
<pre><code>Ext.Router.draw(function(map) {
  map.connect('welcome', { controller: 'welcome', action: 'index' });
  map.connect('dashboard', { controller: 'dashboard', action: 'show' });
  map.connect('login', { controller: 'user_sessions', action: 'new' });
  map.connect('logout', { controller: 'user_sessions', action: 'destroy' });

  map.resources('transfers');
  map.resources('payments');
  map.resources('messages');
  map.resources('accounts');

  map.alias('bill_pay', 'payments');
  map.alias('message_center', 'messages');

  // more fluffy stuff...
});
</code></pre>
<p><code> </code></p>
<p>Note the &#8220;map.resources&#8221; and &#8220;map.alias&#8221; lines, then check out the code below that does the work. Above, the map.resources(&#8216;transfers&#8217;) line will produce 8 routes by default, including &#8216;transfers/index&#8217;, &#8216;transfers/new&#8217;, etc.</p>
<p><a title="Resourceful Routing with Sencha Touch" href="https://gist.github.com/978998" target="_blank">Get the Gist&#8230;</a></p>
<p><code> </code></p>
<p>As you can see, the resources function simply generates the resourceful routes for you. The alias function is a convenience method really which, well, aliases a named route to another URL. So in this example, Ext.redirect(&#8216;bill_pay&#8217;) is identical to Ext.redirect(&#8216;payments&#8217;), both landing you in the index action of the payments controller. That&#8217;s it&#8230; feel free to use/comment at will. Happy coding! <img src='http://jenwendling.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/sencha-touch-resource-routing/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Adding Callbacks to your Sencha Touch Controllers</title>
		<link>http://jenwendling.com/adding-callbacks-to-your-sencha-touch-controllers/</link>
		<comments>http://jenwendling.com/adding-callbacks-to-your-sencha-touch-controllers/#comments</comments>
		<pubDate>Tue, 17 May 2011 03:30:56 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Sencha Touch]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=256</guid>
		<description><![CDATA[Short and sweet. I needed a callback in several of my controllers to validate that a user is logged in, and if not redirect them back to the login screen. My file structure for this project looks a lot like &#8230; <a href="http://jenwendling.com/adding-callbacks-to-your-sencha-touch-controllers/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Short and sweet. I needed a callback in several of my controllers to validate that a user is logged in, and if not redirect them back to the login screen. My file structure for this project looks a lot like Rails, so I have a config/initializers directory, and in that I&#8217;ve dumped a controllers.js file which contains the following:</p>
<pre><code>
Ext.Dispatcher.on('before-dispatch', function(interaction) {
  if(Ext.isFunction(interaction.controller.beforeFilter)) {
    return interaction.controller.beforeFilter.call();
  };
  return true;
});
</code></pre>
<pre><code>
Ext.Dispatcher.on('dispatch', function(interaction) {
  if(Ext.isFunction(interaction.controller.afterFilter)) {
    return interaction.controller.afterFilter.call();
  };
  return true;
});
</code></pre>
<p>In my application setup, I have a function (requireUser) that handles my logic for requiring that a user be logged in:</p>
<pre><code>
Ext.regApplication({
  // code, code, code...
  loggedIn: readCookie('user_credentials') || false,
  requireUser: function() {
    if(app.loggedIn) return true;
    app.flash.warning = 'Please login to continue.';
    Ext.redirect('login');
    return false;
  },
  flash: {
    notice: '',
    warning: ''
  }
});
</code></pre>
<p>Then in each of the files I want to require a user (or run some other before/after filter logic) I have something like so&#8230;</p>
<pre><code>
Ext.regController('accounts', {
  beforeFilter: app.requireUser,
  model: 'Account',
  index: function(options) {
    app.views.viewport.setActiveItem(
      app.views.accountsList, options.animation
    );
  },
  // other actions here...
});
</code></pre>
<p>For reference on Ext.Controller and Ext.Dispatcher, check out the <a title="Sencha Touch API Documentation" href="http://dev.sencha.com/deploy/touch/docs/" target="_blank">Sencha Touch docs</a></p>
<p>Since it is Sencha on Rails, I feel like this approach adds a nice, seamless integration. Feel free to use, share, comment at will. Happy coding! <img src='http://jenwendling.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/adding-callbacks-to-your-sencha-touch-controllers/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mine&#8217;s Bigger Than Yours</title>
		<link>http://jenwendling.com/mines-bigger-than-yours/</link>
		<comments>http://jenwendling.com/mines-bigger-than-yours/#comments</comments>
		<pubDate>Wed, 05 Jan 2011 05:12:13 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Random]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=224</guid>
		<description><![CDATA[First, let me preface by saying, I am not a &#8220;fangirl&#8221; of anything. I own 2 Macs, an AppleTV, an iPod, an iPad, and lots of other random techie gadgets that didn&#8217;t come from the brilliant minds in Cupertino. I &#8230; <a href="http://jenwendling.com/mines-bigger-than-yours/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>First, let me preface by saying, I am not a &#8220;fangirl&#8221; of anything. I own 2 Macs, an AppleTV, an iPod, an iPad, and lots of other random techie gadgets that didn&#8217;t come from the brilliant minds in Cupertino. I do not, nor have I ever owned an iPhone, originally because I had *just* upgraded my phone with T-Mobile and signed a new 2 year contract when iPhone hit the market back in the summer of 2007. However, I have done iPhone development, and I have used at great length many iPhones so I am well aware of what they are capable of and why people buy them, so don&#8217;t discount my opinion just yet.</p>
<p>When the first-gen iPhone was released, it was flashy (although lacked Flash itself) and new; it opened the world&#8217;s eyes to the potential of mobile experience (I will punt on the use of the word &#8220;technology&#8221; here because, let&#8217;s be honest, the original iPhone did not match up to other smart phones on the market at the time). However, by supplying an open SDK for application development and presenting users with a slick, user-friendly interface, it rapidly became a fad&#8230; although I&#8217;m still uncertain as to the reason behind the massive amount of loyalty and defensiveness that goes along with owning an iPhone.</p>
<p>One theory I have for why the launch was so intense is this: For many years after Apple&#8217;s Mac line was completely revamped, there was always an elite status associated with Apple products, simply because at the time, Apple was only known for making computers &#8211; really expensive ones. Then came the iPod which cost significantly more than (roughly double) other MP3 players, but it looked better and if you had iTunes, you were able to very easily purchase and download music, then sync it to the device, essentially taking your Library with you wherever you go. Rhapsody eventually attempted this same business model, but the iPod precedent had been set. The story goes on to say that next was the iPhone, then the iPad but we&#8217;re aware of what&#8217;s gone down in the last 3 years so I&#8217;ll spare the details. So now we&#8217;ve seen a trend in the last decade&#8230; iPod, iPhone, iPad, each of them continue to blow the competition away in terms of market share. But, why? They&#8217;re sleek, sexy and they scream &#8220;status&#8221;. For the same reason that BMWs and Lexus&#8217; are popular and longed-after, so are Apple&#8217;s iProducts. In the U.S., we&#8217;re known for living outside of our means, which means if a sparkly new toy costs less than $500, you *probably* have a credit card with at least that much available to spend. So if you could carry around a status symbol in your pocket in exchange for &#8230; well, nothing up front &#8230; why wouldn&#8217;t you? Right? At least that explains why Apple&#8217;s handheld devices have caught such wind, while their stationary counterparts are still no match for PCs.</p>
<p>I own Macs because I believe in the quality of the computer and doing graphic design and software development is so much faster, especially when you work with Linux, there&#8217;s minimal knowledge transfer needed when switching between environments. I own an AppleTV because dollar for dollar, it&#8217;s cheaper than cable considering I only watch about 3 TV shows and on rare occasion rent a movie. PLUS, I can use it to stream music from my iMac which alleviates the previous requirement of getting up and putting a different CD in the stereo. So I feel those purchases are justified. My iPod Nano was a birthday gift 2 years ago and I think I&#8217;ve used it a total of 7 times, and although it&#8217;s shiny and pink and in perfectly good condition, it&#8217;s essentially useless but I don&#8217;t think it&#8217;s heavy enough to be a paperweight. As for the iPad, didn&#8217;t buy that one either, was a hand-me-down from the CEO of my company who badly needed the 3G version and unloaded his completely antiquated, way uncool WiFi version down to me. I must say, I have taken quite a liking to the iPad, I even cuddle it to sleep at night playing WWF and Angry Birds &#8211; because I&#8217;m just *that* nerdy. Nonetheless, iPhone iLack.</p>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/mines-bigger-than-yours/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Test your mailers in Rails 3</title>
		<link>http://jenwendling.com/test-your-mailers-in-rails-3/</link>
		<comments>http://jenwendling.com/test-your-mailers-in-rails-3/#comments</comments>
		<pubDate>Thu, 23 Dec 2010 00:16:45 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Rails 3]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=241</guid>
		<description><![CDATA[I don&#8217;t blog very often but I felt this was worth posting, since it left me scratching my head for a few minutes&#8230; Trying to test new mailers in Rails 3 (v 3.0.3 to be exact) with no real documentation &#8230; <a href="http://jenwendling.com/test-your-mailers-in-rails-3/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t blog very often but I felt this was worth posting, since it left me scratching my head for a few minutes&#8230; Trying to test new mailers in Rails 3 (v 3.0.3 to be exact) with no real documentation &#8211; everything out there failed miserably since most examples show use of TMail. So here it is, my MailerTest:</p>
<pre><code>
require 'test_helper'

class MailerTest &lt; ActionMailer::TestCase

  CHARSET = 'UTF-8'

  context "Forgetting a password" do
    setup do
      @user = User.create(valid_user_params)
      @expected = Mail.new
      @expected.content_type = 'text/plain'
      @expected.charset = CHARSET
      @expected.mime_version = '1.0'
    end

    should "send password reset instructions" do
      @expected.from    = "from@example.com"
      @expected.to      = @user.email
      @expected.subject = "Some Fancy Subject"

      assert_equal @expected, Mailer.password_reset_instructions(@user)
    end
  end
end
</code></pre>
<p>I&#8217;m using <a href="https://github.com/thoughtbot/shoulda">Shoulda</a> with TestUnit, but in theory this should work with rspec, etc. Thanks to <a href="http://kpumuk.info/ruby-on-rails/testing-mailers-with-rspec/">http://kpumuk.info/ruby-on-rails/testing-mailers-with-rspec/</a> for giving me a starting point&#8230; There&#8217;s definitely more you can add, like testing for the body content, but really this was all I needed for the purposes of this test.</p>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/test-your-mailers-in-rails-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Who needs a codesitter?</title>
		<link>http://jenwendling.com/who-needs-a-codesitter/</link>
		<comments>http://jenwendling.com/who-needs-a-codesitter/#comments</comments>
		<pubDate>Wed, 01 Sep 2010 19:02:02 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[annoying]]></category>
		<category><![CDATA[rails 3]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=228</guid>
		<description><![CDATA[Not this chick. Sorry Rails, I love you and all, but you have now taken a governmental stance by trying to regulate the output of my HTML and for that, I must say: &#8220;Quit it!!&#8221;. If you haven&#8217;t caught up &#8230; <a href="http://jenwendling.com/who-needs-a-codesitter/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Not this chick. Sorry Rails, I love you and all, but you have now taken a governmental stance by trying to regulate the output of my HTML and for that, I must say: &#8220;Quit it!!&#8221;. If you haven&#8217;t caught up yet, Rails 3 takes HTML escaping into its own hands and instead of requiring you to use h() to escape your output, it&#8217;s now automagically escaped for you. Yay, that&#8217;s great right? No. Wrong. Because it means now anywhere you *didn&#8217;t* want your code escaped, you&#8217;ll have to use raw() or #html_safe. Also wrong because it enables bad, bad storage techniques.</p>
<p>First things first, you should be sanitizing your code prior to storage. Worried about someone adding JS to your public blog and breaking the site? Easy solution, throw away the &lt;script&gt; tag before writing to the db. There are plenty of tools to help with this, xss_terminate being one of them, there are even built-in Rails sanitizers. If you do it right on the way in, you won&#8217;t have to worry about it on the way out. Ok, so let&#8217;s say you potentially miss something? It happens, no one is perfect. That&#8217;s the perfect case to use escape trickery ( i.e. h() ) in the areas where you might be worried about your output.</p>
<p>In general, if you develop applications that resemble ones I build in anyway, you have more HTML output that *doesn&#8217;t* need to be sanitized than does. Sorry to whichever genius thought it would be a great idea to escape everything, but you made a bad decision. It&#8217;s okay, have a beer, wallow in your sorrows and then give users the option to turn this off. In the mean time, it&#8217;s easy to disable it yourself.</p>
<p>In config/initializers create a file, call it whatever, I called mine output_buffer.rb and all you need is:</p>
<p><code> </code></p>
<p><code></p>
<pre>class Object
  def html_safe?
    true
  end
end</pre>
<p></code></p>
<p><code> </code></p>
<p><code></p>
<pre>class String
  def html_safe?
    true
  end
end</pre>
<p></code></p>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/who-needs-a-codesitter/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>The video upload marks the spot.</title>
		<link>http://jenwendling.com/the-video-upload-marks-the-spot/</link>
		<comments>http://jenwendling.com/the-video-upload-marks-the-spot/#comments</comments>
		<pubDate>Fri, 23 Apr 2010 02:50:33 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=217</guid>
		<description><![CDATA[It&#8217;s about time I write on this thing since it has been months since my last post. I was sifting through some old code I&#8217;d written last year and I tell you what, sometimes I&#8217;m actually shocked at the things &#8230; <a href="http://jenwendling.com/the-video-upload-marks-the-spot/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s about time I write on this thing since it has been months since my last post. I was sifting through some old code I&#8217;d written last year and I tell you what, sometimes I&#8217;m actually shocked at the things I&#8217;ve written that I have forgotten about. For instance, I had a client who wanted not only the ability to upload videos, but also link to videos through YouTube. Sounds easy right? Okay but make the videos play in the same player, and make them look like there is no difference. Not so easy. It took a lot of scrounging since this was last year, prior to the YouTube API, however it became a very fun little project involving ffmpeg and rvideo.</p>
<p>Basically what happens is if a video has a YouTube ID, then go get the thumbnail image and the original MPEG file from YouTube and convert it to flv before saving. If the user uploads a video, use ffmpeg to grab a still of the first frame to use as the thumbnail, then convert it to flv and save it.</p>
<p>I present thee Video model. (Unfortunately this was so long ago, I was using attachment_fu&#8230; maybe Paperclip would have helped a bit.)</p>
<p><code> </code></p>
<pre>class Video &lt; ActiveRecord::Base
  include AASM

  aasm_column :state
  aasm_initial_state :pending
  aasm_state :pending
  aasm_state :converting
  aasm_state :converted, :enter =&gt; :set_new_filename
  aasm_state :error

  aasm_event :convert do
    transitions :from =&gt; :pending, :to =&gt; :converting
  end

  aasm_event :converted do
    transitions :from =&gt; :converting, :to =&gt; :converted
  end

  aasm_event :failure do
    transitions :from =&gt; :converting, :to =&gt; :error
  end

  def get_yt_video_data
    uri = URI.parse("http://www.youtube.com/get_video_info")
    post_args = { 'video_id' =&gt; self.url }
    res, data = Net::HTTP.post_form uri, post_args
    b = res.body
    CGI::parse(b) ## return a hash of k=&gt;v pairs
  end

  def get_yt_video_thumb
    get_yt_video_data["thumbnail_url"].first
  end

  def get_yt_video_duration
    seconds = get_yt_video_data["length_seconds"].first.to_i ## format this better... seconds/60 = mins/60 = hours ... hh:mm:ss
    total_minutes = seconds / 1.minutes
    seconds_in_last_minute = seconds - total_minutes.minutes.seconds
    "#{total_minutes}:#{seconds_in_last_minute}"
  end

  def get_yt_embed_url
    return CGI::escape("#{public_filename}") unless self.url.present?
    data = get_yt_video_data
    fmt = '';
    fmt_map = data["fmt_map"]
    a = fmt_map[0..2]
    if a == '18/'
      fmt = '18'
    elsif a == '22/'
      fmt = '22'
      break
    end
    token = data["token"]
    uri2 = URI.parse("http://www.youtube.com")
    args2 = {:video_id =&gt; url, :t =&gt; token, :fmt =&gt; fmt }
    qstr = "video_id=#{url}&amp;t=#{token}&amp;fmt=18"
    res = ""
    Net::HTTP.start(uri2.host, uri2.port) {|http|
      res = http.head("/get_video?#{qstr}")
    }
    CGI::escape("#{res.header['Location']}")
  end

  protected

  def after_create
    return true if url.present?
    convert
  end

  def convert
    self.convert!
      spawn do
        success = system("ffmpeg -i #{full_filename} -ar 22050 -s 480x320 -f flv -y #{full_filename}.flv")
        if success &amp;&amp; $?.exitstatus == 0
          self.converted!
        else
          self.failure!
        end
     end
  end

  def create_thumbnail
    system "ffmpeg -i #{full_filename}.flv -s 120x90 -vframes 1 -f image2 -an #{full_filename}.jpg"
  end

  def set_new_filename
    create_thumbnail
    update_attribute(:filename, "#{filename}.flv")
    update_attribute(:content_type, "application/x-flash-video")
    update_attribute(:width, "480")
    update_attribute(:height, "320")
  end

end</pre>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/the-video-upload-marks-the-spot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updating Multiple DOM Elements (Unobtrusively) with AJAX in Rails</title>
		<link>http://jenwendling.com/updating-multiple-dom-elements-unobtrusively-with-ajax-in-rails/</link>
		<comments>http://jenwendling.com/updating-multiple-dom-elements-unobtrusively-with-ajax-in-rails/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 16:35:08 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[AJAX]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=194</guid>
		<description><![CDATA[Okay, so you&#8217;re like me and you have a complex app that requires AJAX calls to update numerous areas on the page with content from partials. For instance, a date range changes, gets submitted, and that updates a calendar, the &#8230; <a href="http://jenwendling.com/updating-multiple-dom-elements-unobtrusively-with-ajax-in-rails/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Okay, so you&#8217;re like me and you have a complex app that requires AJAX calls to update numerous areas on the page with content from partials. For instance, a date range changes, gets submitted, and that updates a calendar, the list of items below it, and so on and so forth. And, like me, you&#8217;re choosing to use sexy, unobtrusive javascript to do so. (I&#8217;ll be using jQuery as it&#8217;s my flavor of choice, but feel free to apply the same principles to your JS library). The purpose of this article is not to explain AJAX or Rails, I will assume if you&#8217;re reading, you have some education on both subjects.</p>
<p>First, we have a template that looks a little something like this:</p>
<pre><code>&lt;div id="events-calendar"&gt;
  &lt;%= render :partial =&gt; "events/calendar" %&gt;
&lt;/div&gt;
&lt;% form_tag events_path, :id =&gt; "update_dates", :name =&gt; "update_dates" %&gt;
  &lt;%= label_tag :start_date %&gt;
  &lt;%= text_field_tag  :start_date %&gt;
  &lt;%= label_tag :end_date %&gt;
  &lt;%= text_field_tag  :end_date %&gt;
  &lt;%= submit_tag "Go!" %&gt;
&lt;% end %&gt;
&lt;div id="events-list"&gt;
  &lt;%= render :partial =&gt; "events/list" %&gt;
&lt;/div&gt;
</code></pre>
<p>Now, in the past using RJS, this was a very easy thing to do, you just did something to the effect of:</p>
<pre><code>render :update do |page|
  page.replace "events-calendar", :partial =&gt; "events/calendar"
  page.replace "events-list", :partial =&gt; "events/list"
end</code></pre>
<p><span id="more-194"></span><br />
Also, note that I could put all of this in a partial of it&#8217;s own and re-render the whole thing, but for all intents and purposes of the app I&#8217;m working on, that doesn&#8217;t cut it since I&#8217;d have about 6 partials that look very similar to this one (for example, I have a view that just has the date inputs and a list that should update, a view that has the calendar and a form for editing an event, etc etc).</p>
<p>In this example, we want when the dates are updated, the calendar and the list of events should refresh in a single AJAX call, without the use of RJS. There are a plethora of reasons to break your RJS habit sooner, rather than later&#8230; I tend to dislike it for the sheer fact that it&#8217;s tied to one JS library or another, whereas using external JS means if I decide I want to use YUI instead of jQuery, the only thing I have to change is my JS function to do a YUI-style AJAX call and DOM update. No Rails plugins, messing with controllers or RJS templates, etc. etc. Plus, it looks so much cleaner when your controllers don&#8217;t have a bunch of render :updates in them.</p>
<p>On to the good stuff&#8230; In my application.js (or wherever you fancy), I have the following:</p>
<pre><code>$.ajaxSetup({
  beforeSend: function(xhr){ xhr.setRequestHeader('Accept', 'text/javascript') }
});

$(document).ready(function() {
  $('form#update_dates').submit(function() {
    $.get($(this).attr('action'), $(this).serialize(), function(data, status) {
      $('#events-calendar').html(data.calendar);
      $('#events-list').html(data.list);
    }, 'json');
    return false;
  });
});</code></pre>
<p>I&#8217;m setting up the beforeSend AJAX option because jQuery doesn&#8217;t communicate AJAX calls to Rails as being of JS format, so if you don&#8217;t have this, you&#8217;ll likely end up in your format.html . You&#8217;ll need to know the appropriate AJAX calls for your library, the reason I&#8217;m using $.get instead of $.ajax with a dataType: &#8216;json&#8217; is that I only care about having one callback. Also, we&#8217;re asking for a JSON result, but I&#8217;m not using $.getJSON  because I&#8217;ve had some issues in the past in Firefox with the getJSON method. If you needed to handle errors as well as successes, you would need to use $.ajax with the error and success callbacks.</p>
<p>Okay, so now let&#8217;s look at the data that Rails is going to give us before we write the callback. We know we want to send back 2 partials, and we don&#8217;t want to tie any javascript or DOM knowledge into this, so here&#8217;s the approach. We are using the Rails helper method &lt;%= events_path %&gt; to direct us to our index method, so we&#8217;ll use respond_to to detect the javascript call.</p>
<pre><code>class EventsController &lt; ApplicationController

  def index
    ## do your logic here, for example:
    if params[:start_date].present? and params[:end_date].present?
      @events = Event.all.between(params[:start_date], params[:end_date]) ## between would just be a named scope that adds date conditions
    else
      @events = Event.all
    end

    respond_to do |format|
      format.html # render default index.erb
      format.js {
        render :json =&gt; { :list =&gt; render_to_string(:partial =&gt; "events/list"), :calendar =&gt; render_to_string(:partial =&gt; "events/calendar") }.to_json
      }
    end
  end

end</code></pre>
<p>So there are a few things this controller method is doing that are outside the scope of this article, such as using named_scopes, the respond_to block, and render_to_string &#8212; all of which can be found documented in the Rails API reference. The main thing we&#8217;re concerned with here is rendering json so that our keys are usable within our javascript. They are not the same as the id of the div since your controller shouldn&#8217;t care what your DOM looks like. And voila, it really is that easy, simple and clean to build tons of AJAX into your app without making it overly messy.</p>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/updating-multiple-dom-elements-unobtrusively-with-ajax-in-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fluid Icons</title>
		<link>http://jenwendling.com/fluid-icons/</link>
		<comments>http://jenwendling.com/fluid-icons/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 16:09:15 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Random]]></category>
		<category><![CDATA[fluid]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[icons]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=185</guid>
		<description><![CDATA[Rock out. I&#8217;m uploading several high-res Fluid icons for your pleasure. Click Here to Download (.zip) Credits to: Facebook: http://cootelibeau.files.wordpress.com Github: http://github.com/blog/47-new-fluid-icon Mint and Pivotal: http://sneaky.me/2008/11/fluid-app-icons-for-mint-and-pivotal-tracker/ Campfire: http://www.flickr.com/photos/indiekid/2555128022/ Gmail: http://iconexpo.com/ No related posts. Related posts brought to you by Yet &#8230; <a href="http://jenwendling.com/fluid-icons/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Rock out. I&#8217;m uploading several high-res Fluid icons for your pleasure.</p>
<p><a href="http://jenwendling.com/wp-content/uploads/2009/11/fluid_icons.zip" target="_blank">Click Here to Download</a> (.zip)</p>
<p>Credits to:</p>
<p>Facebook: <a href="http://cootelibeau.files.wordpress.com" target="_blank">http://cootelibeau.files.wordpress.com</a></p>
<p>Github: <a href="http://github.com/blog/47-new-fluid-icon" target="_blank">http://github.com/blog/47-new-fluid-icon</a></p>
<p>Mint and Pivotal: <a href="http://sneaky.me/2008/11/fluid-app-icons-for-mint-and-pivotal-tracker/" target="_blank">http://sneaky.me/2008/11/fluid-app-icons-for-mint-and-pivotal-tracker/</a></p>
<p>Campfire: <a href="http://www.flickr.com/photos/indiekid/2555128022/" target="_blank">http://www.flickr.com/photos/indiekid/2555128022/</a></p>
<p>Gmail: <a href="http://iconexpo.com/" target="_blank">http://iconexpo.com/</a></p>
<p><a href="http://jenwendling.com/wp-content/uploads/2009/11/fluid_icons.zip" target="_blank"><br />
</a></p>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/fluid-icons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails Collection Blocks</title>
		<link>http://jenwendling.com/rails-collection-blocks/</link>
		<comments>http://jenwendling.com/rails-collection-blocks/#comments</comments>
		<pubDate>Sun, 07 Jun 2009 19:19:21 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=138</guid>
		<description><![CDATA[My great friend and mentor Jake Dempsey is always preaching about code readability and keeping logic out of views, etc, and therefore he&#8217;s always writing nice little helpers to do some of the magic &#8212; for instance, collection_content_for(collection) which will &#8230; <a href="http://jenwendling.com/rails-collection-blocks/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>My great friend and mentor Jake Dempsey is always preaching about code readability and keeping logic out of views, etc, and therefore he&#8217;s always writing nice little helpers to do some of the magic &#8212; for instance, <strong>collection_content_for(collection)</strong> which will takes a block and will only render that block if that collection is not empty.</p>
<p>Now, it&#8217;s my turn to give back:</p>
<p>I wanted something completely reusable, simple and easy-to-read that would allow me to iterate over a collection, whilst producing an html block of content specific to the type of object in the collection. Understand? No. Okay then, here you go:</p>
<h3>BEFORE</h3>
<pre><code>&lt;% if @blog_posts &amp;&amp; @blog_posts.size &gt; 0 %&gt;
  &lt;% @blog_posts.each do |blog_post| %&gt;
    &lt;div class="blog_post"&gt;
      &lt;%= link_to blog_post.title, blog_post %&gt;
      &lt;%= truncate blog_post.content, :length =&gt; 500 %&gt;
    &lt;/div&gt;
  &lt;% end %&gt;
&lt;% end %&gt;</code></pre>
<p>That&#8217;s a lot of ugliness, logic, just &#8212; ugh.</p>
<p><span id="more-138"></span></p>
<p>Now, mind you, I am fully aware of the ability to do partial rendering to achieve the same affect &#8230; i.e.</p>
<pre><code>&lt;%= render :partial =&gt; @blog_posts %&gt;</code></pre>
<p>But, I have some objects that don&#8217;t even have controllers much less views, especially when they&#8217;re associated to other things (like photos for instance &#8230; no controller, no views, but I&#8217;d like to render all of the photos for a certain object)</p>
<p>Introduce collection_content_each_tag.</p>
<pre><code>def collection_content_each_tag(collection, tag_name=:div, &amp;block)
  return unless collection &amp;&amp; collection.size &gt; 0
  collection.each do |item|
    concat("&lt;#{tag_name.to_s} class=\"#{item.class.name.underscore}\"&gt;")
    concat(capture(item, &amp;block))
    concat("&lt;/#{tag_name}&gt;")
  end
end</code></pre>
<p><strong>NOTE:</strong> Only in recent versions of Rails does #concat not want you to pass the binding argument &#8212; If you&#8217;re running older versions of Rails, make sure that on each of the #concat methods above, you add block.binding as a second argument.</p>
<p>So what is this method doing? Well I&#8217;ll tell you. Say for instance you have a collection of photos and you want to generate a div containing each photo and its caption.</p>
<h3>AFTER</h3>
<p><code> </code></p>
<pre>&lt;% collection_content_each_tag @photos do |photo| %&gt;
  &lt;%= image_tag photo.public_filename(:thumb) %&gt;
  &lt;%= photo.caption %&gt;
&lt;% end %&gt;</pre>
<p>The method loops over @photos creating a div, (defaults to :div, but you could pass :span, :p, whatever as your second arg), and generates your html tag with your block elements inside. The photo block argument in this example represents an item in the @photos collection, which gets passed to the block. So our output is:</p>
<p><code> </code></p>
<pre>&lt;div class="photo"&gt;
  &lt;img src="/photos/0001/photo_1_thumb.jpg"/&gt;
  Is this not the most gorgeous flower you've ever seen?
&lt;/div&gt;

&lt;div class="photo"&gt;
  &lt;img src="/photos/0002/photo_2_thumb.jpg"/&gt;
  A panda loose in Brooklyn.
&lt;/div&gt;</pre>
<h3>EXTEND IT</h3>
<p><strong>Add an id attribute on your tag with the object id in it:</strong></p>
<pre>def collection_content_each_tag(collection, tag_name=:div, &amp;block)
    return unless collection &amp;&amp; collection.size &gt; 0
    collection.each do |item|
      concat("&lt;#{tag_name.to_s} id=\"#{item.class.name.underscore}-#{item.id}\" class=\"#{item.class.name.underscore}\"&gt;")
      concat(capture(item, &amp;block))
      concat("&lt;/#{tag_name}&gt;")
    end
end</pre>
<p>Would give you:</p>
<p><code> </code></p>
<pre>&lt;div class="photo" id="photo-1"&gt;
  &lt;img src="/photos/0001/photo_1_thumb.jpg" /&gt;
  Is this not the most gorgeous flower you've ever seen?
&lt;/div&gt;</pre>
<p>Maybe someone&#8217;s done this before, who knows. But that&#8217;s it, simple, reusable, and easy-to-read. <img src='http://jenwendling.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Happy coding!</p>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/rails-collection-blocks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>When you get really bored, and want to find a problem for this solution:</title>
		<link>http://jenwendling.com/when-you-get-really-bored-and-want-to-find-a-problem-for-this-solution/</link>
		<comments>http://jenwendling.com/when-you-get-really-bored-and-want-to-find-a-problem-for-this-solution/#comments</comments>
		<pubDate>Fri, 17 Apr 2009 06:22:42 +0000</pubDate>
		<dc:creator>jen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://jenwendling.com/?p=128</guid>
		<description><![CDATA[Getting the intersection and lowest values of a hash. def hash_intersect_min(*hashes) hashes.inject(hashes.pop.dup) { &#124;i,h&#124; i.delete_if { &#124;k,v&#124; hv=h[k]; next true unless hv; i[k]=hv if hv&#60;v; false }; i } end So the following: hash_intersect_min({:a =&#62; 1, :d =&#62; 2, :k &#8230; <a href="http://jenwendling.com/when-you-get-really-bored-and-want-to-find-a-problem-for-this-solution/">Continue reading <span class="meta-nav">&#8594;</span></a>


No related posts.

Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.]]></description>
			<content:encoded><![CDATA[<p>Getting the intersection and lowest values of a hash. <img src='http://jenwendling.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<pre><code>def hash_intersect_min(*hashes)
  hashes.inject(hashes.pop.dup) { |i,h| i.delete_if { |k,v| hv=h[k]; next true unless hv; i[k]=hv if hv&lt;v; false }; i }
end</code></pre>
<p>So the following:</p>
<pre><code>hash_intersect_min({:a =&gt; 1, :d =&gt; 2, :k =&gt; 2, :j =&gt; 6}, {:k =&gt;1, :a =&gt; 4, :j =&gt; 4}, {:e =&gt; 4, :k =&gt; 2, :d =&gt; 4, :j =&gt; 9})</code></pre>
<p>Produces:</p>
<pre><code>{:k=&gt;1, :j=&gt;4}</code></pre>
<p>I&#8217;m completely aware of the extreme triviality this introduces to most programming, but ya know what&#8230; sometimes you need quirky crap to get you through the day. <img src='http://jenwendling.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Happy coding!</p>


<p>No related posts.</p>
<p>Related posts brought to you by <a href='http://yarpp.org'>Yet Another Related Posts Plugin</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://jenwendling.com/when-you-get-really-bored-and-want-to-find-a-problem-for-this-solution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

