Send your emails using Postmark
Comments Off 
Wildbit recently launched a great new email delivery service named Postmark. Once I read what it was about I knew that we had to integrate in to beyond the whiteboard.
First a little background.
Sending emails from your web application is one of those things that all the programming guides show you how to set up and get going in a few easy steps. However, they never point out the problems that you might come across while trying to send out emails.
When launched the beta version of beyond the whiteboard we setup Gmail to be our smarthost for sending emails. That was pretty easy to get going and worked out pretty well, there where copies of the sent emails in that Gmail account and emails where sent out. However, there where a couple of things which I didn’t really like. First off Gmail, replaces the from field with the user you are sending email through. For example, if your Gmail user is ‘mycoolapp’, that’s what the from will be, even if you in your application set the from to be something else like ’support’. A minor little issue, but we wanted some emails to be from the application and others be from individuals which just wasn’t possible. Lastly, Gmail limits the number of emails that you can send through it in a given period. This was the big killer for us, we hit limit and didn’t know it right away. That cause us some headaches because there really wasn’t a good way to know if we where close to the limit or what.
After the few Gmail incidents I finally broke down and decided to set up an SMTP server to send out our application emails. I really didn’t want to because, well email is kind of scary to me. The server configurations are very complex and they have warnings everywhere that if you make a mistake every spammer in the world will use your server. Then if that happens every ISP will hate you and little kids will point and laugh when you go to the mall. Despite all that I did manage to get a configuration going and we didn’t let any evil spammers or anything bad like that. Everything appeared to be going well, or so I thought.
You see, I setup our SMTP to only send out emails, the receiving part was still handled by Gmail. I hadn’t keeping tabs on the Gmail inbox of the address we where sending from in some time. When I did happen to remember to look in that account, several months later, I discovered that EarthLink and AT&T had decided that we where spammers and blocked all emails from our server. What a drag that was, I had no clue how long that had been going on, and it wasn’t a very good feeling to be labeled a spammer, even if it was from an automated system. They have methods to get you removed from list and I filled out their forms, but it happened at least one other time. That’s when I decided that there had to be something better out there and that’s when I found Postmark.
Why Postmark is good.
Right when I read the description of the Postmark service I signed up, it was an easy decision for me. Here’s how it works, you post your email to Postmark through their HTTP API and then they send your email to it’s destination. See super simple, but wait there’s more, they have a nice overview with a graph of how many emails you’ve sent, how many bounced, and how many where marked as spam. You can then dig deeper and see which emails bounced, why they bounce, and there a way to reactivate those emails if you think there was a mistake.
The integration was also pretty easy, they have published a Ruby gem that hooks right in to ActionMailer. After a couple lines of configuration you can just use ActionMailer just like before and instead of sending emails via SMTP, they are sent to Postmark for delivery. I also really liked the way the set it up by changing ActionMailer’s delivery method. Why is that good? Well, different ActionMailer subclasses can have different delivery methods, which is completely different from the SMTP settings which are shared across all instances. That makes it possible to have emails sent to users got through Postmark, while system emails, like error reports can go through SMTP. Which is exactly how we have it set up today.
I’m really happy with the service, now I know exactly how many emails to users we are sending out each day and how many are bouncing back. Even though Postmark just launched a few weeks ago I know that the folks at Wildbit are going to continue to make it better because they use it with their other web applications. Personally I’m really looking forward to when they get some sort of webhooks going for bounced emails. I would like to inform our users that we couldn’t send them an email at the address they have given us.
All of that totally justifies the cost of the Postmark service, which is currently $1.50 for 1,000 emails. If you are building a web application and are sending out transactional emails to your users, I would really encourage you to investigate a service like Postmark. Why worry about emails when you should be worrying about your application’s main features.
How an AD can ruin design
1 Comment Should design and good user interface be sacrificed for optimal ad viewing? Not in my opinion. CNN, compared to other big news media, has a pretty good site design. However, their new pulse page is ruined by horrible ad placement. In a way the design was successful, because I noticed the ad. However, I noticed it like a teenager notices a pimple on their face. I was disgusted, confused and worried it may leave a scar. I’m seeing this more and more online, and it’s getting more and more annoying. Insert Seth Godin quotes here.
Affion Crockett, Great Example of Online Branding/Marketing
Comments Off Who is Affion Crockett?
Before this video I thought he was just a funny guy on Wild’n Out. I now know he is also a musician, oskamill, and was recently in the movie Dance Flick. Affion is using the internet to show off his versatility as an entertainer. Best of all, he is slowly eliminating the middle man (studios). He has over 47,000 subscribers on youtube (his latest video has about a million views as of now), over 7000 friends on myspace, about 7000 followers on twitter, and has 5000 friends on facebook ( i couldn’t find a real fan page). He has a, almost instant, connection to about 70,000 fans. Fans who will most likely share, retweet and email anything he puts in his feeds.
Using Yaml to stream lots of data
Comments Off Most people just use Yaml for configuration. The prime example is the database.yml file found in almost every single Rails app. But here’s a way to take advantage of Yaml in Ruby as a way to serialize and transfer lots of separate records from one place to another.
The standard yaml library found in Ruby is all you need. First, to serialize the target set of records. For our example, we’re just going to stream to a file, but one can use any IO stream. And instead of streaming an indeterminate number of records, we’re going to bound this process with a fixed number of records.
require ‘yaml’
file = File.open(‘test.yml’, ‘w’)
for x in 0..100
hash = {
‘id’ => x,
‘field1′ => “somedata”,
‘field2′ => “someother data”,
‘option’ => true
}
file.write hash.to_yaml
end
file.close
Notice that all we needed to do is call the #to_yaml method to do the serialization. It also handles adds the Yaml document start character sequence automatically (i.e. “—”, three dashes alone on a new line).
To read that stream of data:
File.open(‘test.yml’, ‘r’) do |io|
YAML.each_document(io) do |record|
# Do something here
puts record.inspect
end
end
Question: What’s the advantage here?
Answer: Constant memory footprint. We only read in as much as we need to handle the next Yaml document (object, hash). So if you’re processing a 2 Gig file, the process won’t try to load the entire file into memory at once. Or you may not actually know how many records will come over the wire.
Some Uses:
- Mass dumping data from one system to another where the source system lacks write permissions, or even network access, to the target system.
- Data Archival in a common format. Yaml is accessible by tools without the need for a SQL database… if one archived everything in SQL dumps. And this lets you keep rows clustered in manageable sized files.
- Stream real-time updates from one system to another. Either HTTP post a batch document stream to a Webhook, or just read and write on raw TCP sockets.
How to Quickstart Merb Slice Development
6 Comments What are Merb Slices?
Merb Slices are a kind of mini Merb Application that can be packaged up as gems and used as is (or with customizations) within actual Merb Applications. They are full Model-View-Controller stacks to support a large feature within a larger application. Examples could be a full blogging system, user management system or a file upload system.
Where else can I find good overview information about Merb Slices?
There are a few places, but you should start with the MerbCamp 2008 MerbSlices talk by Daniel Neighman aka hassox. His slides are found here and here. Watch the other MerbCamp videos for more Merb info.
So what does this article cover?
This just provides some missing details for a developer to immediately get a slice working. The above material gives a great overview of slices in general and the why/how to use/install them in main Merb applications.
Let’s start by creating our slice.
$ merb-gen slice myslice
Generating with slice generator:
[ADDED] app/controllers/application.rb
[ADDED] app/controllers/main.rb
[ADDED] app/helpers/application_helper.rb
[ADDED] app/views/layout/myslice.html.erb
[ADDED] app/views/main/index.html.erb
[ADDED] config/init.rb
[ADDED] config/router.rb
[ADDED] lib/myslice.rb
[ADDED] Rakefile
[ADDED] README
[ADDED] spec/myslice_spec.rb
[ADDED] spec/controllers/main_spec.rb
[ADDED] spec/spec_helper.rb
[ADDED] stubs/app/controllers/application.rb
[ADDED] stubs/app/controllers/main.rb
[ADDED] TODO
[ADDED] public/javascripts/master.js
[ADDED] public/stylesheets/master.css
[ADDED] LICENSE
[ADDED] lib/myslice/merbtasks.rb
[ADDED] lib/myslice/slicetasks.rb
[ADDED] lib/myslice/spectasks.rb
$ cd myslice
Our goal here is to set up our slice so we can actually do development without needing to install it within a Merb application, and to give an example run through of creating a resource.
Let’s start by editing the slice’s init.rb file. This file is solely used in your slice development cycle; it is omitted from the final packaged gem; it is NOT used in production. If you look at the slice’s Rakefile, you will see that NO file in the config/ directory is included in the gem.
$ vi config/init.rb
# Add the following to the top of the slice's config/init.rb file.
# USE THE CORRECT GEM VERSIONS.
merb_gems_version = "0.9.12"
dm_gems_version = "0.9.6"
# Uncomment the following two lines to develop with haml instead of erb.
# dependency "merb-haml", merb_gems_version
# use_template_engine :haml
dependency "dm-core", dm_gems_version
dependency "dm-aggregates", dm_gems_version
dependency "dm-migrations", dm_gems_version
dependency "dm-timestamps", dm_gems_version
dependency "dm-types", dm_gems_version
dependency "dm-validations", dm_gems_version
use_orm :datamapper
What we did above is to declare a dependency on the DataMapper ORM. You can use whatever ORM you wish, but I’ll be using DataMapper as the example in this article.
Also, I have included commented lines to show how one would use Haml instead of Erb as the templating engine. I highly suggest that developers write views for BOTH Erb and Haml when developing slices. This gives the users of such slices a choice.
Since we’re editing files in the config/ directory, we’ll go ahead and create the database.yml file we’ll need.
$ vi config/database.yml
# This is a sample database file for the DataMapper ORM
development: &defaults
# These are the settings for repository :default
adapter: sqlite3
database: sample_development.db
Next, we go ahead and try creating a resource as most developers will be doing. It’s just the same merb-gen command as one would do for any regular Merb application.
$ merb-gen resource article
[ADDED] spec/models/article_spec.rb
[ADDED] app/models/article.rb
[ADDED] spec/requests/articles_spec.rb
[ADDED] app/controllers/articles.rb
[ADDED] app/views/articles/index.html.erb
[ADDED] app/views/articles/show.html.erb
[ADDED] app/views/articles/edit.html.erb
[ADDED] app/views/articles/new.html.erb
[ADDED] app/helpers/articles_helper.rb
When we edit the articles controller, we’ll see that it looks exactly like a generated resource that one would get in a Merb application. In fact that’s probably the whole point since we want our slices to be full MVC stacks to implement our subsystem features. But if we tried to use this resource right now, we’ll find that our slice just won’t work. The main reason is how we define a slice’s controller versus a controller in a full Merb application. The whole issue is about namespacing.
$ vi app/controllers/articles.rb
We need to change the following class declaration:
class Articles < Application
to
class Myslice::Articles < Myslice::Application
This article class needs to inherit from the slice’s application class instead of whatever Merb app it is installed in. And the Articles class needs to be in the Myslice namespace so the slice router rules will actually be able to find the class.
The rest of the controller looks good. It’s got all the default DataMapper access code for its methods. NOTE: If one did not call “use_orm :datamapper” in the slice’s init.rb file, then all this ORM access code will be omitted; one would have a plain class whose methods just called `render`.
As a next step, one would generally verify that merb-gen would have updated the config/router.rb file with this new resource. WARNING! The config/router.rb file is NOT where routes are configured for slices. Everything is done in lib/myslice.rb, or whatever it is named in your real slice. In fact, this is also where we’ll find other configuration options.
$ vi lib/myslice.rb
Let’s go ahead and update our slice meta data. Replace the following code with your own stuff.
# All Slice code is expected to be namespaced inside a module
module Myslice
# Slice metadata
self.description = "Myslice is a chunky Merb slice!"
self.version = "0.0.1"
self.author = "Engine Yard"
I won’t cover the other slice hooks in this file except for the “def self.setup_router(scope)” method. This is where you SHOULD to add your resource. Although the scope.default_routes line will correctly route to your resource, I find it cleaner to explicitly declare the slice’s routes. Watch the video mentioned above to understand why we setup routes in this hook instead of a slice’s router.rb file.
def self.setup_router(scope)
# Add the following resource line
scope.resources :articles
# The lines that follow are the pre-generated ones.
scope.match('/index(.:format)').to(:controller => 'main', :action => 'index').name(:index)
# the slice is mounted at /myslice - note that it comes before default_routes
scope.match('/').to(:controller => 'main', :action => 'index').name(:home)
# enable slice-level default routes by default
scope.default_routes
end
I personally would delete the “scope.default_routes” line because I’m all about explicitly specifying routes.
At this point, we’ve got routes and a fixed up controller.
Now we look at the Article model. This model contains the code required to define it as a DataMapper resource.
$ cat app/models/article.rb
class Article
include DataMapper::Resource
property :id, Serial
end
Again, as with controllers, the DataMapper code would have been omitted without the “use_orm :datamapper” in the slice’s config/init.rb file. We would have had an empty class.
I will skip over how we develop Models for Datamapper in Merb. One should watch the other MerbCamp videos for that. Let’s just assume that you’ve added a few other properties to the Article model class.
Let’s create the model’s sqlite3 tables.
$ rake db:automigrate
Don't know how to build task 'db:automigrate'
Oops. We don’t have that kind of default support in our slice’s rake tasks. But no fear, we’ll just invoke the auto_migrate! directly:
$ echo 'DataMapper.auto_migrate!' | slice -i
Loading init file from /Users/notroot/projects/myslice/config/init.rb
~ Connecting to database...
~ Loaded slice 'Myslice' ...
~ Parent pid: 9145
~ Activating slice 'Myslice' ...
DataMapper.auto_migrate!
[Merb::DataMapperSessionStore, Article]
Be sure to use single quotes since the `!’ character is special in bash. But if you want to do it interactively, just start up the slice irb console.
$ slice -i
The only other thing to note is how slice sql tables are named. Our “articles” table in the slice’s development database becomes “myslice_articles” in a Merb application’s database.
And to finally get it all together, we need to start mogrel to serve up the slice… but NOT using the `merb` command. We use the `slice` binary.
$ slice
Loading init file from /Users/notroot/projects/myslice/config/init.rb
~ Connecting to database...
~ Loaded slice 'Myslice' ...
~ Parent pid: 9147
~ Activating slice 'Myslice' ...
merb : worker (port 4000) ~ Starting Mongrel at port 4000
merb : worker (port 4000) ~ Successfully bound to port 4000
And off to the browser you go; and off to developing your slice.
Example) http://localhost:4000/articles
So what’s next once I finish developing my slice?
Install your slice directly into your gem repository.
$ sudo rake install
Add your slice to the application’s list of dependencies.
$ cd ~/projects/myapp
$ vi config/dependencies.rb
# Add your slice dependency to the bottom of the file.
dependency "myslice", "0.0.1"
Install the Slice into your Merb Application.
$ rake -T slices
$ rake slices:myslice:install
And go ahead and add your slice to your application’s router.rb file.
$ vi config/router.rb
# Find the following method call and add your slice.
Merb::Router.prepare do
# This mounts your slice to the default http://example.com/myslice/
# "namespace". See Merb's rubydocs for more info about options.
slice(:myslice)
# other stuff omitted.
end
Now, you can run `merb` to start up mongrel for your application and
hit away under the /myslice url path namespace.
Example) http://localhost:4000/myslice/articles
Go forth and slice!
Rails Select Helper
4 Comments One of the major benefits of Ruby on Rails is rapid development. Something that we love at BadPopcorn. Rails has great helper methods to minimize code and bugs. One of my favorites is the select helper. There are several different ways to make a select tag, but I am going to demonstrate the one I like best. Let’s say you are creating a new “gym member”. He will have a name and belong to a gym.
View
1 <%= form_for(@member) do |f| %>
2 <%= f.text_field :name %>
3 <%= select :member,:gym_id,Gym.find(:all).collect{|p| [p.name, p.id]}%>
4 <%= f.submit "Create" %>
5 <% end %>
Line 1 builds the form. Rails uses the @member variable to generate the action,id and name of the form.
<form id="new_member" class="new_member" action="/members" method="post">
Notice the “do | f |” code in the form deceleration (line 1). You can now use the local variable f to bind attributes of member to input variables. Line 2 of the code generates the below html. The name of the input variable is a Rails convention.
<input id="member_name" name="member[name]" size="30" type="text" />
Line 3 is the Rails select tag helper. The select tag generates the html select tag cleanly. The “name” of the select is dynamically created by using the first two parameters of the helper function “:member” and “:name”. The options are generated by the third parameter.
<select id="member_gym_id" name="member[gym_id]">
<option value="1">Get Ripped Here</option>
<option value="2">Hot Girls Welcome</option>
</select>Â
Line 4 creates the html submit button.
<input id="member_submit" name="commit" type="submit" value="Create" />Also, Rails will throw an exception if you attempt to bind to a member attribute that does not exist. For example, <%= f.text_field :height %> will throw the exception: undefined method `height' for #. Changing the “gym_id” parameter in the select helper will cause the same type of exception. This will save you from making dumb mistakes time and time again.
So what’s posted?
This is where the rails form helper tags come in useful. An organized list of Member was passed as a post parameter to the controller.
Parameters: {"commit"=>"Create", "member"=>{"name"=>"moe", "gym_id"=>"1"},
"authenticity_token"=>"52646c5a18d11c6009b5597af3bf798942a59c0a",
"action"=>"create", "controller"=>"members"}
Controller
When the form is posted it will hit the “create” function in the members controller by default. You can change where it will post to if necessary.
1 def create
2 @member = Member.new(params[:member])
3 respond_to do |format|
4 if @member.save
5 flash[:notice] = 'Member was successfully created.'
6 format.html { redirect_to(@member) }
7 end
8 end
9 end
Line 2 makes a new instance of Member and passes the post parameter member list in the constructor. This returns a member object with the name and gym_id set properly. Line 4 saves the new member in the database.
Member Create (0.000386) INSERT INTO members ("name", "updated_at",
"gym_id", "created_at") VALUES('moe', '2008-09-02 02:00:35', 1,
'2008-09-02 02:00:35')
The same type exception(s), discussed earlier, will occur here. For example, an exception will be thrown if there is a “height” attribute in the members post parameter.
How we saved time (the short list)
- Initially we didn’t have to pass much to the view. Just an instance of Member.
- We were able to use the Rails html helper to build the correct form quickly.
- Rails conventions made it easy to know where the post would be directed to within the controller.
- In two lines we created a new Member instance, updated the values with the posted parameters and updated the database.
- It’s also worth noting that the Rails error checking, when using the helper tags, saves us a lot of debugging time.
What’s Next?
Input validation. Making sure the user isn’t inputting dumb data. For example, in the above code the user could use undesirable characters in their name. Yup, that’s super simple too.
Google Health
Comments Off Google health launched today and could be really big. The new Google product will let you store and manage all of your health information in one central place. I think this is a great step forward for the online medical community. Sites like webmd are very informative but not personal. I can only imagine the amount of data Google will be able to index now. But hey, it’s free.
I hope Google doesn’t drop the ball on the social side, because it could be really helpful to a lot of people. Let users rate and comment on doctors and perhaps even view your friend’s doctors. Let users exchange medical treatments they tried out and give first hand accounts of medications. I’m tired of going to sites that pretend to be informative when, in actuality, are trying to push a certain new medication or treatment process on you.
- Start tracking a medical history and learn about your conditions
- Import your medical records
- View your medical history
- Find out how medications might interact
- Make your health information work for you
- Search for doctors and hospitals
Find out more information here.
Social Adwords vs Regular Adwords
1 Comment Remember when you only saw Google content after a web search? You know, before they basically took over the internet. Google introduced or rather made popular the concept of adwords but it seems facebook might be throwing their hat.
Adwords Crash Course
Google is really good at indexing websites and labeling them with certain keywords. Let’s say you have a blog about Ronaldihno. Google might tag your website with keywords such as “soccer”, “sports”, “ronaldinho” and so forth. How they do it doesn’t matter, the fact is that they can do it. Then they thought, “hmmm since we know what the page is about, we could show the best ad on it.” By “best ad” I mean an advertisement that has a high chance of getting clicked on. For example, ads selling a poster of Ronaldihno would probably do better on your blog then the limited edition Jane Austin novel. That’s ad words is in a nutshell. People purchase ad words and Google shows them on various pages across the internet.
The key here is page content. It has little or nothing to do with the actual user. What if you were on the blog and happened to be looking for new soccer cleats? The best ad would probably be for cleats. What if the ad module knew that you were a huge fan with the popular soccer game Fifa by EA? Here is where social adwords becomes really interesting. Facebook has data and collects data all the time. If they launch a social adwords service it could be amazing. They could show an ad based on the content of the site but also by the user. As of right now facebook has 50 million users and counting and I doubt anyone thinks it is going to slow down anytime soon. They’ll dominate Tom’s social site soon enough. Probably by the time he is 30. Or is it 40? I forget how old he is saying he is this week.
Don’t think they can do it?
The newsfeed module can be seen as the building blocks for the ad module. It basically shows you content of what you should be interested in. Facebook could use these same algorithms and just run with them to display ads. Read this great article for more about new feeds.
There are two important things to realize. First, facebook is thinking far far ahead then anyone gives them credit for. Second, data is great but organized data is the key.
I’m sure you are wondering how much facebook could know about you? The first seven are from the great article I mentioned above.
- Whose profile pages you visit – and how frequently, how recently, and how often
- Who you message, and who messages you
- Whose walls you write on, and who writes on yours
- Who/what you search for
- Who you invite to events and groups, who accepts, and who invites you
- Who you tag in photos, and who tags you
- Which News Feed items you’ve clicked on before.
- What you are trying to get rid of or looking to buy (Marketplace).
- What types of links you are sharing.
- What type of videos you watch and how often.
- What groups you are in and what discussions you take part in.
- What type of people do you befriend and how often do you make new friends.
- What you are blogging about (Notes).
- Which events have you attended and plan to attend.
- Possibly know where you tavel to often based on your picture locations and names. For example, if you are tagged in a lot albums with “Las Vegas” then it’s safe to assume you travel to Vegas a lot.
- What locations you usually use the internet from and what times are you most active.
- More data can be pulled from the Polling application.
- Which applications you use the most (they are categorized).
- Profile
- Activities
- Affiliations (Networks)
- Age
- Books
- Current Location
- Education History
- Interests
- Desired Relationship or status
- Movies
- Music
- Poltical Status
- Religion
- Sex
- Television Shows
- Work History
Privacy
Privacy as we used to know it disappeared a long time ago. Probably some time after credit cards and a little before Google Earth. I don’t think facebook is doing anything wrong from a business standpoint. They aren’t selling the data they collect rather using it build another technology. It is a bit scary when I imagine the ads could but I would rather see relevant ads on sites I visit rather then have my email address sold to the highest bidder.
If you want to read more about the facebook ad-words rumors, check out facebook launching the google adwords killer.
privacy policy or the lack of it
3 Comments A few months ago I signed up for a SharedReviews beta account. The idea behind the site is to get solid reviews of products and pay the community 50/50 on certain revenue. Sounds pretty cool huh? Well it may be but as I was signing up I came across the privacy policy. Usually I just breeze through it but I decided to read this one.
“We protect your privacy with a passion!”
First, I want to say that I think ShareReviews is a cool site and I hope their business model works out. However, the privacy policy was kind of weird. It was actually amusing. Why do sites even have privacy policies? They should just come out and say “Yea, we’ll use your information for whatever we damn well please.” Below are some lines right of the policy.
“For the purposes of this policy, “Personal Information” means any information about you except your business title, address, e-mail address, telephone number or facsimile number. It also does not include your home address and telephone number if these are published in a telephone or other directory, and does not include any Review, content or other materials that you post or submit to use for possible publication. “
Umm….so what else is there? What exactly is private then?
“We do not sell your Personal Information to third parties. We may share some or all of your Personal Information with our third party business partners”
Hmmm ok. I shouldn’t be surprised. It’s a “review” site and to make money they are probably selling data. For that data to be worth anything they have to include user data with it. So why throw in the line about “we protect your privacy with a passion.” Half the business model is actually based upon doing the exact opposite.
Most users caring less is the worst part. We’ll go crazy if a telemarketer calls our house but we don’t blink while registering for a new site. Personally, I’m not against a website data mining to show relevant ads. Let’s take facebook for example. They will look at your profile and use that to display an advertisement. An advertiser will pay more to know that their ad is getting to their target demographic. I’m fine with that. I’m going to see an ad anyway, might as well see one that I might actually like. That’s how Google makes all their money.
What I don’t like is when companies sell information they collect. To me thats like selling hot pictures your ex girlfriend took for you. The ones she would dress up like a tiger and act like she is…ok getting off topic. The pictures were meant for you not the public or your favorite “rate this chick” website. Just because you don’t care about her anymore doesn’t mean you should go and sell something she wouldn’t want sold. However, let’s say you analyze the pictures. After hours of analyzing, and frequent naps, you say to yourself “hey i bet she would really like this lingerie site.” You contact her the usual way you two communicate and let her know that you are an affiliate for an animal lingerie site. Nothing wrong with that, right?
RDFa Complexities
2 Comments So I briefly read over the new draft of the RDFa Primer. It’s good overall, but Section 5 introduces unnecessary interpretation complexities.
I say BLEAH to the Section 5. I want “Keep It Simple, Stupid.” parsing. The nested layers make it harder for the parser to parse; it makes it harder for the lay person to understand RDFa (and to adopt, and to use).
I also REALLY don’t like the idea of intermixing the id and about attributes for use in defining the subjects & objects. Although the primer makes a case for it, I counter with this example:
<body about=”http://example.com/mydoc#section”>
<div id=”popup”>
The document was written by <span rel=”dc:author”>Tim</span>
</div>
<a onClick=”…”>Show PopUp</a>
</body>
The ‘popup’ id is overloaded. It’s the identifier for which the Javascript code looks up, and it’s also become the subject of the dc:author statement. The above fragment is also non-intuitive. I would expect <http://example.com/mydoc#section> dc:author ‘Tim’. Instead, I get <#popup> dc:author ‘Tim’.

