News

Bringing in the JSON

Added by Matt Platte over 1 year ago

As preparation for making the Photo Tagger project, I attempt to communicate with the server via jQuery/JSON.

It begins with attaching events to buttons (I didn't know about the <button tag!) to raise the alert. Then this stuff begins, never to completely go away. This is the biggest chunk of magic that I'm seeing right now:

      
  //jsonURL = "http://192.168.1.2:3000/feeds.json?callback=?"; // fails in Rails
  //jsonURL = "http://192.168.1.2:3000/feeds.json?callback=Bullhockey"; // works in Rails
  jsonURL = "http://192.168.1.2:3000/feeds.json"; // note: this one works in Rails

... not that any of these are the Right Answer® yet.
Takes a really long time to get JSON from the Rails into the page. Not knowing how to debug Javascript doesn't help. Not knowing what's busted doesn't help. Silent failure isn't my friend. Once I get something all the way from Rails to visible-on-the-page I then look to building a select/options control.

And building that select control took considerable time. Eventually settled on constructing HTML tags instead of using the Javascript Option object. Might come back to that sometime. Delays all along the way because of the callback magic mentioned above.

Eventually I have a chunk of Javascript/HTML and a feed_controller in Rails that more or less talk to each other. Lots of trial and error. Then more trial and error. One thing I notice is that while LiveHTTPHeaders doesn't show the delivery package, it does indicate its size. By altering the data I send to the server I get confirmation that Rails is actually returning the desired object on a successful save into the database. There should be a better way....

Sample code that kinda works:

<script type="text/javascript">
  $(document).ready(function(){
    console.log("_1 document ready");
    larry();
    $('#pik').bind('click', pikker);
    $('#rik').bind('click', rikker);

  }); // doc.ready
    /* [
    {"feed":{"title":"Walla","id":1,"description":"The long divide"}},
    {"feed":{"title":"Wander","id":2,"description":"Along the riparian road"}},
    {"feed":{"title":"Wishful","id":3,"description":"Daydreams in the meadow"}}
    ] */
  function larry(){
    var stURL = "http://192.168.20.2:3000/feeds.json?callback=?";
    console.log("stURL=" +stURL);
    $('#stutton').click(function(){
      $.getJSON(stURL, function(data){
        var htm = '<option value=""></option>';
        $.each(data, function(i,slug){
//          $("#millertime").append('&lt;option>* '+slug.feed.title+'&lt;option>');
          $("#millertime").append('.');
          htm += '<option value="'+slug.feed.id+'">'+slug.feed.title+'</option>';
        }); // .each
        $("#sally").append(htm);
      }); //getJSON stURL
    }); //stutton.click
  }; // larry
  function pikker(){ 
    console.log("Ahahahah pikker!");
    var postURL = "http://192.168.20.2:3000/feeds.json";
    var drek = $("#pikform").serialize();
    console.log(drek);
    $.post(postURL, drek, function(data){
        console.log("pikker got something back from the serva!");
      });

  }; // pikker
  function rikker(){ 
    console.log("Why hello, rikker! Yes, you may read my comics.");
    var postURL = "http://192.168.20.2:3000/feeds.json";
    var drek = $("#pikform").serialize();
    console.log(drek);
    $.ajax({
      type: "POST",
      url: postURL,
      data: drek,
      success: function(){
        console.log("okay");
      }
    });
  }; // rikker
</script>

<h3>Call and Respond</h3>
<p>This form gets posted to the Rails database, to populate the select control below.</p>
<div id="success" style="display:none;">Aha!</div>
<table><tr><td>title</td><td>description</td><td>buttons</td></tr><tr><td>
<form id="pikform">
  <input id="feed_title" type="text" name="feed[title]" /></td><td>
  <input id="feed_description" type="text" name="feed[description]" /></td><td>
</form>
<button id="pik">&nbsp; pik &nbsp;</button>
<button id="rik">&nbsp; rik &nbsp;</button>
</td></tr></table>

<h3>How To Read JSON Using JQuery</h3>
<p>From this 
<a href="http://webhole.net/2009/11/28/how-to-read-json-with-javascript/">tutorial</a> 
that describes pulling stuff from Twitter's API.  I cloned the above, but pointed 
it to my test JSON feed at jsonURL ~= "http://192.168.20.2:3000/feeds.json?callback=Bullhockey".</p>
<table><tr><td>
<button id="stutton">&nbsp; stutton button &nbsp;</button></td><td>
<div id="millertime"></div></td><td>
<select id="sally"></select></td></tr></table>
<pre> e n d</pre>

Wow, the nested <pre> tags above didn't fail!

Baby steps with a debugger

Added by Matt Platte over 2 years ago

I reckon I've never even wanted to use a Ruby debugger, at least not that I can recall. TMI perhaps. Should the occasion arise, however, this little recipe looks quite simple, simple enough for me.

http://groups.google.com/group/georuby/browse_thread/thread/a3769f9b0adbf018/6069975a476fa084?show_docid=6069975a476fa084&pli=1

Daniel Cohen wrote:

To identify where thing are going wrong, try a debugger. Install rdebug: (gem install ruby-debug). Right before application_controller line 14, type "debugger" to make a breakpoint. Then restart your app using rdebug: "rdebug script/server". Here's a nice resource to get going with rdebug: http://cheat.errtheblog.com/s/rdebug/ .

Baseball-card tiles with HTML and CSS

Added by Matt Platte over 2 years ago

Two sources:
http://www.communitymx.com/content/article.cfm?cid=27f87
and
http://stackoverflow.com/questions/827683/side-by-side-list-items-as-icons-within-a-div-css

I initially wanted to apply this technique to the "Projects" page here at drhf.triopticon so's the projects would all appear "above the fold" - at least until there are many more projects.

Click away, click away, click away, Dixieland

Added by Matt Platte over 2 years ago

Real hyperlink artists know that paradoxically, the more people are tempted to click away from your content, the more they want to keep coming back. There is a set of tradeoffs involving compactness, temptation to click, foreshadowing to eliminate surprise (and retain the reader), and altruism in passing on the reader. But the medium is friendlier to generosity in yielding the stage. This yielding the stage metaphor is important and we will come back to it.

Yeah, more good stuff like that. Must absorb.

Amitabh stared down grimly from a ratty old Sholay poster.

(a version of this solution, curiously, has been available to comic-book artists. If the sentence above had been the caption of a panel showing a boy staring at an Amitabh Bachchan Sholay poster, you would have achieved nearly the same effect)

Parallel request to HTTP Services

Added by Matt Platte over 2 years ago

Amazon CTO Werner Vogels... states that when a user visits the Amazon.com home page it calls out to up to 100 different services to construct the single page before returning it to the user. I [Paul Dix] like Amazon's approach of a services architecture, specially AWS, and wondered if I could do the same thing in Ruby. Typhoeus is the result of that effort.

http://www.pauldix.net/2009/05/breath-fire-over-http-in-ruby-with-typhoeus.html

ActiveSupport in IRB

Added by Matt Platte over 2 years ago

http://www.adminmyserver.com/articles/activesupport-outside-rails

require 'rubygems'
require 'activesupport' unless ENV['RAILS_ENV']

Cucumber Factory

Added by Matt Platte over 2 years ago

I'd seen something like this before but for me, right now, this klass = eval(model_str) is still a bit Cargo-culty. I'm going to use it anyhow.

http://cassiomarques.wordpress.com/2009/04/16/a-cucumber-step-to-generate-any-number-of-objects-for-any-model/

Given /^there are (\d+) (.+)$/ do |n, model_str|  
  model_str = model_str.gsub(/\s/, '_').singularize  
  model_sym = model_str.to_sym  
  klass = eval(model_str.camelize)  
  klass.transaction do  
    klass.destroy_all  
    n.to_i.times do |i|  
      Factory(model_sym)  
    end  
  end  
end  

Now it seems to me that fussing with camels and singularize could be avoided by simply adopting the convention of saying in Cucumber

Given in cowbell there are 7 instances of Cowbell

Which could be matched by something like the following. I put this here because earlier today I wanted to figure out this very same non-magical technique and I failed.

Given /^in (.+) there are (\d+) instances of (.+)$/ do |model_symbol, n, model_name|  
  model_sym = model_symbol.to_sym  
  klass = eval(model_name)  
  klass.transaction do  
    klass.destroy_all  
    n.to_i.times do |i|  
      Factory(model_sym)  
    end  
  end  
end 

But this might not even work for all I know.

Console Controller

Added by Matt Platte over 2 years ago

1

http://snippets.dzone.com/posts/show/600
It seems like a simple task, but here's how you can simulate the calling of a controller's action:

ruby script/console

irb> require 'action_controller/test_process'
irb> require 'application'
irb> require 'site_controller'
irb> request = ActionController::TestRequest.new
irb> response = ActionController::TestResponse.new
irb> request.env['REQUEST_METHOD'] = 'GET'
irb> request.action = "late_employee" 
irb> InfoController.process(request,response)

2

http://errtheblog.com/posts/41-real-console-helpers
...let’s think about this. It’s just Ruby, right? If we think back to our studies, we may remember the extend method. From the Pickaxe: “The Object#extend method adds the methods in its parameter to its receiver.” Erm, right. So we can add the methods from our target to our receiver. Let’s add the methods from ApplicationHelper to helper then, yes?

>> helper.extend ApplicationHelper
=> #<Object:0x2572f68>
>> helper.application_helper_method
=> true

ecommerce explained

Added by Matt Platte almost 3 years ago

http://philip.greenspun.com/panda/ecommerce

"...companies that have always sold wholesale may initially see the Internet as a great opportunity to cut through layers and get directly to the consumer. Yet the cost of building a sales tax compliance department may wipe out many years of profits from Internet sales."

This article (chapter of a book, apparently) chronicles the pitfalls for the early adopter, in this case setting up ecommerce for a smallish prototype charity store as well as a more robust system for a Fortune 500 client. Strangely enough, the few hyperlinks I clicked on are still alive, helping to make this chapter still relevant despite its age.

Accessible to the non-technical audience, this chapter is a must-read for a starry-eyed entrepreneur wanting to set up an Internet store. While providers have changed and rates are no doubt different, having an awareness of sales tax and the many hoops involved in a "simple" credit card transaction should serve as a sobering back-to-reality call for the uninitiated.

Also available in: Atom