1. When using Geokit + Google, sometimes, giving a valid postal code will fail. It's a very random thing. I'm not sure if it's just Google, but sometimes, it fails, even with a valid postal code. I'm guessing it has something to do with the network or perhaps they limit how many you can ask for in a period of time so you don't overload their server.
2. If you add :within to your find, Geokit doesn't recognize that :within => nil means not to add :within. Sometimes, you have a variable that may or may not be nil, and this controls whether you want to search using a distance. The :origin key works fine with nil, but :within does not. It blindly adds the distance calculations to the find. I had to hack acts_as_mappable.rb a little bit in order to get it to work.
In the apply_distance_scope(options) function, I have:
distance_condition = "#{distance_column_name} <= #{options[:within]}" if options.has_key?(:within) && !options[:within].nil?
distance_condition = "#{distance_column_name} > #{options[:beyond]}" if options.has_key?(:beyond) && !options[:beyond].nil?
and
[:within, :beyond, :range].each { |option| options.delete(option) }
This will take the :within => nil into account and skip the adding of the distance calculations out of the find and remove the useless keys.
3. In the Geokit README, there is a section about using :includes. However, there isn't a section on using :joins. Apparently, when you use :joins, things can screw up. For instance, if I have
Shop.find(:joins => "INNER JOIN products where products.shop_id = shops.id", :conditions => ..., :origin => ..., :within => ...)
You would expect a Shop object to be returned. This is true, but I found a small error. The Product id replaced the Shop id, leaving me with a Shop object with an id of the Product id.
I traced this down to the function add_distance_to_select(...). In this function, it blindly sets the :select option in the find to "*" if it isn't already defined. I'm guessing, because both Shop and Product have ids, they get mixed up somehow.
In order to fix this, I needed to add :select => "shops.*".
Hopefully, this info helps those that are having the same problems. If you have a better solution, feel free to share!
W
Showing posts with label Plugins. Show all posts
Showing posts with label Plugins. Show all posts
Tuesday, August 26, 2008
Thursday, April 17, 2008
Responds_to_parent loc error
If the rjs inside your responds_to_parent block ended up removing the iframe from your html page, the loc variable will no longer be defined.
Besides having an ugly error message on your firebug console, it can actually cause problems for the javascripts on that page as well.
In order the get around this problem, you'll need to do the following patches:
in parent_selector_assertion.rb and responds_to_parent.rb
replace all occurrence of
(3 in parent_selector_assertion, 1 in responds_to_parent)
J
Besides having an ugly error message on your firebug console, it can actually cause problems for the javascripts on that page as well.
In order the get around this problem, you'll need to do the following patches:
in parent_selector_assertion.rb and responds_to_parent.rb
replace all occurrence of
(3 in parent_selector_assertion, 1 in responds_to_parent)
loc.replace('about:blank');
with
if (window.loc) { loc.replace('about:blank'); }and that's it!J
Tuesday, February 12, 2008
attachment_fu - Controller and View
Upload Image - after all the hard work trying configuring the damn thing, this is where it pays dividends. To create an upload form, all we need are three lines:
<% form_for(:photo, @photo, :url => some_path,
:html => { :multipart => true }) do |f| %>
<%= f.file_field :uploaded_data %> <%= submit_tag "Upload" %>
<% end %>
make sure multipart is set to true, or else it won't work.
Over to the controller side, you just do what you normally do with other create actions
def create
@photo = Photo.new params[:photo]
if @photo.save ... yayaya
and the rest will be handled by attachment_fu
Listing Images - once again, three lines
<% for pic in @photo %>
<%= link_to image_tag(pic.public_filename(:thumb)), pic.public_filename %>
<% end %>
sticking in the :thumb will grab all the thumbnails, leaving it out will grab the bigger version
example:
photo.public_filename #=> /photo/2/file.jpg
photo.public_filename(:thumb) #=> /photo/2/file_thumb.jpg
Delete Image - it's just like any other objects
@photo = Photo.find(id)
@photo.destroy
J
<% form_for(:photo, @photo, :url => some_path,
:html => { :multipart => true }) do |f| %>
<%= f.file_field :uploaded_data %> <%= submit_tag "Upload" %>
<% end %>
make sure multipart is set to true, or else it won't work.
Over to the controller side, you just do what you normally do with other create actions
def create
@photo = Photo.new params[:photo]
if @photo.save ... yayaya
and the rest will be handled by attachment_fu
Listing Images - once again, three lines
<% for pic in @photo %>
<%= link_to image_tag(pic.public_filename(:thumb)), pic.public_filename %>
<% end %>
sticking in the :thumb will grab all the thumbnails, leaving it out will grab the bigger version
example:
photo.public_filename #=> /photo/2/file.jpg
photo.public_filename(:thumb) #=> /photo/2/file_thumb.jpg
Delete Image - it's just like any other objects
@photo = Photo.find(id)
@photo.destroy
J
attachment_fu - configurations
In our model, we'll use the has_attachment command to hook into attachment_fu.
example:
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 500.kilobytes,
:resize_to => '320x200>',
:thumbnails => { :thumb => '100x100>' }
:processor => 'Rmagick'
validates_as_attachment
Let's look at each option in detail
for storage, you have three options, :db_system (default), :file_system, or :S3. If you are using :db_system, attachment_fu will convert and save the image to your db as a BLOB (binary large object). If :file_system is used, the file will be saved to your hard disk. If :S3 is used, image will be saved to Amazon's S3 server.
:max_size lets you specific the maximum size of the photo, and there's also a :min_size which works the other way
:resize_to - resize your image to an acceptable width and height like facebook :) It takes a string called the Geometry String, which has the format:
< width > x < height > + - < x > + - < y > { % @ ! < > }
where any of the field can be omitted.
By default, width and height are the maximum value. If you enter something like '300x500' the image will expand or contract to fit the width and height value while maintaining the aspect ratio of the image.
If you want to enforce the image size to be exactly the size you specify, you can append an exclamation mark in the end like so: '300x500!'
You can also specify either the width '300' or the height 'x500' where the missing parameter will be chosen to maintain the aspect ratio
You can append % to specify percentage width and height ('110%' - increase, '90%' - decrease, '110%x90%' = increase width, decrease, height)
You can use @ to specify the maximum area in pixels of an image (I don't see how this is gonna be useful)
You can use < or > to change the dimensions of the image only if its width or height exceeds the geometry specification. < resizes the image only if both of its dimensions are less than the geometry specification. For example, if you specify '300x500>' and the image size is '250x250', the image size will not change. However if the image is '1000x1000', the it'll be resized to '300x300' and vice versa.
Finally x and y are offsets for width and height. + causes x and y to be measured from the left or top edges and - measures from the right or bottom edges. And they are always measured in pixels.
:thumbnails - a set of thumbnails to generate, specified by a has of filename suffixes and resizing options. You can omitted it if you don't want thumbnails. Generating multiple thumbnails will look something like this
:thumbnails => { :thumb_big => '500x500', :thumb_small => '100x100' }
:thumbnail_class - set what class to use for thumbnails (defaulted to whatever model you are in) However, you can generate a seperate model with seperate set of validations
:processor - 'ImageScience', 'Rmagick', or 'MiniMagick'. I like Rmagick cause it has the most features, but MiniMagick is less of a memory hog.
:path_prefix - Path to store the uploaded files, which defaults to public/your_table_name
If you are using S3 backend, it defaults to just your_table_name
validates_as_attachment does all the validations for you, so you have nothing to worry about :)
J
example:
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 500.kilobytes,
:resize_to => '320x200>',
:thumbnails => { :thumb => '100x100>' }
:processor => 'Rmagick'
validates_as_attachment
Let's look at each option in detail
for storage, you have three options, :db_system (default), :file_system, or :S3. If you are using :db_system, attachment_fu will convert and save the image to your db as a BLOB (binary large object). If :file_system is used, the file will be saved to your hard disk. If :S3 is used, image will be saved to Amazon's S3 server.
:max_size lets you specific the maximum size of the photo, and there's also a :min_size which works the other way
:resize_to - resize your image to an acceptable width and height like facebook :) It takes a string called the Geometry String, which has the format:
< width > x < height > + - < x > + - < y > { % @ ! < > }
where any of the field can be omitted.
By default, width and height are the maximum value. If you enter something like '300x500' the image will expand or contract to fit the width and height value while maintaining the aspect ratio of the image.
If you want to enforce the image size to be exactly the size you specify, you can append an exclamation mark in the end like so: '300x500!'
You can also specify either the width '300' or the height 'x500' where the missing parameter will be chosen to maintain the aspect ratio
You can append % to specify percentage width and height ('110%' - increase, '90%' - decrease, '110%x90%' = increase width, decrease, height)
You can use @ to specify the maximum area in pixels of an image (I don't see how this is gonna be useful)
You can use < or > to change the dimensions of the image only if its width or height exceeds the geometry specification. < resizes the image only if both of its dimensions are less than the geometry specification. For example, if you specify '300x500>' and the image size is '250x250', the image size will not change. However if the image is '1000x1000', the it'll be resized to '300x300' and vice versa.
Finally x and y are offsets for width and height. + causes x and y to be measured from the left or top edges and - measures from the right or bottom edges. And they are always measured in pixels.
:thumbnails - a set of thumbnails to generate, specified by a has of filename suffixes and resizing options. You can omitted it if you don't want thumbnails. Generating multiple thumbnails will look something like this
:thumbnails => { :thumb_big => '500x500', :thumb_small => '100x100' }
:thumbnail_class - set what class to use for thumbnails (defaulted to whatever model you are in) However, you can generate a seperate model with seperate set of validations
:processor - 'ImageScience', 'Rmagick', or 'MiniMagick'. I like Rmagick cause it has the most features, but MiniMagick is less of a memory hog.
:path_prefix - Path to store the uploaded files, which defaults to public/your_table_name
If you are using S3 backend, it defaults to just your_table_name
validates_as_attachment does all the validations for you, so you have nothing to worry about :)
J
attachment_fu - Installation and Setup
attachment_fu plugin is the complete package in handling images for your website. It handles image upload, resize, generate thumbnails, storing image info to database and saving the file to physical disk drive
to install attachment_fu, we type
~$ .script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu/
if you don't have imagemagick and rmagick installed
~$ sudo apt-get install imagemagick
~$ dpkg -l | grep magick
~$ sudo apt-get install libmagick9-dev
~$ sudo gem install rmagick -v=1.15.12
window users: you can go download the imagemagick executable and install rmagick by doing gem install rmagick -v=1.15.12
now let's generate a model to test it out
~$ .script/generate model photo
open up the migration file and enter the following
class CreatePhotos < ActiveRecord::Migration
def self.up create_table :photos do |t|
t.column :user_id, :integer
t.column :parent_id, :integer
t.column :content_type, :string
t.column :filename, :string
t.column :thumbnail, :string
t.column :size, :integer
t.column :width, :integer
t.column :height, :integer
end
end
def self.down
drop_table :photos end
end
:user_id - I'm assuming these photos belong to someone, you can replace it with another model_id depending on the relationship
:parent_id - don't touch, it's reserved for attachment_fu
:content_type - specify the content type of your data, default is image, but it can also be audio, or video the rest are pretty self explanatory, and we'll revisit these fields in a moment. now save your file, and do a quick rake db:migrate
J
to install attachment_fu, we type
~$ .script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu/
if you don't have imagemagick and rmagick installed
~$ sudo apt-get install imagemagick
~$ dpkg -l | grep magick
~$ sudo apt-get install libmagick9-dev
~$ sudo gem install rmagick -v=1.15.12
window users: you can go download the imagemagick executable and install rmagick by doing gem install rmagick -v=1.15.12
now let's generate a model to test it out
~$ .script/generate model photo
open up the migration file and enter the following
class CreatePhotos < ActiveRecord::Migration
def self.up create_table :photos do |t|
t.column :user_id, :integer
t.column :parent_id, :integer
t.column :content_type, :string
t.column :filename, :string
t.column :thumbnail, :string
t.column :size, :integer
t.column :width, :integer
t.column :height, :integer
end
end
def self.down
drop_table :photos end
end
:user_id - I'm assuming these photos belong to someone, you can replace it with another model_id depending on the relationship
:parent_id - don't touch, it's reserved for attachment_fu
:content_type - specify the content type of your data, default is image, but it can also be audio, or video the rest are pretty self explanatory, and we'll revisit these fields in a moment. now save your file, and do a quick rake db:migrate
J
Thursday, January 31, 2008
12 Hour Time
RoR comes with many fantastic helpers for the view. However, there is one helper that is definitely lacking some features. Perhaps it is purposely missing features because of its complexity and range of customization. What I'm referring to is the DateHelper.
Firstly, when selecting a date, having selects as inputs just outright sucks! It's very hard for the user to visualize such a layout. We are used to seeing calendars. In what real world situation do you ever look at dates in a select box format... none that I can think of. But calendars, that's another story. Calendars are so normal to users that without them, we're lost! Unfortunately, RoR does not come prepackaged with a calendar format for dates. But luckily, RoR is extendable through plugins! We're currently testing out which one works best for us, and we'll let you know when we've come to a decision.
The second problem with the prepackaged helper is the fact that when selecting times, we're forced to take the inputs based on a 24 hour clock... EWWW!!! No body works on a 24 hour clock (except if you're in the military...) The usual person just isn't used to seeing a 24 hour clock. That's where plugins come in again!
I found a plugin that worked very well and required very little modifications:
12_hour_time
This plugin allows you to add an option to your current time selects to make them based on a 12 hour clock:
:twelve_hour => true
The rest (frontend and backend) are automatically handled for you!
Brilliant!
W
Firstly, when selecting a date, having selects as inputs just outright sucks! It's very hard for the user to visualize such a layout. We are used to seeing calendars. In what real world situation do you ever look at dates in a select box format... none that I can think of. But calendars, that's another story. Calendars are so normal to users that without them, we're lost! Unfortunately, RoR does not come prepackaged with a calendar format for dates. But luckily, RoR is extendable through plugins! We're currently testing out which one works best for us, and we'll let you know when we've come to a decision.
The second problem with the prepackaged helper is the fact that when selecting times, we're forced to take the inputs based on a 24 hour clock... EWWW!!! No body works on a 24 hour clock (except if you're in the military...) The usual person just isn't used to seeing a 24 hour clock. That's where plugins come in again!
I found a plugin that worked very well and required very little modifications:
12_hour_time
This plugin allows you to add an option to your current time selects to make them based on a 12 hour clock:
:twelve_hour => true
The rest (frontend and backend) are automatically handled for you!
Brilliant!
W
Saturday, January 26, 2008
Pagination
When displaying a list of information to the user, it's always handy to separate it into several pages if your list gets too long. This is a very common task, but also a very redundant and mundane task.
The logic to figure out how to display the page links is rather repetitive:
<Prev 1 2 ... 99 100 Next>
Instead of wasting time writing and rewriting this, wouldn't it be a better use of time working on something else? Well, there's a plugin that makes your life easy! It's called will_paginate.
will_paginate gives a wrapper around the find functions, allowing you to give the page number you want, and it returns to you just those objects that will be displayed on the page. Furthermore, with one simple function call, the nice page links will be displayed for you properly! Check out the will_paginate page for a quick example.
The only down-side I found to this plugin was that it didn't support AJAX. I hope that in one of the future releases they'll add AJAX support. In the meantime, I added one myself called will_remote_paginate. It merges will_paginate and the usual remote calls together like so:
<%= will_remote paginate @products, :url => list_products_path, :method => :get %>
If your interested in seeing what I did, give me a shout and I'll post it up. It's not the best solution in the world, but at least it works for me!
W
The logic to figure out how to display the page links is rather repetitive:
<Prev 1 2 ... 99 100 Next>
Instead of wasting time writing and rewriting this, wouldn't it be a better use of time working on something else? Well, there's a plugin that makes your life easy! It's called will_paginate.
will_paginate gives a wrapper around the find functions, allowing you to give the page number you want, and it returns to you just those objects that will be displayed on the page. Furthermore, with one simple function call, the nice page links will be displayed for you properly! Check out the will_paginate page for a quick example.
The only down-side I found to this plugin was that it didn't support AJAX. I hope that in one of the future releases they'll add AJAX support. In the meantime, I added one myself called will_remote_paginate. It merges will_paginate and the usual remote calls together like so:
<%= will_remote paginate @products, :url => list_products_path, :method => :get %>
If your interested in seeing what I did, give me a shout and I'll post it up. It's not the best solution in the world, but at least it works for me!
W
Saturday, January 19, 2008
Time Zones
When developing an application with an audience larger than your local neighbourhood in mind, you have to start thinking where your users are. One major point that comes into play is time. The world works on different time zones, and you must realize and honour that. When your application is based on time, time zones become important.
However, time zones are one of those things you just never want to touch. Why? Because usually it's a bloody mess! There are several factors to consider, like the time on your server and database (are they in local time or UTC?), local times for users using time zones, and daylight savings times. All this bundles together to make one messy problem.
RoR's built-in Date/DateTime/Time/TimeZone classes are poorly equipped to handle... well... anything to do with local times. However, because RoR is so extendable, there are always gems and plugins! In order to get everything working nicely, the problem of time zones requires 1 gem and 3 plugins! Wow! That's a lot, but trust me, it makes things much cleaner!
Firstly, there's the TZInfo gem. This little gem provides daylight savings aware transformations of time. This is useful because not everybody observes daylight savings.
Secondly, there's the TZInfo Timezone plugin. This little baby is where most of the magic occurs. This essentially replaces RoR's built-in TimeZone class. It does wonders.
Thirdly, there's the TzTime plugin. This is another little baby that does wonders. It basically replaces RoR's built-in Time class, and works in unison with TZInfo Timezone.
In short, all you do is set TzTime.zone to the current user's time zone, and then you can use things like TzTime.now, which will return you the current local time of the user. Clean and simple!
For an illustration of this, go to:
http://www.caboo.se/articles/2007/2/23/adding-timezone-to-your-rails-app
There was one modification which I needed to make in order for the example to work. Instead of TZInfo::Timezone, I needed to write TzinfoTimezone.
Good luck with time zones, and hopefully, this will keep your application a little bit cleaner (and minus the hair pulling!)
W
However, time zones are one of those things you just never want to touch. Why? Because usually it's a bloody mess! There are several factors to consider, like the time on your server and database (are they in local time or UTC?), local times for users using time zones, and daylight savings times. All this bundles together to make one messy problem.
RoR's built-in Date/DateTime/Time/TimeZone classes are poorly equipped to handle... well... anything to do with local times. However, because RoR is so extendable, there are always gems and plugins! In order to get everything working nicely, the problem of time zones requires 1 gem and 3 plugins! Wow! That's a lot, but trust me, it makes things much cleaner!
Firstly, there's the TZInfo gem. This little gem provides daylight savings aware transformations of time. This is useful because not everybody observes daylight savings.
Secondly, there's the TZInfo Timezone plugin. This little baby is where most of the magic occurs. This essentially replaces RoR's built-in TimeZone class. It does wonders.
Thirdly, there's the TzTime plugin. This is another little baby that does wonders. It basically replaces RoR's built-in Time class, and works in unison with TZInfo Timezone.
In short, all you do is set TzTime.zone to the current user's time zone, and then you can use things like TzTime.now, which will return you the current local time of the user. Clean and simple!
For an illustration of this, go to:
http://www.caboo.se/articles/2007/2/23/adding-timezone-to-your-rails-app
There was one modification which I needed to make in order for the example to work. Instead of TZInfo::Timezone, I needed to write TzinfoTimezone.
Good luck with time zones, and hopefully, this will keep your application a little bit cleaner (and minus the hair pulling!)
W
Sunday, January 13, 2008
ActiveForm
Suppose you're doing a search form. This search form can be using fields from many different ActiveRecord models and probably doesn't correspond to any table in your database.
What's nice about being an ActiveRecord model is that in the view, you can do wonderful things like a form_for helper or error_messages_for helper. Furthermore, ActiveRecord provides you a collection of wonderful validation functions.
However, without ActiveRecord, your solution would be to do it all by hand. How very sad T.T
This is where ActiveForm is a time saver! Basically, you create an ActiveForm model exactly the way you would an ActiveRecord model. It even supports validation! Furthermore, it is supported in the view, so all those helpers will still work! Just wonderful!
You can grab it as a plugin from here:
http://www.realityforge.org/svn/code/active-form/trunk
Enjoy!
W
What's nice about being an ActiveRecord model is that in the view, you can do wonderful things like a form_for helper or error_messages_for helper. Furthermore, ActiveRecord provides you a collection of wonderful validation functions.
However, without ActiveRecord, your solution would be to do it all by hand. How very sad T.T
This is where ActiveForm is a time saver! Basically, you create an ActiveForm model exactly the way you would an ActiveRecord model. It even supports validation! Furthermore, it is supported in the view, so all those helpers will still work! Just wonderful!
You can grab it as a plugin from here:
http://www.realityforge.org/svn/code/active-form/trunk
Enjoy!
W
Labels:
ActiveRecord,
Plugins,
Solutions,
Views,
W
Monday, October 29, 2007
Tags Solution
Ok... so what is our solution to tags? We're going to do our own! This is gonna be interesting...
Basically, we couldn't decide which acts_as_taggable we should use, and started digging deeper into both. The plugin had very little documentation, and we needed a rich association table. However, it supported polymorphic associations, but we decided that we wouldn't require such a feature. The gem was lacking in some specifics that we wanted to implement, so in the end, we decided on our own version that was customized to our tastes.
I did come across one called acts_as_taggable_on_steroids which is based on the acts_as_taggable plugin. It includes some nice caching features that are built-in. I think we'll have to read up on caching, as it might be a good idea to cache tags!
Well... it'll definitely be interesting developing our own tags. We'll see what happens!
W
Basically, we couldn't decide which acts_as_taggable we should use, and started digging deeper into both. The plugin had very little documentation, and we needed a rich association table. However, it supported polymorphic associations, but we decided that we wouldn't require such a feature. The gem was lacking in some specifics that we wanted to implement, so in the end, we decided on our own version that was customized to our tastes.
I did come across one called acts_as_taggable_on_steroids which is based on the acts_as_taggable plugin. It includes some nice caching features that are built-in. I think we'll have to read up on caching, as it might be a good idea to cache tags!
Well... it'll definitely be interesting developing our own tags. We'll see what happens!
W
Saturday, October 27, 2007
Tags
So I was reading up on polymorphic associations, and came across tags. Apparently, RoR has support for tags. So I dug a little deeper, and got myself into a mess!
Here's the thing. RoR has something called acts_as_taggable. You create the relevant tables, and then you label a model as taggable, and it can then be tagged. Pretty neat huh? However, there are 2 acts_as_taggable. Yes... 2! And they both have the same name! One is a gem, the other a plugin.
What's interesting is that the plugin was written after the gem, but by the creator of Rails (David Heinemeier Hansson)! So now, I'm having troubles about which one should be used... there seems to be a split in the community, since the gem is documented, but apparently the plugin has good features, but isn't documented. Furthermore, the plugin is the way to go for extending RoR.
Not sure what to do, so I'll research some more, and hopefully come to a decision.
W
Here's the thing. RoR has something called acts_as_taggable. You create the relevant tables, and then you label a model as taggable, and it can then be tagged. Pretty neat huh? However, there are 2 acts_as_taggable. Yes... 2! And they both have the same name! One is a gem, the other a plugin.
What's interesting is that the plugin was written after the gem, but by the creator of Rails (David Heinemeier Hansson)! So now, I'm having troubles about which one should be used... there seems to be a split in the community, since the gem is documented, but apparently the plugin has good features, but isn't documented. Furthermore, the plugin is the way to go for extending RoR.
Not sure what to do, so I'll research some more, and hopefully come to a decision.
W
Subscribe to:
Posts (Atom)