Posted by BadReligion
Tue, 14 Jul 2009 12:11:00 GMT
I wanted a DRY way to set the published_at attribute of a Blog. Remembering the advice of my peers to keep a fat model I decided to stuff the logic there. This could be used for any similar attribute. First decide on a method name that we will call on our instance variable, I decided to use "publish?". So for instance I can call "@blog.publish?", now I know I will need to know whether or not to publish the blog and I am just directly passing in the value of my published check box from params. Be sure to sanitize anything an end user can control, in this case only I use this behind an admin.
Now we need to define this method in the model, in my case "blog.rb". Its easier to show what this method looks like, then explain it.
Class Blog << ActiveRecord::Base
...
def publish?(bool)
bool ? self.published_at = Time.now : self.published_at = nil
end
end
We define this method just like any other, we expect a boolean as an input. First we simply set the published_at to Time.now if 1 is passed in (check box is checked) otherwise set published_at to nil, effectively un-publishing the blog. However, we do not want to update the published_at with a new timestamp if the article has already been published. Although this could be dependent on the expected behavior of the application, I personally don't think it makes sense. Reason is I sort articles by published_at, I do not want them popping back up if I go back and edit them. That is what I have an updated_at attribute for.
I often found myself wondering why bother with all this...just slap another conditional in the controller, copy paste, no big deal. However as you add more and more code, the controller quickly gets out of hand and turns into complete anarchy. Refactoring your code and continually enforcing the "fat model" theory will make your controllers (and code) much easier to manage later on. Take it from someone who as learned the hard way!
Thanks for reading... Sean
Posted in Ruby on Rails | no comments
Posted by BadReligion
Wed, 21 Jan 2009 11:06:00 GMT
In case it wasn’t obvious I use Lightbox to make my photo album a little flashy. However, I never really read the Lightbox documentation, I simply used the Rails plugin view helper. I have for a while been wondering how to pass in an array of pictures and have the ability to click through them in the light box. When I looked at the HTML generated by the view helper I realized it wasn’t doing much. See the Lightbox homepage for more info. Then after seeing how easy it is to tell Lightbox about having more than one picture I dove in. Bear in mind I have always steered clear of JavaScript. I just never liked it. Aw, forget it I’ll cut right to the point! I didn’t like the default layout of the light box. A hover property splits the light box 50/50 and uses that to display the previous and next buttons. I just wanted them to always be displayed at the bottom with the close button and other data.
I am not in the mood to describe everything I did with the code so here is a diff of the lightbox.js. I won’t post my hackish style sheet modifications…I won’t even go there….I hate writing CSS.
For some unexplainable reason I deleted some code while only commenting other code. Whatever, maybe someone will find this useful:
==
65,68c65
< //var fileBottomNavCloseImage = "/images/closelabel.gif";
< var fileBottomNavCloseImage = "/images/custom-close-label.png"
< var fileBottomNavNextImage = "/images/custom-nextlabel.png"
< var fileBottomNavPrevImage = "/images/custom-prevlabel.png"
---
> var fileBottomNavCloseImage = "/images/closelabel.gif";
73c70
< var resizeSpeed = 8; // controls the speed of the image resizing animations (1=slowest and 10=fastest)
---
> var resizeSpeed = 7; // controls the speed of the image resizing animations (1=slowest and 10=fastest)
296a294,303
> var objPrevLink = document.createElement("a");
> objPrevLink.setAttribute('id','prevLink');
> objPrevLink.setAttribute('href','#');
> objHoverNav.appendChild(objPrevLink);
>
> var objNextLink = document.createElement("a");
> objNextLink.setAttribute('id','nextLink');
> objNextLink.setAttribute('href','#');
> objHoverNav.appendChild(objNextLink);
>
335,352d341
< var objPrevLink = document.createElement("a");
< objPrevLink.setAttribute('id','prevLink');
< objPrevLink.setAttribute('href','#');
< objBottomNav.appendChild(objPrevLink);
<
< var objPrevLinkImage = document.createElement("img");
< objPrevLinkImage.setAttribute('src', fileBottomNavPrevImage);
< objPrevLink.appendChild(objPrevLinkImage);
<
< var objNextLink = document.createElement("a");
< objNextLink.setAttribute('id','nextLink');
< objNextLink.setAttribute('href','#');
< objBottomNav.appendChild(objNextLink);
<
< var objNextLinkImage = document.createElement("img");
< objNextLinkImage.setAttribute('src', fileBottomNavNextImage);
< objNextLink.appendChild(objNextLinkImage);
<
425,426c414,415
< //Element.hide('prevLink');
< //Element.hide('nextLink');
---
> Element.hide('prevLink');
> Element.hide('nextLink');
472,473c461,462
< //Element.setHeight('prevLink', imgHeight);
< //Element.setHeight('nextLink', imgHeight);
---
> Element.setHeight('prevLink', imgHeight);
> Element.setHeight('nextLink', imgHeight);
==
I am dirty, tired and don’t feel like writing about this anymore.
Sean
Posted in Ruby on Rails, Tech | no comments
Posted by BadReligion
Sat, 06 Dec 2008 12:19:00 GMT
Ever call a method on a class in Rails or even just Ruby and got this:
NoMethodError: undefined method `never’ for Time:Class
Now you swear on everyone that means anything to you, that the method you are using exists. Sure it does! No, really we believe you, but lets ask Ruby since, after all she should know best right! Now before I continue I wouldn’t know about this if some time ago my co-worker, Crazy Chicken Fingers, would not have told me about the methods method. So lets see what happens:
irb(main):003:0> Time.methods
=> ["inspect", "pretty_print", "private_class_method", "const_missing", "clone", "method", "public_methods", "public_instance_methods", "instance_variable_defined?", "method_defined?", "superclass", "equal?", "freeze", "mktime", "included_modules", "const_get", "pretty_print_instance_variables", "methods", "respond_to?", "_load", "module_eval", "class_variables", "now", "dup", "protected_instance_methods", "instance_variables", "public_method_defined?", "__id__", "pretty_inspect", "eql?", "object_id", "const_set", "id", "at", "singleton_methods", "send", "class_eval", "taint", "utc", "frozen?", "instance_variable_get", "include?", "private_instance_methods", "__send__", "instance_of?", "private_method_defined?", "to_a", "name", "autoload", "type", "new", "<", "protected_methods", "instance_eval", "<=>", "display", "==", ">", "===", "instance_method", "gm", "instance_variable_set", "kind_of?", "extend", "protected_method_defined?", "const_defined?", ">=", "ancestors", "to_s", "<=", "public_class_method", "pretty_print_cycle", "allocate", "hash", "pretty_print_inspect", "class", "instance_methods", "tainted?", "=~", "private_methods", "class_variable_defined?", "nil?", "untaint", "local", "times", "constants", "is_a?", "autoload?"]
irb(main):004:0>
Saweet! By the time I read through all of that I could have found the methods nicely formatted in the API, and my eyes will be burned up anyway. So lets add a little help using the pp helper. But first we need to require it in, unless you have it in your .irbrc file, and in that case why are you still reading?
irb(main):002:0> pp Time.methods
["inspect",
"pretty_print",
"private_class_method",
"const_missing",
"clone",
"method",
"public_methods",
"public_instance_methods",
"instance_variable_defined?",
"method_defined?",
"superclass",
"equal?",
"freeze",
"mktime",
"included_modules",
"const_get",
"pretty_print_instance_variables",
"methods",
"respond_to?",
"_load",
"module_eval",
"class_variables",
"now",
"dup",
"protected_instance_methods",
"instance_variables",
"public_method_defined?",
"__id__",
"pretty_inspect",
"eql?",
"object_id",
"const_set",
"id",
"at",
"singleton_methods",
"send",
"class_eval",
"taint",
"utc",
"frozen?",
"instance_variable_get",
"include?",
"private_instance_methods",
"__send__",
"instance_of?",
"private_method_defined?",
"to_a",
"name",
"autoload",
"type",
"new",
"<",
"protected_methods",
"instance_eval",
"<=>",
"display",
"==",
">",
"===",
"instance_method",
"gm",
"instance_variable_set",
"kind_of?",
"extend",
"protected_method_defined?",
"const_defined?",
">=",
"ancestors",
"to_s",
"<=",
"public_class_method",
"pretty_print_cycle",
"allocate",
"hash",
"pretty_print_inspect",
"class",
"instance_methods",
"tainted?",
"=~",
"private_methods",
"class_variable_defined?",
"nil?",
"untaint",
"local",
"times",
"constants",
"is_a?",
"autoload?"]
=> nil
irb(main):003:0>
Pretty cool eh? As I said a co-worker showed me the methods method some time ago and I have used it quite a bit since then. However, I often found myself having an idea of what functionality I’m searching for, therefore I can make an educated guess on what the method might be called. In this case this random list is still very inconvenient. So me being me I started looking for a method to sort the results, wouldn’t you know I found one called…SORT! Yes, amazing I know.
irb(main):004:0> pp Time.methods.sort
["<",
"<=",
"<=>",
"==",
"===",
"=~",
">",
">=",
"__id__",
"__send__",
"_load",
"allocate",
"ancestors",
"at",
"autoload",
"autoload?",
"class",
"class_eval",
"class_variable_defined?",
"class_variables",
"clone",
"const_defined?",
"const_get",
"const_missing",
"const_set",
"constants",
"display",
"dup",
"eql?",
"equal?",
"extend",
"freeze",
"frozen?",
"gm",
"hash",
"id",
"include?",
"included_modules",
"inspect",
"instance_eval",
"instance_method",
"instance_methods",
"instance_of?",
"instance_variable_defined?",
"instance_variable_get",
"instance_variable_set",
"instance_variables",
"is_a?",
"kind_of?",
"local",
"method",
"method_defined?",
"methods",
"mktime",
"module_eval",
"name",
"new",
"nil?",
"now",
"object_id",
"pretty_inspect",
"pretty_print",
"pretty_print_cycle",
"pretty_print_inspect",
"pretty_print_instance_variables",
"private_class_method",
"private_instance_methods",
"private_method_defined?",
"private_methods",
"protected_instance_methods",
"protected_method_defined?",
"protected_methods",
"public_class_method",
"public_instance_methods",
"public_method_defined?",
"public_methods",
"respond_to?",
"send",
"singleton_methods",
"superclass",
"taint",
"tainted?",
"times",
"to_a",
"to_s",
"type",
"untaint",
"utc"]
=> nil
Now that is something useful! Can’t tell you how many times I have used this and realized the method really does exist, that is was just a spelling mistake on my part…very frustrating to say the least!
There is a great article on how to pimp out your irb here.
Why is it that I just can’t remember to close my damn tags! Is it just me or all programmers?
Sean
Posted in Ruby on Rails, Tech | no comments
Posted by BadReligion
Sat, 06 Dec 2008 12:04:00 GMT
No! Not that kind of quickie!!!
I should already be asleep but I feel like talking code. So lately I was blown away that the ActiveRecord contained a count method but ActionSupport did not. For instance to find the number of comments for each blog I ended up doing this in my controller:
@comment_count = Comment.count(:conditions => "blog_id = #{params[:id]}")
So in my blogs controller I have a class defined show that looks like this:
def show
@blog = Blog.find(params[:id])
@comment = Comment.new
@ip = request.remote_ip
respond_to do |format|
format.html
format.xml { render :xml => @blog }
end
end
All I really need to do in my view for show is:
<%= @blog.comments.count %>
Since blog.comments actually performs an ActiveRecord find it is of that class, and therefore has the count method available.
If you are not operating on an ActiveRecord class, then what you can do instead is use the size method. For example:
@posts = [1, 2, 3, 5, 10]
=> [1, 2, 3, 5, 10]
@posts.size
=> 5
I really need to go to bed but I’m going to write tomorrow about some other fun things I’ve learned about Rails in the past couple days. Such as the lightbox plugin and more.
Sean
Posted in Ruby on Rails, Tech | no comments