Posts tagged with rails
Regarding growing up your acts_as_taggable and lack of primary_key
Posted on August 12, 2009 at 07:53 PM
Categories: code, rails
This is a comment on "growing up your acts_as_taggable" post on Evan Weaver's blog snax.... because comments there are closed.
If you are upgrading from an older acts_as_taggable installation and moving to has_many_polymorphs, as I did, your old table will have create_table :id => false. That will be unhappy. You should add this to your migration:
add_column :taggings, :id, :primary_key
And that's all.
Rails "core team" fucks up big time
Posted on June 07, 2009 at 11:03 PM
Categories: tech, code, rails
Hey, if you have a rails app that uses the recently introduced authenticate_or_request_with_http_digest Rails 2.3 / http_authentication.rb, you've got a big fucking security hole. Anyone can log in if they provide a wrong username and no password, or a nil username & password.
Kind of terrible, right?
So Nate posts it on his blog after a week of trying to get the attention of the Rails security people, and they blame him in their security alert:
Due to communication difficulties and a mis-understanding between the reporter and the security team. This vulnerability has been publicly disclosed on several websites, users are advised to update their applications immediately. Steps are being taken to ensure that the security email is more reliable in the future. We regret the nature of this disclosure and will endeavor to ensure it doesn’t happen again in the future.
And they give him no credit. Most of the RCT idiosyncracies I can write off but don't fuck with security.
How to do rails tests when running with restful_authentication
Posted on May 26, 2009 at 01:18 AM
Categories: code, rails, ruby
The Restful Authentication plugin seems to be the standard right now, although I'm staring to wish I'd tried something else, maybe AuthLogic... because restful_authentication is kind of poorly documented. One serious error of ommission is how the hell do you update your tests so that you can run them on controllers that require a logged in user? Well, I have had the pain, and so you can have the quick answer, here it is.
Assuming you are using ActionController::TestCase ... first edit test_helper.rb:
# Add this helper function to test_helper.rb
# It will allow you to run any block under the aegis of
# a controller of your choosing. This is not something
# that is possibly by default
def run_with_controller( controller_class )
old_controller = @controller
@controller = controller_class.new
yield
@controller = old_controller
end
Now you can use that helper method in your test cases, in the setup function do this:
def setup
run_with_controller(SessionsController) do
post :create, { :login => "george", :password => "monkey" }
end
end
What you're doing here is simply making a POST to the Restful Authentication SessionsController to "create" a new session, pass in a login/password that exists in your fixtures. And that's it.
By the way, if you chose to install with RSpec because of the dire warnings that old fashioned tests will be out of date, but aren't currently using RSpec for you other tests, you should copy the rspec fixture data into test/ so that you get the right password hashes. Tricky...
Don't use porn in your slides at a tech conference
Posted on May 15, 2009 at 09:47 PM
Categories: tech, rails, theories, ruby
So Merb developer Matt Aimonetti made a presentation at GoGaRoCu heavily laden with soft-core pornography and some people got upset. In particular, a woman got upset—Sarah Allen. It didn't help that she was one of only six women at a 200 person conference. Holy shit!
Don't put sexual images of women in your slides. If you must do it, then put just as many sexual images of men in your slides. Be fair. Unless of course you're presenting to a club that only allows male members. Which in a way is what pisses off the women who are reacting to this incident—because it implies that Ruby/Rails/whatever is a men-wanted-only club.
If I had been there, I suspect I would have walked out. I've walked out of presentations, movies, plays, etc. for less. I have low patience no pride.
Why the lucky stiff posted a summary of women rubyist's reactions, and there's discussion aplenty there and elsewhere on the net. Hopefully the positive outcome will be a community that is more aware of issues that differ between men and women, and therefore has more women in the future.
sudo apachectl stop && sudo apt-get remove apache2 && sudo apt-get install nginx
Posted on April 30, 2009 at 12:56 AM
Categories: tech, code, rails, internet
I binned apache finally on semacode.com. It was easy. A little bit of "this is really the last straw" frustration with mod_rewrite and I ditched it.
I've been threatening to leave you, apache, for years. Ever since I first cursed your horrid rewriterules, I knew that it would never be the same between us. You were good, once. You weren't just "a patchy" web server, but a scrappy one... once. But 2.0 you just didn't live up. You didn't fix your big warts. You got flabby. Even the decision by your developer team to finally remove the default MIME type didn't redeem you in my eyes.
No, it was just one poke in my eye too many, when you insisted on unencoding my percent encoded URLs before passing them to the rails/mongrel proxy, and there was just no way to make you stop doing it, no matter how many googles I searched. And so I said: enough is enough. Everyone on Rails uses nginx now, and I will too. I'm tired of learning how to sacrifice chickens to the apache configuration gods. Bring me something new, clean, shiny, fast, and easy to configure!
Learning how to configure nginx took an hour on the outside—it's very easy and keeps all the good parts of apache's syntax and throws away the complete crap. It even allows me to compress stupid blocks into one-liners! :
if (-f $document_root/system/maintenance.html) { rewrite ^(.*)$ /system/maintenance.html last; break; }Isn't that gorgeous! I agree. And so the "engine x" russians get my love now. It's all over. Sayanora. End communication.
The better way to code error-handling routines
Posted on April 17, 2009 at 12:50 PM
Categories: code, rails, ruby
There's an excellent guide to Rails 2 that I'm reading through right now, but I don't like this bit:
if @comment.save
redirect_to post_comment_url(@post, @comment)
else
render :action => "new"
end
It's much better like this:
render :action => "new" and return unless @comment.save
redirect_to post_comment_url(@post, @comment)
They do exactly the same thing, but mine is 2 lines instead of 5, and mine clearly eliminates the exceptional/error case first, and then leaves you to see the normal case. In fact, I virtually always code this way when I can, deal with the error cases first, and return, and then the rest of the function is an un-nested normal case handler.
Simplelog-X... is coming...
Posted on April 11, 2009 at 02:50 AM
Categories: meta, rails, ruby, simplelogx
So I just made some major updates to the software running this site, which for now I'm calling "Simplelog-X". And the source code for simplelog-x is now on github.
This will probably interest people who are running the original SimpleLog by Garrett Murray which he no longer supports (and incidentally it doesn't run on Rails 2.x). Simplelog-X also has quite a few other changes aside from working on (presently) Rails 2.2.2, all of the details are in the README.
I'm not going to annouce this loudly just yet because I still have a whole ton of my own site files in the public directory, and I need to move them to public/system I guess and get them out of the repo but still capistrano-friendly.
I was just making a lot of changes and it struck me how much more I know about Rails now than when I started this journey...
Yup.
Got a new server.
The old box, was a Penguin Computing rack-mount purchased in 1999 or 2000. It had a PIII and was totally maxed out RAM-wise—at 512 MB. Anyone who's tried to run rails on a box with that much ram might understand why I had occasional downtime. mongrel would just give up sometimes. Trying to install new gems was fun as well. Still, the old box had a good run.
The new box is a Dell R300... Core 2 Duo... RAM is at 4GB right now, max 24. And we've gone with RAID-1 since we don't really need the space but like the redundancy.
Also, we switched from debian to ubuntu. Ubuntu is a bit less secure but a hell of a lot easier to deal with in terms of package management and installation.
Ruby on Rails Feed/RSS Aggregator (35 lines)
Posted on December 07, 2008 at 03:17 AM
Categories: code, rails, ruby
I wrote myself a feed aggregator for my front page. And... voila! I'm finally satisfied with it to post it.
Update: I've now published this as a complete standalone rails app on github/sbwoodside/portal. The important bits are app/controllers/portal_controller.rb and config/config.yml.
For me I run this as a standalone rails app, separately from my weblog. You could do that (and redirect requests to / or /index.html with Apache or nginx/etc. Or you could integrate it into your own app. Up to you.
Features:
- Will aggregate ANY feed, no matter how badly mangled by the creators, using FeedTools (I also tried feed_normalizer and simple rss but they're not as good)
- Deals with slowness of downloading feeds, RSS, etc., and REXML by caching
- Deals with need to recache using elegant http/cron periodic system
- Display the feeds in a facebook-like news feed format, sorted by dated.
- You can easily re-label the feeds, add and renew feeds (in the code)
- Only 35 lines of controller code!
The heart of it is the controller, obviously. The best thing? It's only one page of code! Ruby rocks!
require 'feed_tools'
class PortalController < ApplicationController
layout 'site'
# Instructions: 1. Change @@secret. 2. Add a cron job to regularly call /?recache=yes&secret=XXXXXXX
# This is a feed aggregator that uses FeedTools because it handles practically any feed.
# But FeedTools is super slow in every way so this aggregator stops using it as soon as possible.
# TODO add XML feed output
@@secret = "change_this" # change this to protect your site from DoS attack
# The array of feeds you want to aggregate. If you change this then manually delete the whole cache.
@@uris = ['http://simonwoodside.com:8080/posts/rss', 'http://simonwoodside.com/comments/rss',
'http://semacode.com/posts/rss',
'http://api.flickr.com/services/feeds/photos_public.gne?id=20938094@N00&lang=en-us&format=rss_200',
'http://api.flickr.com/services/feeds/activity.gne?user_id=20938094@N00']
# A map between the "official" feed titles in the XML, and the titles you want to show when rendered.
@@title_map = { "Simon Says" => "Simon Says:", "Simon Says: Comments" => "Simon Says comment:",
"Uploads from sbwoodside" => "Flickr picture:", "Semacode" => "Semacode blog post:",
'Comments on your photostream and/or sets' => 'Flickr comment:' }
def index
if params[:recache] and @@secret == params[:secret]
cache_feeds
expire_fragment(:controller => 'portal', :action => 'index') # next load of index will re-fragment cache
render :text => "Done recaching feeds"
else
@aggregate = read_cache unless read_fragment({})
end
end
private
# This will replace cached feeds in the DB that have the same URI. Be careful not to tie up the DB connection.
def cache_feeds
puts "Caching feeds... (can be slow)"
feeds = @@uris.map do |uri|
feed = FeedTools::Feed.open( uri )
{ :uri => uri, :title => feed.title,
:items => feed.items.map { |item| {:title => item.title, :published => item.published, :link => item.link} } }
end
feeds.each { |feed|
new = CachedFeed.find_or_initialize_by_uri( feed[:uri] )
new.parsed_feed = feed
new.save!
}
end
# Make an array of hashes, each hash is { :title, :feed_item }
def read_cache
@@uris.map { |uri|
feed = CachedFeed.find_by_uri( uri ).parsed_feed
feed[:items].map { |item| {:feed_title => @@title_map[feed[:title]] || feed[:title], :feed_item => item} }
} .flatten .sort_by { |item| item[:feed_item][:published] } .reverse
end
end
It's actually pretty simple but it took me a while to get the balance just right. What you need to do is set up a cron job or other repetitive task that does an HTTP load on http://mywebsite.com/?recache=yes&secret=XXXXXXXX ... every once in a while. You can use wget or curl, or whatever. You might want to recache every minute, five minutes, hour, whatever. Since it's done as a part of the controller there's no nonsense about running backgroundRB, RubyCron and all the other nonsense at HowToRunBackgroundJobsInRails. Yay!
Here's the view:
<div id="feed-stream">
<% cache do %>
<%
lastday = -1
@aggregate.each do |item| %>
<div class="item">
<%
mydate = item[:feed_item][:published].getlocal
if mydate.yday != lastday
%><div class="item_details"><p style="text-align:right"><%= mydate.strftime('%A, %B %e') %></p></div><%
lastday = mydate.yday
end
%>
<div class="item_content">
<%= item[:feed_title] %>
<a href="<%= item[:feed_item][:link] %>"><%= item[:feed_item][:title] %></a>
</div>
</div>
<% end %>
<% end %>
</div>
My cache is all Hashes. I don't cache the FeedTools object because I discovered that even after FeedTools has parsed your feed, accessing the supposedly "final" data is incredibly slow (like maybe 10x or 100x slower than a hash).
Here's the model:
require 'feed_tools'
class CachedFeed < ActiveRecord::Base
validates_presence_of :uri, :parsed_feed
validates_uniqueness_of :uri
serialize :parsed_feed, Hash # note that if this exceeds a certain KB size, it will likely fail (thinking it's a String)
end
And the migration:
class CreateCachedFeeds < ActiveRecord::Migration
def self.up
create_table :cached_feeds do |t|
t.column :uri, :string, :limit => 2048
t.column :parsed_feed, :text, :limit => 128.kilobytes # use for serialized object
t.timestamps
end
end
def self.down
drop_table :cached_feeds
end
end
Well, that's all you need. When I started out to make this I thought I'd find a simple example out there but there wasn't anything. It turns out that there's a number of interesting challenges — picking a parser to deal with difficult feeds, XML, and malformatted XML... to deal with caching ... to deal with background processing. Took me a while to get it all just right.
It powers my own front page ... consider to be under standard ruby open source license. As the vending machine says: Share And Enjoy!
Hi there.
Well, I'm back. I was running this site on really ancient technology — AxKit — so 2001. Now I'm running it on modern technology, i.e. Rails 2. And doesn't it rock. Now I have a cool GUI editor to type into, I have easy programming in ruby, and I have of course polished both my design and my CSS/XHTML skillz considerably in the mean time, hopefully making this all easier to look at and navigate.
So I'm running on SimpleLog here, but it's not "stock". Oh no. Stock SimpleLog right doesn't run on Rails 2, but this one does. Also, I made it even MORE simple than it used to be:
- Support Rails 2.0 (no need to freeze an old rails)
- no themes—annoying to use anyway, and no one was publishing themes either
- replaced the editor/preview panel with WYM on Rails, which is by FAR the best WYSIWYG / GUI editor I've ever found, and the end of a long search for me
...and so on.