Cooler

This page is for random comments, discussion, etc.

Questions for the Dec. 17 Panel go here: http://e168f08.plugh.org/cooler/panel-of-rubyrails-professionals-dec-17/ (same password as for downloads)



Viewing 162 Comments

    • ^
    • v
    John, can we talk about employment with RoR?
    • ^
    • v
    Yes, by all means. Why don't you ask some questions right here.

    Here are some brief notes on getting a Rails job:

    0. The course is good for looking for a job, but it would be a component in a whole package involving who you know, what you know, and how you grow as a developer.

    1. Who: You really should start networking by going to meetings of the Boston Ruby Group (http://bostonrb.org/). For women, e-mail Amy about her new group for Women and Ruby and Boston.

    2. What: I would advise everyone to start downloading and reading code. There are countless awesome Ruby/Rails packages you can find at RubyForge and/or Github. What you want to find are full apps. Then go over the code. Also, you may well find projects that need documentation or light fixes. You would be amazed at how many sophisticated projects have open tickets that are essentially one-line fixes. To learn how to contribute patches and fixes, Google for a screencast on using Github.

    3. Growing: You need to think of your developer status as a work in progress. Make a list of things to learn. E.g., if you've never configured a Linux system, learn by doing it. If you've never used source control (e.g., subversion), set it up. If you've never used a bug tracker, set it up. All of these tools can be useful for your personal use.
    • ^
    • v
    This sounds like a plan.

    Having been laid off mid last week, a new adventure begins. I want to use this time to retool.

    The calculus I am trying to solve is how long it will take for me to become employable in RoR. It seems to me, 6 to 18 months.
    • ^
    • v
    Off-topic, did anyone else rsvp to that 4-week rails class at sermo that John forwarded a few days ago? I haven't heard anything back and was wondering if anyone knows if it's actually happening.
    • ^
    • v
    Rakefile not getting packaged?
    Hi, I am trying to rake package to submit but for some reason the rakefile isn't getting packaged up. It seems to be the only file that's missing. The weird thing is, it's in the package directory but it's not in the .zip. (I'm using the zip_in_ruby script that came with metricsmine)
    • ^
    • v
    Strange.

    The e168:submit task uses the standard rake package target, so it should be grabbing the Rakefile normally.

    I just verified the e168:submit task, but I'm on a Mac.

    Just ZIP up your project with any tool -- or, if you like, use the e168:submit task and zip up the Rakefile separately.
    • ^
    • v
    last minute cleaning-
    I was making the code clean now few things don't work and I do not know why.

    My logout does not logout anymore -
    Console shows that email is genereated and sent, but i never get in my inbox.
    • ^
    • v
    Nothing is really coming to mind -- sorry!
    • ^
    • v
    Would it be possible to get some more information about what the write up for the final project should contain, or maybe an example of what the write up should look like? I've got my project just about done, but I'm lost on the write up.

    Thanks
    • ^
    • v
    Pat,

    I just sent an e-mail out on that topic. I covered some of the expectations here: http://e168f08.plugh.org/assignments/final-proj...

    As far as length, "what it should look like," etc.: The key is to think about the audience. The audience is a developer like yourself who must understand (1) What the app is supposed to do; and (2) how it is implemented. If you are like me, this is a high standard -- I personally need very clear and complete documentation to understand someone else's work.

    John
    • ^
    • v
    Quick question about links/routes/atom feeds:

    I'm exposing an atom feed for a user at the url: http://localhost:3000/posts/feed/username.atom

    In my posts controller:
    def feed
    @user = User.find_by_login(params[:id])
    @posts = @user.posts.find(:all, :order => :created_at).reverse
    respond_to do |format|
    format.html
    format.atom
    end
    end

    Now in the html I want to put in an link tag using <%= auto_discovery_link_tag :atom, {:controller=>:posts, :action=>:feed, :id=>@user.login }, {} %>

    But that gives me
    http://localhost:3000/posts/feed/username
    instead of
    http://localhost:3000/posts/feed/username.atom

    Is there any way I can get the suffix in there?
    • ^
    • v
    auto_discovery_link_tag :atom, { :controller => :posts, :action => :feed, :id => @user.login, :format => :atom } %>
    • ^
    • v
    Fantastic, thanks!
    • ^
    • v
    Where is everybody?

    Can anyone suggest a good summary of the differences between all the different ajax remote tags and when to use which?

    Thanks.
    • ^
    • v
    In order to get a decently populated database I decided to try Hpricot's rival, Nokogiri for html scraping. I'm puzzled as to how to point the parser to a directory of docs as opposed to individual documents. It can't be too different from the way Hpricot does it. Has anyone had experience with this? Thanks.
    • ^
    • v
    How do you do it in hpricot?

    My experience with Nokogiri is that it's not quite there yet.
    • ^
    • v
    Here's my code from file asanas_helper.rb:



    require 'rubygems'
    require 'open-uri'
    require 'nokogiri'

    module AsanasHelper
    def self.feed

    doc = Nokogiri::HTML(open('http://www.yogabasics.com/asana/postures/*.html')) #this doesn't work.

    poses = doc.search('/html/body/div/div/div/div[5]/div[div/div/span/@class="pathway"]')

    postures = []

    poses.each do |pose|

    english = pose.search('span[@class="pathway"].first').text
    . . . .
    postures << {:message => "searching yoga plexus", :english => english, :sanskrit => sanskrit, :basic_instruction => basic_instruction} #:difficulty => difficulty, , :benefits => benefits, :contraindications => contraindications
    end

    return postures

    end
    end
    • ^
    • v
    If you can get that to work with hpricot, do it with hpricot -- I wasn't aware that you could glob (*.html) with hpricot in the first place.
    • ^
    • v
    Nokogiri seemed simpler to me and the reviews seemed quite positive. I never tried Hpricot. The glob I wrote was just to show what I was trying to achieve, although I understood that wasn't the way to do it. I guess what I'm asking is, how would you suggest handling this in ruby? Would I need to use "mechanize"?
    thanks
    • ^
    • v
    If you want to scrape only, use hpricot or nokogiri. If you want to "click buttons" on a live web site, and follow links, etc., then you would additional want to use Mechanize.

    In your case: Use hpricot or nokogiri.
    • ^
    • v
    You say something like:

    filenames = Dir.glob("*.html")
    filenames.each do |filename|
    doc = Nokogiri::HTML(open(filename))
    end

    see http://www.ruby-doc.org/core/classes/Dir.html#M...
    • ^
    • v
    • ^
    • v
    I'm having a problem where my application needs to update around 3000 rows , and it's doing it slowly. Any ideas to speed things up? I've removed the updated_at timestamp, which helps a little, but it still takes 5 to 10 seconds. I looked at update_all but there's no pattern that the updates follow. The update SQL command the server prints out say it's updating two integers where id = the id
    • ^
    • v
    You need to paste in your code.
    • ^
    • v
    I collected the Word table rows in an array, and wrote them out like this:
    save_these_words.each { |each| each.save }

    I read Time.now before that statement and again aftewards, and it confirms that this is the major bottleneck. (The value is 6.8 seconds)

    In the ouput of script/server there are a bunch of these lines:
    UPDATE "words" SET "current_index" = 816, "current_position" = 19239 WHERE "id" = 2166

    A bunch print out at once, there's a pause, then another bunch, etc, for around 5 seconds, for roughly a thousand rows from id=1300 to id=2300. There is a lot of hard disk activity too.
    • ^
    • v
    Must you save every single word? Or can you be more selective?

    How much RAM is on your computer?
    • ^
    • v
    Forgot to mention, the Word table in question has a text column, 4 integer columns, and a creation timestamp column, if that informatoin is helpful
    • ^
    • v
    George -- I wrote a little simulation app like yours (similar columns) that updates 3000 rows.

    The total time to update 3000 rows, row by row, in Sqlite3, is: 60 seconds.

    I also tried it on MySQL: 47 seconds.

    You are updating each row separately. 3000 / 60 is 50, so you're updating 50 rows per second.

    I don't know enough about your application to know what to recommend. What does your application do? Does this need to happen very frequently? Or can it happen once a night or once per hour? If the answer is "Yes," then you should run this update code periodically with a scheduled task or cron job.

    Does the data need to be access immediately after it is updated? If the answer is "no," you could update the data asynchronously with Workling (see http://github.com/purzelrakete/workling/tree/ma...)

    Does the data need to be accessed "row-wise" or do you tend to want to grab all 3,000 rows each time? If the answer is the latter, then the data should not be kept in rows. Let us say that it is a Hash, and you want to grab it once, update the 3,000 items, and save it back at once. What you would want to look at is the ActiveRecord "serialize" feature which allows for saving a big object as one column value. If you want to know more about this, let me know.

    If it is the former -- the data has to be accessed row-wise, and you also need to update 3,000 rows at a time -- we should talk.
    • ^
    • v
    I serialized the rows, and it seems to be much quicker now
    • ^
    • v
    Very good. Did you use a "text" column for the data?
    • ^
    • v
    yes
    • ^
    • v
    All these geniuses like Philadelphia ready to deploy already, and me still struggling to get through my darn multiple model forms, ain't even touched ajax yet... Are there any more schmo's out there? Please, normal dufuses, tell me you're alive!
    • ^
    • v
    Amy set me straight in about 10 minutes. ps. please don't take me seriously; I was joking around. In the words of steve martin: soooooorry!
    • ^
    • v
    Hi there! Busy at work here. Things are rolling along. Lots of heavy lifting, but gradually getting there.

    Quick comment on setting up the external site. My Ubuntu server on slice did not come with 'make'. I used "sudo apt-get install build-essential" to install the gnu compiler, after which all worked well.

    I may have missed a step in the tutorial. Perhaps this will help a classmate.

    Take care,
    Mike
    • ^
    • v
    OK.. spoke too soon. Mongrel installed by sqlite3-ruby complains about " No rule to make target `ruby.h'".

    Googling now.

    Mike
    • ^
    • v
    I found that if I first get the sqlite3 lib with " sudo apt-get install libsqlite3-dev", then the "sudo gem install sqlite3-ruby" works fine.

    Mike
    • ^
    • v
    I am SO CONFUSED! ARRRGGGGh!

    My Sequence form is the most complicated. In a single region I need to have:
    one form that just wants to collect preferences (pose type and pose subtype) so the app can narrow what's listed in the next section. If the user selects either type or subtype the next section will list only the poses that are children of that type/subtype. If the user selects both type & subtype the list will include only poses in both sets (overlapping). I want to do something like <% form_tag {:action =>"accept_asana_categories_and_return_asanas", :id => @asana_type } do %>.. but instead of choosing just @asana_type I want to return either/both asana_type and asana_subtype as parameters to "accept_asana_categories_and_return_asanas".

    Any ideas as to how to accomplish that?

    The next form needs to list a collection of asanas based on the first form's returned parameters, types/subtypes; each pose is a link that will create a new row in the join table, asanas_sequences. Ultimately when Ajax comes in (I haven't even been able to think about Ajax yet!) the list of poses will update automatically.
    • ^
    • v
    In order to get done (as a friend of mine said in her speech for her graduating class, being done means being "sufficiently cooked"), can you eliminate the pose subtype?

    Then it might be a lot simpler.
    • ^
    • v
    So I've discovered what seems to be a pretty serious gotcha:

    If we have the following model:

    class User < ActiveRecord::Base
    belongs_to :clinic

    we can say things like:
    validates_presence_of :clinic

    but we can't say:
    validates_uniqueness_of :login, :scope => :clinic

    instead we have to say
    validates_uniqueness_of :login, :scope => :clinic_id

    since the "belongs_to :clinic" in the migration for the user model creates a column called "clinic_id" not "clinic".

    This seemed very counter-intuitive, and took me a number of hours to debug so I thought I would post for others.
    • ^
    • v
    OK, but this will say you can have two users with the same logins but associated with different clinics. Is that ok?

    I.e., 'john' for clinic #1, 'john' for clinic #2.
    • ^
    • v
    Yup. That's exactly the intent. :-)
    • ^
    • v
    Heres's a way to easily pick out syntax errors in your code: Go to http://blog.hungrymachine.com/2008/06/04/rake-t..., and copy the code to a new file in lib/tasks. Name the file check.rake or something ending in .rake. I surrounded the code in a 'namespace :check do' block (after the require statements) so I can just run rake check:check_syntax from the command line and it checks all my code for syntax! It's beautiful.
    • ^
    • v
    Can you write multiple routing statements about the same model?, eg
    map.resources :sequences
    map.resources :sequences, :member => { :get_postures => :get }
    map.resources :sequences, :has_many=>:user_observations
    • ^
    • v
    that was a really stupid question and I tried to delete it but no go. No wonder Anne wanted to start a separate google group! I couldn't figure it out until I realized that once you post a comment here, it's impossible to delete it. Now everyone knows I'm a schmo.
    • ^
    • v
    The more stupid questions, the merrier -- especially if you then answer your own question!!
    • ^
    • v
    Hi,
    How can I add a standalone class to RoR ? I have some source code which I wrote, it works perfectly as a script, there is a class called "IMDB" which, you guessed it, scrapes IMDB for content. I run it from the command line or with a wrapper, but want to get it into my rails site. Where do the files go, and how do you "require" them in the right place?

    (I'm a C++ developer and can't believe that ruby would have an obvious solution to this too)
    • ^
    • v
    Put in the lib/ directory -- it will be loaded automatically.
    • ^
    • v
    duh ... should have known
    • ^
    • v
    Hi -- I'm playing with a model, "Sequence", that should have no existence independent of its collection of objects. Validation is tricky here because the model, Sequence, has no attribute that correlates with its collection. It has a has_many :through relationship to "Asana". I don't want to allow any new Sequences to be created without at least one asana associated with them. How would one validate such a thing? Thanks!
    • ^
    • v
    Could you write out the model names and give all of the associations? E.g.,

    Sequence: has_many :somethings
    Sequence: has_many :asanas, :through :somethings

    That kind of thing.
    • ^
    • v
    Sure.

    AsanasSequences is the join table. I implemented acts_as_list so that users could rearrange the order of postures in their sequences. The actual name of the association I want to validate in Sequence.rb is "postures", and each of these is an instance of AsanasSequences that relates to one of the asanas.

    To access the properties of an asana in a Sequence named sequence1 you need to use sequence1.posture.asana.

    Here is the class def for Sequence:
    class Sequence < ActiveRecord::Base
    belongs_to :user
    has_many :postures, :class_name => "AsanasSequences", :order => :position
    has_many :asanas, :through => :asanas_sequences
    end

    thanks!
    catherine
    • ^
    • v
    I think first of all you want:

    class Sequence . . .
    has_many :postures, :class_name => 'AsanasSequences', :order => :position
    has_many :asanas, :through :postures

    The value of :through is the name of the ASSOCIATION through which you have many. So here it should be :postures. Maybe it works with :asanas_sequences.

    Now that I see this model: Are you sure you want to disallow a Sequence with no asanas? Why?

    Suppose in my UI I want to create a sequence named "foobar" and then add a bunch of postures -- Right after I create the sequence there would be no associated postures. So it seems to me that it would not be wrong ot allow the collection to be empty.
    • ^
    • v
    thanks, John! Makes sense. It does beg the question of how to validate a model for associated instances, but I clearly don't need to use that at this point. Merry Chanukah/Happy Xmas
    • ^
    • v
    On the "belongs_to" side, you can validate for the key having a value.

    E.g., if a Book belongs_to :user , you would check user_id to be non-null. You can also set that in the migration so AR will enforce it there.
    • ^
    • v
    H there,

    I'm working on some test capabilities for the final project. I want to be able to run a server which will inject messages using HTTP to my WEBrick web service.

    I've created a script which will do this. I can make it run as long as I do not attempt to access any User Defined Classes, for example Classes in my app/models directory.

    I've tried to include the environment by using:

    require File.dirname(__FILE__) + '/../config/boot'

    which is apparently how the script/console and other scripts pull in the Environment variables. The script does not recognize my model classes. If I require them in my script explicitly, I can see them, but if they refer to additional classes (maintained in the lib library), Ruby complains about not being able to find them.

    Is there any way to make this work? Please let me know if you need me to provide more information.

    Mike
    • ^
    • v
    You just want to make requests to your web service? I.e., hit URLs like:

    http://localhost:3000/users/1

    and the like?
    • ^
    • v
    Sort of...

    I have an XML file I read in to pull some specifics about the User and the site to be tested.

    I set up a log file to ouput status.

    I've created 500 or so components in the DB I need to update through HTTP POSTS.

    I've been using: res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) } to do so, from within a Windows Service I built.

    In the Windows Service, I don't need access to the local classes... I'm just pulling a small amount of information from the XML file and from the local PC.

    In the case of the test, I wanted to pull the specific endpoint information from the System Under Test. I can get at the classes to pull information, but one of the ones I need to access implements "acts_as_mappable". This is a class located within the lib/geo_kit directory. Unfortunately, I can't seem to be able to get the script to see this file.

    My next step is to comment out the acts_as_mappable, in my locations model, to see if I can make it work...


    Here's the script so far:

    require File.dirname(__FILE__) + '/../config/boot'
    require 'rubygems'
    require 'activerecord'
    require 'xmlrpc/client'
    require 'win32/daemon'
    require 'net/http'
    require 'uri'
    require "rexml/document"
    require 'user'
    mappable_path = '../lib/geo_kit/acts_as_mappable'
    require 'location'
    require File.dirname(mappable_path)

    LOG_FILE = File.dirname(__FILE__) + '/test.log'

    #here we want to read in the xml config file
    @doc = REXML::Document.new File.new("./config/test_config.xml")

    #open the log file
    File.open(LOG_FILE, 'a+'){ |f|
    f.puts @doc
    }
    #establish the xml doc root
    root = @doc.root
    #grab the user name & pwd for the test
    @user_name = root.elements[1].elements["user_name"].text
    @pwd = root.elements[1].elements["pwd"].text
    @remote_server = root.elements[4].elements["remote_server"].text
    # Initialize ActiveRecord
    config = YAML.load_file('./config/database.yml')

    #grab the development configuration
    spec = HashWithIndifferentAccess.new(config['development'])
    # Uncomment the next two lines if you want to see the SQL
    # ActiveRecord::Base.logger = Logger.new $stderr
    # ActiveRecord::Base.colorize_logging = false
    ActiveRecord::Base.establish_connection(spec)

    msg = 'Testing script started at: ' + Time.now.to_s
    File.open(LOG_FILE, 'a+'){ |f|
    f.puts msg
    }

    url = URI.parse(@remote_server + '/svc/post_kw_reading/')
    req = Net::HTTP::Post.new(url.path)
    req.basic_auth @user_name, @pwd
    #find the locations for the user from the config file
    locations = User.find_by_login(@user_name).locations
    #create an array to hold devices
    devices = Array.new
    #add the devices for the user to the array
    locations.each {|l|devices.push location.devices}


    #start the while loop which will send usage data to the web server
    #appearing as actual clients
    while true

    for device in devices

    #make up some kw and voltage readings
    kw = rand(10)
    volts = 119.5 + rand

    req.set_form_data({:kw => kw, :volts=>Vrms, :guid=>device.guid,:cost=>'0.22'} )

    res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }

    case res
    when Net::HTTPSuccess, Net::HTTPRedirection
    File.open(LOG_FILE, 'a+'){ |f| f.puts res }
    else
    File.open(LOG_FILE, 'a+'){ |f| f.puts 'Error in posting' }
    end
    sleep 60
    end

    end
    • ^
    • v
    Put that script into a class in the lib directory, and define a class method called, e.g., run. e.g.,

    class Exerciser
    def self.run
    # YOUR SCRIPT HERE
    end
    end

    Now from the root you can do

    script/runner "Exerciser.run"

    (Check script/runner in AWDR)
    • ^
    • v
    Yes... I will try that. I have it working in after commenting out two included libraries I had used in a couple of the models. These were:
    acts_as_mappable and uuidtools. Neither of these are required for my current testing. They are used for adding devices and locations.

    So.... will use your idea right now... and let you know how it goes.

    Thanks!
    Mike
    • ^
    • v
    If you do it the script/runner way, you should be able to remove ALL of those requires, etc.
    • ^
    • v
    P.S. Once you do this, you can get at all of your models, everything.
    • ^
    • v
    :-)

    Works like a champ without the requires!

    Thanks!!!
    Mike
    • ^
    • v
    The Ajax examples we've seen in lecture, section, and in AWDR, all involve the controller sending text to be injected directly into the page, either something to go directly into the innerHTML of some element, or RJS sending raw JavaScript to be executed by the browser. This all feels to me like it's skating very close to the boundaries between the View and the Controller in the MVC pattern, although I see that it's not, as long as the controller is well-behaved and only does things like rendering partials or other things in the view directory.

    But this all looks mostly like "AJ" without the "AX". The "standard" way of doing Ajax (or at least the style that I'm used to) involves the server sending DATA (usually structured in some form, hence "And XML") to the browser, to be processed by client-side JavaScript. AWDR mentions the possibility of this in passing, but shows no examples. Can we see some examples of Asynchronous JavaScript AND XML (or AND JSON)? How does the code in the view deal with parsing and/or evaluating JSON or XML returned by the server? For the Ajax-worthy bits of my final project, I can't easily see any way that the view would know which elements of the page to update, without embedding code that more properly belongs in the controller.
    • ^
    • v
    If you use a partial, then the display piece is properly in a view component. I show using a partial in the lecture (the refactoring sequence).

    Also, about the target id:

    Understand that you are clicking on something (triggering a browser event). So, you write view handler code to catch that event, trigger a controller call, and then take the result and shoot it into an element (or its innerhtml) with that id. So the actually move from event to target is all handled in the view, probably where it should be. Indeed, if the controller picked the id, that would strike me as problematic.

    You can send JSON (easily) but I believe that if you want to respond to it in your JavaScript, you are going to have to write that JavaScript manually. Let me check with someone here at the office.
    • ^
    • v
    (I replied to this via the Disqus email reply facility, but it doesn't seem to have shown up; apologies for duplication if and when that reply gets here)

    I see that when using a partial, the distinction between the View and the Controller is being maintained, but at one stage of your first lecture example, the controller is just rendering text to be inserted into the innerHTML of a DOM element, and it seems that it could be very easy and tempting to start rendering actual HTML markup in the controller (or, as in the case of echo_observer1, rendering as text any HTML markup that might be in the user input; a quick browse of the the Rails API and AWDR doesn't show me the usable-by-controllers version of ERB::util#html_escape).

    Regarding the element id. In some cases, it's not always trivial to determine which DOM element should be updated after an Ajax call completes. The element could be different for success or failure, or the result could be dependent on information in a form on the page, which needs to be processed to determine which element (if any) to update. My real-world example here is what I'm thinking about for my FP, where there will be a datetime_select which should be processed to determine which <td> in a calendrical table should be modified. I don't think a view should be doing this kind of processing, but the controller can send back structured information which enables JavaScript embedded in the view to compute the element id.

    Other examples of when one would want to process the reply, instead of simply replacing the innerHTML of an element, would perhaps be when the contents are large and unchanged, and one just wants to modify attributes of that element, e.g. style.
    • ^
    • v
    "a quick browse of the the Rails API and AWDR doesn't show me the usable-by-controllers version of ERB::util#html_escape".

    Duh. That's because it's part of core (non-Rails) Ruby. Improved code for echo_controller:

    def echo_observer1
    render :text => CGI.escapeHTML(params[:echo_observer_text])
    end

    and, correspondingly, in the views, (echo1.html.erb and the partial view _echo_text.html.erb), there should be an 'h':
    <%=h echo_text %>
    • ^
    • v
    But why not use a partial for the render (and thus preserve the MVC distinction) and then you don't have to escape HTML, etc. (?)
    • ^
    • v
    Well, of course you still need to escape the HTML, in the view.
    I agree that using a partial is better, because it preserves the VC distinction. I was commenting on the intermediate stage in the lecture ajax-refactorying example, where the echo_observer1 action renders text directly. This is a good argument against rendering text.
    • ^
    • v
    It depends on the text!
    • ^
    • v
    I feel like we're going around in circles here. What it boils down to, I think, is that you're either rendering a partial, thus clearly preserving the MVC distinctions; rendering structured data of some sort (e.g. XML or JSON), following the classic Ajax pattern; or rendering text, which is either plain text (which you'd better escape) or HTML (which steps across the distinction between the controller and the view).
    • ^
    • v
    Yes.

    I think the best practices are:

    -- Single update of a block of HTML: Use a partial
    -- Single data item, numeric or short String: Possibly render text; probably better to just go with a partial
    -- Update multiple parts of the page: Use RJS
    -- Supply JSON or XML data to Prototype: Render JSON or XML (for XML, possbility use builder)
    -- "Catch" JSON or XML . . . You're on your own. If you use Prototype, at least the methods are based on Ruby iterators.

    The gap is that Rails is good at marshallng data back in XML or JSON, but doesn't give you much in terms of "catching" that data in the view and doing something with it.

    The Rails answer for "how can I update multiple parts of the page" is: Use RJS.

    Incidentally, what is your use case where you want to send data back to the client?
    • ^
    • v
    > The Rails answer for "how can I update multiple parts of the page" is: Use RJS.

    This still feels gross to me, as if it's violating not only the View/Controller distinction, but also the Client/Server distinction. I realize this is probably unreasonable, but the idea of shipping executable code to the client just feels spooky and icky.

    >Incidentally, what is your use case where you want to send data back to the client?

    Adding an event to a calendar, with a simple "add an event" form on the same page as the table holding the calendar. I don't want to re-render the whole calendar, just the one (at most) <td> that represents the date of the event (if that date is within the currently-displayed date range)
    • ^
    • v
    The controller picks the view; the view renders something for the client. The data the RJS template reacts to is supplied by the controller; the RJS template shouldn't be going back to the database on its own.

    Also, since the KIND of executable code exercised on the client is primarily about updating the view, it's arguably still within the responsibility of the view.

    If client-side JavaScript is shipped data (via JSON) and updates the view asynchronously, if you're an MVC purist then you have to be very careful to separate your concerns there as well. So I think really that RJS constrains you in a nice way.

    For the calendar:

    -- If the calendar is displayed in a table, you might as well re-render the entire table, because dynamic table cell updating is uneven across browsers, even with Prototype. I think there's a callout somewhere in AWDR that discusses this a bit.

    -- If the calendar is a list of dates and events: If you display the calendar as a list (ul and li tags), then you can update ":before" or ":after" something, and you should be able to squeeze a new item in at the start or end of the list. Having it update in place (i.e., a new event in between two other events) would require you to have a unique id for each list item.

    In any case, get it working without Ajax first.

    Side issue for anyone who is reading: Incidentally, last night after the panel, Amy told me that I overstressed backwards compatibility / graceful degradation. If you are using an Ajax-only component -- such as Google Maps -- then you certainly don't have to render all of the information in the map when JavaScript is turned off.
    • ^
    • v
    You've got to write your own javascript...
    • ^
    • v
    This would by specifying :complete, :success, and/or :failure callbacks in the invocation of link_to_remote? That's what it looks like in the API doc. Are there any Rails hooks/helpers into Prototype, to keep this JavaScript from being totally raw JS?
    • ^
    • v
    ta
    • ^
    • v
    Ran across an interesting talk about memcached here: http://www.facebook.com/note.php?note_id=393913...

    This gets a bit in-depth, but it is a description of how Facebook is making use of, and modifying, memcached and the considerations in scaling Web 2.0 applications. There seem to be a lot of people out there using ROR to build applications for Facebook.
    • ^
    • v
    We "memcache" everything at our company -- including our FB app.
    • ^
    • v
    I have a question on 1-to-xxx relation that wasn't clear to me.

    If say ModelB has a field that belongs_to :ModelA, must ModelA has a matching has_xxx field ?
    There is a "has_one" and a "has_many". My situation is has_zero_or_one, and I am not
    clear whether has_one means EXACTLY one, though has_many seems to cover the case of 0 to many.

    To repeat myself, just to be clear, say ModelA has fieldA, fieldB, fieldC. fieldB references modelB.
    There are modelB that does not reference any modelA. What relationship should this be ?

    Thanks
    • ^
    • v
    Let me say it a bit differently. Let us start with:

    ModelB belongs_to :model_a

    In Rails, this means that the table underlying ModelB (model_bs) should have a foreign key called model_a_id. That is, a row in model_bs "refers" to a row in the model_as table. In other words, the column model_a_id is a foreign key. ModelB is a "child" of the "parent" ModelA.

    The table model_as does not have a foreign key.

    When we define ModelA, we can say in our association that it:

    has_one :model_b

    OR

    has_many :model_bs

    In the first case, there should be 0 or 1 rows in model_b. In the second case, 0 or more.

    The reason you are having trouble with this is in your last paragraph. You write: "Say ModelA has fieldA, fieldB, fieldC. fieldB references ModelB." But that's not how it works. The foreign key is in the CHILD. The parent model DOES NOT HAVE A FIELD that refers to the child. The only way we can "trace" the relationship between ModelA and ModelB is through the *association* -- the *association* (namely, has_one :model_b or has_many :model_bs) is not about FIELDS. It's about a method that allows you to collect up all of the model_bs.

    Finally, something to think about is whether ModelB (whose underlying table model_bs has the foreign key model_a_id) is allowed to have a null for the value of the foreign key. This is something you would have to decide for your own application.

    I think what I've just written is correct though with names like "ModelA" and "ModelB" I might have gotten something backwards. This is why in the examples I've tried to show somewhat plausible model names like "Book" and "IndexEntry" so that there are some semantics to provide cues as to what is the parent and what is the child.
    • ^
    • v
    Ah, I got the ModelB and ModelA mixed up in my 2nd paragraph, but what you described in your first 10 lines is what I was thinking.

    So, now, I know that
    - "has_one" includes the case of ZERO as well,
    - NULL is allowed for the value of the foreign key

    Thanks
    • ^
    • v
    Yes, but make sure that you understand: The fact that the foreign key can be null has nothing to do with has_one vs. has_many.

    Let's say that model_a is for people, and model_b is for their company: And we say that ModelA has_one :model_b (so a person has 0 or 1 companies - this is not necessarily the way the real world works, but it's how we're going to do it).

    Example:

    Rows in model_a (columns are: id, name):

    1 John
    2 Bill Gates
    3 Steve Jobs

    Rows in model_b (columns are: id, model_a_id, company_name):

    1 1 digital_advisor.com
    2 3 apple
    3 2 microsoft
    4 null ibm
    5 null dell
    6 3 apple
    7 1 beatthat.com

    NOTICE the following facts:

    (1) Even though our association says ModelA :has_one :model_b, it happens that there are TWO rows in model_b where the foreign key is "1" (for John). That is because having just one is not enforced at the database level with more work. I believe Rails will try to enforce the 0 or 1, but if someone forced that row into your table manually, Rails would just bring back one row from model_b when you follow the association from ModelA.

    (2) The rows in model_b with nulls for the foreign key value are essentially "orphans." They don't know to whom they belong.

    Both of these situations (1) and (2) are problematic. If you want to control whether a null is allows in the foreign key in model_b, look at the ":null" option for columns in the documentation-- in AWDR on p. 277. :null seems not to be in the index.
    • ^
    • v
    Thanks.

    What I try to model is slightly different.

    Let's say we want to buy something (a house, perhaps).
    You make an "offer".
    If all goes well, this "offer" results in a "transaction".

    So in my case, the "transaction"(modelB) if one materializes, belongs to an "offer" (modelA)
    An "offer" on the other hand, may or may not result in ONE transaction. If no one buys the house, the "offer" will not have a corresponding.
    The "transaction" will never have null value for its foreign key because it is result of an "offer" made.
    So, I think that I won't be running into the problematic situation (2) for this case.

    Thanks
    • ^
    • v
    Hi there,

    I'm thinking about the final project, and as one of the elements, I'm interested in maintaining minute by minute usage data associated with internet enabled equipment. But I'd like to roll the data up into hours, days, weeks, and years, so that I will not have to maintain hundreds of thousands of rows for each user for each year.

    Is there a best practices way of doing this? I've been thinking about writing it myself using after_save callbacks on a Usage table. But, it's not all together trivial due, amongst other things, to some recursion issues I foresee (I foresee, I foresee, I foresee :-). I'd be very happy to find out someone has already figured this out and has written a gem or plugin...

    Thanks,
    Mike
    • ^
    • v
    What you want to do is collect all of the observations, and then periodically have a process that summarizes the data. Or, if you wanted to do it on the fly -- that's fine, too. But i think you are going to have to hand-roll this process. This is very much like data-warehousing ETL (extract / transform / load).

    The original collection could be into a flat file or into a database table (you would truncate or archive the original data after you summarize it). You would surely want to archive it.

    The standard way to manage rollups is with a table such as the one used in MetricsMine. You are free to use it. Note that that table doesn't have indices. You would want to keep your data in a database such as Postgresql or MySQL which does allow for indexes.

    In any case, the big question for you will be what you want to do with the immediately-collected data before it gets summarized. Will users want to see their data trickle in within the hour?
    • ^
    • v
    They will want to see minute by minute data for the previous 60 minutes. Then hourly averages for the previous day. The daily for the previous 7 days. Then weekly (forever?).

    The difficulty is the missing data... machines go down and so do internet connections. Therefore, the data will have missing elements, which in some cases will span hours, days or weeks. So, I need to be able to handle missing observations as well.

    I'll take another look at the rollups in MetricsMine. I may be able to use some or all of it for this purpose.

    Thanks,
    Mike
    • ^
    • v
    The way to handle missing data is definitely with a rollup table where you use the rollup to "left join" against your data. The 2nd key technique is to put a key in your "data" table that links to the rollups table (this is what happens in MetricsMine -- when an observation is added, a callback is used to grab the right rollup). The naive approach is to have the linkage between the data table and the rollups data to be by the actual time column, but this is not a good practice.
    • ^
    • v
    After reading your comment and thinking about it some more, maybe the best way to handle this is to write to the DB for each event with a timestamp and then report based upon this information. Every week a cron job would run and create weekly average. In that way, the max rows in the table would be 10,800 per user per reporting device. That's not too bad, as long as they are indexed. Most of the reporting will pull the most recent record (greatest timestamp) and will not require a lot of overhead (if it is indexed).

    Thanks,
    Mike
    • ^
    • v
    That sounds good to me. I think a real question is going to be granularity of the initial data, and the smallest size of the initial report. You would have a significant boost if you could make that initial report by even 10-minute intervals.
    • ^
    • v
    After watching this week's lecture this morning, and checking quickly in the Rails documentation, I wonder why there's a helper for Atom feeds, but no helper for RSS. It seems to me that I see lots more RSS feeds on the net than Atom feeds.

    A very quick web search reveals this article

    http://myersds.com/notebook/2006/05/11/how_to_g...

    which seems very clear, which is just using generic Builder to put together the XML for an RSS document, which raises the next question, whether AtomFeedBuilder is providing any real added value, compared to just building an Atom feed out of raw XML
    • ^
    • v
    Atom is a building block for providing much more sophisticated feeds.

    This is a biased account, but will give you some of the flavor for why you might go for Atom:

    http://www.intertwingly.net/wiki/pie/Rss20AndAt...

    This is a big deal: http://www.intertwingly.net/wiki/pie/Rss20AndAt...

    Re: building an Atom feed out of raw XML: If you use the atom_feed helper, then if common usage moves to a different version of Atom, you'll have built your feed using a higher level API, which might get updated -- and then you don't have to dig around in your own home-build XML.

    There is nothing wrong with providing both kinds of feeds. "One resource, many representations." If you include two "auto discovery" links, must feed consumers will give you an option to select (atom vs rss 2.0, etc.).
    • ^
    • v
    Which still leaves the question of why the developer(s?) of Rails included a helper for Atom in the Rails core classes, but chose not to do the same for RSS. The same issue, of common usage moving to a different version, applies.
    • ^
    • v
    Well, one reason might be that there isn't much of a standard for RSS: http://en.wikipedia.org/wiki/Rss#Variants

    If you want to support RSS, which one? Should you expose 0.9 AND 1.0 AND 2.0? Do we need to support ALL of those? There is doubtless a plugin that will do all of that for you; I would bet that DHH would say that Rails, being "opinionated software" advocates Atom . . .
    • ^
    • v
    The documentation for methods in ActionView::Helpers subclasses (e.g. FormHelper, DateHelper) shows a first argument for each method, which is an object_name. But in the examples, and in practice, that argument seems to be optional, and defaults to the object which is the first argument of the enclosing form_for method. E.g. the signature for datetime_select is

    datetime_select(object_name, method, options = {}, html_options = {})

    but in practice we call it as something like

    form.datetime_select :observed_at

    with the implicit @observation (or :observation) as the object, and :observed_at as the method on that object.

    Two questions:

    1) How does this work, from a language viewpoint? Do these methods examine the types of their arguments, figure out that the first argument is the name or symbol of a method rather than an instance variable, and adjust the argument list appropriately?

    2) More importantly, other than by reading AWDR and intuiting the methods' behavior from the code examples, how would we be able to figure out that some arguments (not the trailing arguments, and not those shown with default values in the method signature via an '=' character) are optional?
    • ^
    • v
    1) When you call form.datetime_select, the form already knows what object is in play (because you said form_for, which yields the form variable). So it can delegate directly to the datetime_select which expects an object as the first param. I haven't looked at the source, but that is likely how it is implemented.

    2) The on-line documentation is bad, in my humble opinion, because it underplays what the "form builder" (the variable form_for yields). The docs (http://api.rubyonrails.org/classes/ActionView/H...) say:

    The generic way to call form_for yields a form builder around a model . . . (and they quote an example) . . .

    There, the first argument is a symbol or string with the name of the object the form is about, and also the name of the instance variable the object is stored in.

    [KEY SENTENCE -->] The form builder acts as a regular form helper that somehow carries the model. Thus, the idea is that

    <%= f.text_field :first_name %>

    gets expanded to

    <%= text_field :person, :first_name %>

    -----

    And that is the whole enchilada. You can use any of the form helpers via that "f" or "form" or whatever variable you have assigned to the one yielded to you by form_for.

    The RDoc generator that makes the HTML pages should cross-reference what is happening here so that whenever you're looking at "datetime_select" there is some indicator of how you would use it from form_for; and the idea that the variable form_for yields magically sprouts these methods that delegate can't be overplayed enough.