While on Internship I've been asked not to blog anything that may appear in my report until after it has been marked. To minimize risk, this means radio silence. So far I've learned such an absolute mountain of information that it makes my earlier blog posts seem novice and I can fill in those blanks at a later date.
Thanks.
G
Monday, 24 March 2014
Sunday, 25 August 2013
Current Windows Environment
Small intro:
I have been introduced to vagrant and rvm several years back when they were both rather unpolished and I ran into several issued with them at the time. rvm still has some obscure bugs when you are really stretching the limits of what it was built for but I now feel comfortable that both of these tools have come far enough to surpass my usual workflow and they have entered my normal use now.
This is all installed ontop of Windows 7 x64.
You may need to install VirtualBox before vagrant as it needs to hook into it.
Install cygwin for the terminal, Vagrant for the machine and Sublime for the editor.
In cygwin: using Solarized Dark set in my .minttyrc for theme.
Using Arnold Clark's polygot for aliases in cygwin and vagrant.
I picked a debian box running on virtualbox but you can set this how you like. Vagrant Boxes
In cygwin terminal, cd ~
vagrant box add deb http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box
vagrant init deb
vagrant up
vagrant ssh
That's the machine done.
Now for ruby.
curl -L https://get.rvm.io | bash -s stable --ruby=1.9.3
Done!
Sublime setup:
Download sublime text 2
Package manager:
https://sublime.wbond.net/installation#st2
Get packages:
"Arnold Clark Snippets for Ruby",
"CoffeeScript",
"ERB Snippets",
"Rails Partial",
"rails_go_to_spec",
"rspec-snippets",
"Sass",
"SideBarEnhancements",
"StringEncode",
"TrailingSpaces"
Set keybindings (I've been working on a mac lately so some of these keybindings may seem wonky.)
{ "keys": ["alt+shift+l"], "command": "reindent", "args": { "single_line": false } },
{ "keys": ["alt+shift+`"], "command": "delete_trailing_spaces" },
{ "keys": ["alt+shift+h"], "command": "html_entitize" },
{ "keys": ["alt+shift+."], "command": "rails_go_to_spec" },
{ "keys": ["alt+control+right"], "command": "indent" },
{ "keys": ["alt+control+left"], "command": "unindent" },
{ "keys": ["alt+control+up"], "command": "swap_line_up" },
{ "keys": ["alt+control+down"], "command": "swap_line_down" },
{ "keys": ["alt+left"], "command": "move_to", "args": {"to": "bol", "extend": false} },
{ "keys": ["alt+right"], "command": "move_to", "args": {"to": "eol", "extend": false} },
{ "keys": ["shift+alt+left"], "command": "move_to", "args": {"to": "bol", "extend": true} },
{ "keys": ["shift+alt+right"], "command": "move_to", "args": {"to": "eol", "extend": true} }
I have been introduced to vagrant and rvm several years back when they were both rather unpolished and I ran into several issued with them at the time. rvm still has some obscure bugs when you are really stretching the limits of what it was built for but I now feel comfortable that both of these tools have come far enough to surpass my usual workflow and they have entered my normal use now.
This is all installed ontop of Windows 7 x64.
You may need to install VirtualBox before vagrant as it needs to hook into it.
Install cygwin for the terminal, Vagrant for the machine and Sublime for the editor.
In cygwin: using Solarized Dark set in my .minttyrc for theme.
Using Arnold Clark's polygot for aliases in cygwin and vagrant.
I picked a debian box running on virtualbox but you can set this how you like. Vagrant Boxes
In cygwin terminal, cd ~
vagrant box add deb http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box
vagrant init deb
vagrant up
vagrant ssh
That's the machine done.
Now for ruby.
curl -L https://get.rvm.io | bash -s stable --ruby=1.9.3
Done!
Sublime setup:
Download sublime text 2
Package manager:
https://sublime.wbond.net/installation#st2
Get packages:
"Arnold Clark Snippets for Ruby",
"CoffeeScript",
"ERB Snippets",
"Rails Partial",
"rails_go_to_spec",
"rspec-snippets",
"Sass",
"SideBarEnhancements",
"StringEncode",
"TrailingSpaces"
Set keybindings (I've been working on a mac lately so some of these keybindings may seem wonky.)
{ "keys": ["alt+shift+l"], "command": "reindent", "args": { "single_line": false } },
{ "keys": ["alt+shift+`"], "command": "delete_trailing_spaces" },
{ "keys": ["alt+shift+h"], "command": "html_entitize" },
{ "keys": ["alt+shift+."], "command": "rails_go_to_spec" },
{ "keys": ["alt+control+right"], "command": "indent" },
{ "keys": ["alt+control+left"], "command": "unindent" },
{ "keys": ["alt+control+up"], "command": "swap_line_up" },
{ "keys": ["alt+control+down"], "command": "swap_line_down" },
{ "keys": ["alt+left"], "command": "move_to", "args": {"to": "bol", "extend": false} },
{ "keys": ["alt+right"], "command": "move_to", "args": {"to": "eol", "extend": false} },
{ "keys": ["shift+alt+left"], "command": "move_to", "args": {"to": "bol", "extend": true} },
{ "keys": ["shift+alt+right"], "command": "move_to", "args": {"to": "eol", "extend": true} }
Set preferences:
"ensure_newline_at_eof_on_save": true,
"ignored_packages":
[
"Vintage"
],
"save_on_focus_lost": true,
"tab_size": 2,
"trailing_spaces_trim_on_save": true,
"translate_tabs_to_spaces": true
Sunday, 2 December 2012
Understanding REST In Practical Terms
I have been using Rails for a little while now and REST is always floating around conversations about designing things in Rails. It seemed like a nebulous topic so I did a little research of my own.
To my understanding it is all about building resources and nouns that respond to the HTTP verbs.
Instead of sending a GET request to http://www.example.co.uk/user/create , you PUT to http://www.example.co.uk/user
To my understanding it is all about building resources and nouns that respond to the HTTP verbs.
Instead of sending a GET request to http://www.example.co.uk/user/create , you PUT to http://www.example.co.uk/user
Similarly you POST to user/151 if you wish to update him.
It really is that simple.
There is one Gotcha though. If you want to delete user 151, you send a DELETE request to /user/151, you can then perfectly validly send another DELETE request to /user/151 because it is a word new to me, Idempotent, which roughly means you can do the same request to the same noun and the system will not change.
If I were to PUT (create) the same user twice, it is also idempotent and should only have the first user assuming you have some valid way of identifying duplicates.
There is one Gotcha though. If you want to delete user 151, you send a DELETE request to /user/151, you can then perfectly validly send another DELETE request to /user/151 because it is a word new to me, Idempotent, which roughly means you can do the same request to the same noun and the system will not change.
If I were to PUT (create) the same user twice, it is also idempotent and should only have the first user assuming you have some valid way of identifying duplicates.
Tuesday, 23 October 2012
Random interesting system thing of the day
Just a short one.
When you have delayed job (Or anything with lots of children)t gets tedious writing ps aux | grep del then 100x kill -STOP 11992, kill -STOP 11993, kill -STOP 11998...
Turns out pkill takes regex, meaning you can pkill -STOP delayed which will pause everything with delayed in the process name.
Also pgrep -l delayed finds all PID's of processes with Delayed in it.
Really handy!
Reference: http://linux.about.com/library/cmd/blcmdl1_pkill.htm
Turns out pkill takes regex, meaning you can pkill -STOP delayed which will pause everything with delayed in the process name.
Also pgrep -l delayed finds all PID's of processes with Delayed in it.
Really handy!
Reference: http://linux.about.com/library/cmd/blcmdl1_pkill.htm
Sunday, 21 October 2012
VPS experiance & Domain Name Registrar
This has been a busy week. I acquired a Virtual Private Server, a Domain and I have been having my first experiences with Apache2 since I am normally an Nginx man.
Firstly my reasons for getting a VPS are a few:
I did not want to leave my computer on all the time.
If I did leave my computer on, my IP is not static.
The electric bill would be more expensive than a small VPS anyway.
My main computer is windows so I would not get any of the lovely *NIX goodies through SSH.
A VPS is on all the time if I choose.
It is more online storage.
I wanted a personal GIT server.
I wanted to learn more about servers and networking.
So with this in mind, I started my search. Because I wanted it for personal use and GIT, I was looking for hard drive space over bandwidth or transfer limits.
A friend of mine at the university owned fusevps but sadly when I looked it appeared to be nuked from orbit.
My next stop was a VPS offers list: Low End Box, I like helping the local economy so I restricted my search to UK hosting and found several great offers from EaseVPS, CastleGem, Edis and MiniVPS. MiniVPS's offering fitted my criteria best and so I chose them to be my first VPS.
They have a nice control panel to change Operating Systems, shutdown, restart, change hostname, see usage graphs and the like which is nice, and their installs come with Apache2 running automatically which I did not expect. Overall I like the machine, it feels speedy enough and I have Gitolite set up so it really has everything I was going for.
So onto the next thing.
I managed to get my hands on bookofgreg.co.uk for a reasonable price from 123-reg (I didn't search around too much except to avoid godaddy), someone already had bookofgreg.com which is a little strange to think someone might be using my alias but seems it is not actively used at the moment. Using 123-reg's control panel I managed to set the DNS to point everything but mail to my VPS so I can happily use git@bookofgreg... now. It was at this point when checking the DNS was pointing to the right place I discovered Apache was running until it gave it's "everything is Ok" message when going to the browser.
Overall it is surprisingly quick, simple and easy to get a Domain name pointing to a VPS. Both VPS provider and Domain Name Registrar have everything automated to a T and it is such a quick and easy system. Very pleasantly surprised. Next Step, mail server setup (This is going to be HELL!)
Firstly my reasons for getting a VPS are a few:
I did not want to leave my computer on all the time.
If I did leave my computer on, my IP is not static.
The electric bill would be more expensive than a small VPS anyway.
My main computer is windows so I would not get any of the lovely *NIX goodies through SSH.
A VPS is on all the time if I choose.
It is more online storage.
I wanted a personal GIT server.
I wanted to learn more about servers and networking.
So with this in mind, I started my search. Because I wanted it for personal use and GIT, I was looking for hard drive space over bandwidth or transfer limits.
A friend of mine at the university owned fusevps but sadly when I looked it appeared to be nuked from orbit.
My next stop was a VPS offers list: Low End Box, I like helping the local economy so I restricted my search to UK hosting and found several great offers from EaseVPS, CastleGem, Edis and MiniVPS. MiniVPS's offering fitted my criteria best and so I chose them to be my first VPS.
They have a nice control panel to change Operating Systems, shutdown, restart, change hostname, see usage graphs and the like which is nice, and their installs come with Apache2 running automatically which I did not expect. Overall I like the machine, it feels speedy enough and I have Gitolite set up so it really has everything I was going for.
So onto the next thing.
I managed to get my hands on bookofgreg.co.uk for a reasonable price from 123-reg (I didn't search around too much except to avoid godaddy), someone already had bookofgreg.com which is a little strange to think someone might be using my alias but seems it is not actively used at the moment. Using 123-reg's control panel I managed to set the DNS to point everything but mail to my VPS so I can happily use git@bookofgreg... now. It was at this point when checking the DNS was pointing to the right place I discovered Apache was running until it gave it's "everything is Ok" message when going to the browser.
Overall it is surprisingly quick, simple and easy to get a Domain name pointing to a VPS. Both VPS provider and Domain Name Registrar have everything automated to a T and it is such a quick and easy system. Very pleasantly surprised. Next Step, mail server setup (This is going to be HELL!)
Friday, 21 September 2012
Process Watchman
Update: If the code it is running completes before the maximum time, it will block the program from completing until the time runs out. Still needs work! (Read: It doesn't work XD)
I was looking for a process monitor, sort of like monit, or god but these two solutions are for keeping a process alive or restarting a process if it is misbehaving. What I wanted was a simple process watcher that would simply kill a process if it misbehaves or runs out of time, while returning the completed or partial output of the process it was watching.
For this I quickly wrote a small tool to do this on *nix machines.
It is quite hacked together so I must apologise for the mess, it is in its first version here and the program was written as fast as I could imagine without prior design. There will be numerable ways of improving this tool.
Currently it accepts 3 args, a command, an integer value for seconds and a float value for ram megabytes. There is probably a problem with commands that are more than one word long which is most of them, experimentation and improvements are needed.
I was looking for a process monitor, sort of like monit, or god but these two solutions are for keeping a process alive or restarting a process if it is misbehaving. What I wanted was a simple process watcher that would simply kill a process if it misbehaves or runs out of time, while returning the completed or partial output of the process it was watching.
For this I quickly wrote a small tool to do this on *nix machines.
It is quite hacked together so I must apologise for the mess, it is in its first version here and the program was written as fast as I could imagine without prior design. There will be numerable ways of improving this tool.
Currently it accepts 3 args, a command, an integer value for seconds and a float value for ram megabytes. There is probably a problem with commands that are more than one word long which is most of them, experimentation and improvements are needed.
#Author: Greg Myers
#Date: 30/08/12
@command = ARGV[0]
@time_limit = ARGV[1].to_i #seconds
@ram_limit = ARGV[2].to_f #megabytes
def watch_time(sec)
exception = Class.new(Interrupt)
begin
x = Thread.current #x will contain whatever runs in yield
y = Thread.start { #y watches and causes x to throw when timeout.
begin
sleep(sec)
rescue => e #This raises any error x naturally hits
x.raise e
else #This executes if no exceptions happened until now
x.raise "Process ran out of time to execute."
end
}
return yield(sec)
ensure
if y
y.kill
y.join
end
end
end
def watch_ram(megabytes, pid)
exception = Class.new(Interrupt)
begin
x = Thread.current #x will contain whatever runs in yield
y = Thread.start { #y watches and causes x to throw when timeout.
begin
loop {
rss_use = `ps -o rss= -p #{pid}`.to_i #use ps to get rss of pid
raise "Hit Ram Limit #{megabytes*1024}kb, with #{rss_use}kb" if megabytes*1024 < rss_use
sleep(0.5)
}
rescue => e #This raises any error x naturally hits
x.raise e
end
}
return yield
ensure
if y
y.kill
y.join
end
end
end
def get_payload_child_pid(pid)
pipe = IO.popen("ps -ef | grep #{pid}")
pipe.readlines[2] =~ /\w+\s+(?\d+)\s+(?\d+)/ #Always line 3, Line 1 = spawn cmd, Line 2 = IO.popen, Line 3 = ruby, Line 4 = grep
pipe.close
return $~[:child_pid]
end
if @command
if @time_limit > 1
if @ram_limit > 0
watch_time(@time_limit){
require 'pty'
PTY.spawn("#{@command} 2>&1") do |r,w,p|
child_pid = get_payload_child_pid(p)
watch_ram(@ram_limit, child_pid){ loop { puts r.gets } }
end
}
else
puts "Invalid memory limit #{ARGV[2]}"
end
else
puts "Invalid time limit #{ARGV[1]}"
end
else
puts "Invalid command #{ARGV[0]}"
end
I will be putting this on github publicly shortly.
Multicore programming with ruby
As I understand it multicore programming is about the ability to utilize multiple CPUs.
Also I hear a lot of people saying ruby cannot use multiple CPUs.
This is a load of rubbish if you are on a *nix system.
All you have to do if you want to use multiple CPUs is fork{} and it is running in its own process.
You can leave whatever is in the block to run and reap the process later, or detatch it if you do not need to see the results.
Fork returns the PID of the process it spawns, and used with Process.waitpid(), you can make the main process wait for the results to come back from the child. If you want the results yourself, you can just open a pipe between the child and the main process with IO.pipe
Simple.
read, write = IO.pipe
pid = fork do
write.puts "test"
end
Process.waitpid(pid)
write.close
puts read.read
read.close
Resources:
http://www.ruby-doc.org/core-1.9.3/IO.html
http://www.ruby-doc.org/core-1.9.3/Process.html
Example based on:
http://stackoverflow.com/questions/1076257/returning-data-from-forked-processes
Also I hear a lot of people saying ruby cannot use multiple CPUs.
This is a load of rubbish if you are on a *nix system.
All you have to do if you want to use multiple CPUs is fork{} and it is running in its own process.
You can leave whatever is in the block to run and reap the process later, or detatch it if you do not need to see the results.
Fork returns the PID of the process it spawns, and used with Process.waitpid(), you can make the main process wait for the results to come back from the child. If you want the results yourself, you can just open a pipe between the child and the main process with IO.pipe
Simple.
read, write = IO.pipe
pid = fork do
write.puts "test"
end
Process.waitpid(pid)
write.close
puts read.read
read.close
Resources:
http://www.ruby-doc.org/core-1.9.3/IO.html
http://www.ruby-doc.org/core-1.9.3/Process.html
Example based on:
http://stackoverflow.com/questions/1076257/returning-data-from-forked-processes
Thursday, 16 August 2012
Rails Time
Earlier in the month I was experiencing some odd behaviour in ruby.
irb(main):002:0> DateTime.now
=> Mon, 13 Aug 2012 17:04:34 +0100
irb(main):003:0> DateTime.now + 2.days
=> Sat, 22 Sep 2485 17:04:42 +0100
DateTime is a class with a limit that goes up to year 9999 and as far as I can tell isn't stored as seconds, the more commonly used Time class is measured in seconds and goes up to 03:14:08 UTC on 19 January 2038 on 32 bit (thanks Wikipedia). All the Railsy time goodies (example, 5.weeks.from_now) are measured in seconds too, and so are only compatible with Time (or Date) class but not DateTime.
It is almost misleading that ActiveRecord says time is stored as DateTime in databases, it is actually stored as Time.
References
DateTime
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/DateTime.html
Date
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/Date.html
Time in Core
http://ruby-doc.org/core-1.9.3/Time.html
Time in Date. The difference is this has to_date, to_time, and to_datetime methods.
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/Time.html
Tuesday, 31 July 2012
Story of Compiling Kernel for Linux VServer
So I've been having a fun week.
This is my first time compiling a kernel and It should be straight forward as there are some helpful websites available on just this topic:
pre-requisites:
Patience. This will take an hour (or more) on a decent quad core machine.
gcc-<version>-plugin-dev
fakeroot
make-kpkg
libncurses5-dev
On compiling the kernel with the VServer patch
http://linux-vserver.org/Installation_on_Linux_2.6
On compiling a general kernel
http://www.howtoforge.com/kernel_compilation_ubuntu
On using your complete kernel
http://www.centos.org/docs/2/rhl-cg-en-7.2/buildkernel-bootloader.html
I was running the commands on a Ubuntu12.04 virtualbox machine, following the Vserver instructions and while running make, it kept running out of disk space.
A quick google tells me the result should be about 500MB at most, and doesn't even tell you what the result should be. My attempts kept running out of space after about 40 minutes and after hitting 8GB used space, of which almost all the room was taken up by vmlinux (2.9GB) and vmlinux.o (4.9GB)
Apparently this is not normal.
Eventually after making a virtual hd with a size of 100GB (of which the result was just short of 9GB itself) it appeared to say a build of bzimage in /arch/boot/x86 folder was completed. This I could never find anywhere in the folder.
I am currently compiling using the howtoforge.com link so we will see how much success I shall have later on.
Currently I am getting GCC error "array subscript is above array bounds" quite a lot but it appears to be ignoring it.
#Edit
Its been 2 hours. I didn't set CONCURENCY_LEVEL= because of fear of it crashing. Starting to wonder if it was a mistake given how long this is taking. It is still compiling and it has just moved from ./drivers to ./fs. My favourite file list, sudo du --max-depth=1 -h | sort -rh , reports file is at 7.9GB and growing.
7.9G .
4.8G ./drivers
689M ./net
602M ./fs
316M ./arch
259M ./sound
126M ./kernel
76M ./security
58M ./crypto
41M ./mm
34M ./lib
31M ./include
19M ./Documentation
17M ./block
13M ./.tmp_versions
6.8M ./firmware
6.2M ./ipc
5.0M ./grsecurity
4.7M ./init
4.1M ./tools
3.8M ./scripts
2.8M ./virt
2.0M ./debian
156K ./samples
92K ./usr
This is my first time compiling a kernel and It should be straight forward as there are some helpful websites available on just this topic:
pre-requisites:
Patience. This will take an hour (or more) on a decent quad core machine.
gcc-<version>-plugin-dev
fakeroot
make-kpkg
libncurses5-dev
On compiling the kernel with the VServer patch
http://linux-vserver.org/Installation_on_Linux_2.6
On compiling a general kernel
http://www.howtoforge.com/kernel_compilation_ubuntu
On using your complete kernel
http://www.centos.org/docs/2/rhl-cg-en-7.2/buildkernel-bootloader.html
I was running the commands on a Ubuntu12.04 virtualbox machine, following the Vserver instructions and while running make, it kept running out of disk space.
A quick google tells me the result should be about 500MB at most, and doesn't even tell you what the result should be. My attempts kept running out of space after about 40 minutes and after hitting 8GB used space, of which almost all the room was taken up by vmlinux (2.9GB) and vmlinux.o (4.9GB)
Apparently this is not normal.
Eventually after making a virtual hd with a size of 100GB (of which the result was just short of 9GB itself) it appeared to say a build of bzimage in /arch/boot/x86 folder was completed. This I could never find anywhere in the folder.
I am currently compiling using the howtoforge.com link so we will see how much success I shall have later on.
Currently I am getting GCC error "array subscript is above array bounds" quite a lot but it appears to be ignoring it.
#Edit
Its been 2 hours. I didn't set CONCURENCY_LEVEL= because of fear of it crashing. Starting to wonder if it was a mistake given how long this is taking. It is still compiling and it has just moved from ./drivers to ./fs. My favourite file list, sudo du --max-depth=1 -h | sort -rh , reports file is at 7.9GB and growing.
7.9G .
4.8G ./drivers
689M ./net
602M ./fs
316M ./arch
259M ./sound
126M ./kernel
76M ./security
58M ./crypto
41M ./mm
34M ./lib
31M ./include
19M ./Documentation
17M ./block
13M ./.tmp_versions
6.8M ./firmware
6.2M ./ipc
5.0M ./grsecurity
4.7M ./init
4.1M ./tools
3.8M ./scripts
2.8M ./virt
2.0M ./debian
156K ./samples
92K ./usr
Tuesday, 10 July 2012
Foolproof FactoryGirl Sequence
Turns out Sequencing in FactoryGirl isn't as easy as it used to be.
Factory.next has been deprecated and the two obvious ways to make a sequence now throw Trait error or Attribute already defined error "FactoryGirl::AttributeDefinitionError"
The problem with this first approach is name. In a normal sequence you would just say name but I want to use it in the description too. This somehow makes FactoryGirl believe name is a trait.
FactoryGirl.define do
sequence(:code) {|n| "#{n+1000}"}
factory :course do |u|
name "CS#{ generate :code }"
description "#{name}, 1st year, 1st semester, Foundation Of #{name}"
end
end
This next example has a problem with the description line. This causes the description to generate 2 more names and throw an AttributeDefinitionError because you now have more than 1 name generated.
For some reason you cannot get around it by making the name line name = Factory.generate :name because name becomes a Trait again.
FactoryGirl.define do
sequence(:name) {|n| "CS#{n+1000}"}
factory :course do |u|
name
description "#{name}, 1st year, 1st semester, Foundation Of #{name}"
end
end
This is the only thing that works. Static forcing FactoryGirl to use the already defined name again using the |a| block in description. It isn't as pretty as it could be but I have to live with it unless someone can tell me a better way. There is probably a solution where you use an after_build tag but that makes it longer and more complicated unnecessarily and it would still be ugly.
FactoryGirl.define do
sequence(:name) {|n| "CS#{n+1000}"}
factory :course do |u|
u.name
u.description {|a| "#{a.name}, 1st year, 1st semester, Foundation Of #{a.name}"}
end
end
Factory.next has been deprecated and the two obvious ways to make a sequence now throw Trait error or Attribute already defined error "FactoryGirl::AttributeDefinitionError"
The problem with this first approach is name. In a normal sequence you would just say name but I want to use it in the description too. This somehow makes FactoryGirl believe name is a trait.
FactoryGirl.define do
sequence(:code) {|n| "#{n+1000}"}
factory :course do |u|
name "CS#{ generate :code }"
description "#{name}, 1st year, 1st semester, Foundation Of #{name}"
end
end
This next example has a problem with the description line. This causes the description to generate 2 more names and throw an AttributeDefinitionError because you now have more than 1 name generated.
For some reason you cannot get around it by making the name line name = Factory.generate :name because name becomes a Trait again.
FactoryGirl.define do
sequence(:name) {|n| "CS#{n+1000}"}
factory :course do |u|
name
description "#{name}, 1st year, 1st semester, Foundation Of #{name}"
end
end
This is the only thing that works. Static forcing FactoryGirl to use the already defined name again using the |a| block in description. It isn't as pretty as it could be but I have to live with it unless someone can tell me a better way. There is probably a solution where you use an after_build tag but that makes it longer and more complicated unnecessarily and it would still be ugly.
FactoryGirl.define do
sequence(:name) {|n| "CS#{n+1000}"}
factory :course do |u|
u.name
u.description {|a| "#{a.name}, 1st year, 1st semester, Foundation Of #{a.name}"}
end
end
Monday, 2 July 2012
Importing a CSV File from Upload in Rails >= 3
For some reason I found the documentation for CSV's really bad!
What I wanted to do is accept a file from a form and parse it into a list of users to be added to the database without saving the CSV file. (Note: I DO save the file via the Paperclip Gem for logging purposes but I do all the processing from the file before it is saved to the database.)
When you have uploaded the file using Form_Tag, the file is usually in params[:name] where :name is tag you gave to file_field_tag :name
If you are using a Form_For, which by the way is strange if you do not intend to save it to the model in question, the file will be in params[:model][:name] from f.file_field :name
The magic part is to actually get to the file you need to call .read on it.
In the View remember to make it multipart to accept files.
<%= form_for @model, :html => { :multipart => true } do |f| %>
<%= f.label :file %><br />
<%= f.file_field :file %><br />
<%= f.submit "Upload" %>
<% end %>
In the Controller require csv, you do not need to install it as a gem but you do need to require it as it is in standard library not core.
require 'csv'
def my_method
@lines = []
CSV.parse(params[:submission][:file].read) do |row|
@lines << row
end
Replace the yellow bits with whatever you want to do with your CSV file.
Have fun!
What I wanted to do is accept a file from a form and parse it into a list of users to be added to the database without saving the CSV file. (Note: I DO save the file via the Paperclip Gem for logging purposes but I do all the processing from the file before it is saved to the database.)
When you have uploaded the file using Form_Tag, the file is usually in params[:name] where :name is tag you gave to file_field_tag :name
If you are using a Form_For, which by the way is strange if you do not intend to save it to the model in question, the file will be in params[:model][:name] from f.file_field :name
The magic part is to actually get to the file you need to call .read on it.
In the View remember to make it multipart to accept files.
<%= form_for @model, :html => { :multipart => true } do |f| %>
<%= f.label :file %><br />
<%= f.file_field :file %><br />
<%= f.submit "Upload" %>
<% end %>
In the Controller require csv, you do not need to install it as a gem but you do need to require it as it is in standard library not core.
require 'csv'
def my_method
@lines = []
CSV.parse(params[:submission][:file].read) do |row|
@lines << row
end
Replace the yellow bits with whatever you want to do with your CSV file.
Have fun!
Sunday, 24 June 2012
Cucumber Feature Fun
This post will be expanded later. For now its just a note to self.
http://lmarburger.github.com/2009/09/cucumber-features-in-subdirectories.html
http://robots.thoughtbot.com/post/189412598/five-ridiculously-awesome-cucumber-and-webrat
NOTE TO SELF:
Cucumber will not find step definitions when running a single feature unless you tell it to require the whole folder.
Good
cucumber --require folder_with_step_definitions feature_file_I_want_to_run
Real life Example:
cucumber -r features features/courses #whole folder
cucumber -r features features/courses/new_course.feature #Single Feature
Bad
cucumber feature_file_I_want_to_run
#Will hit a wall of Step Definition Missing messages.
cucumber -r /features /features/courses #Will cause it to start looking from Root and not Rails.root causing File Not Found issues
http://lmarburger.github.com/2009/09/cucumber-features-in-subdirectories.html
http://robots.thoughtbot.com/post/189412598/five-ridiculously-awesome-cucumber-and-webrat
NOTE TO SELF:
Cucumber will not find step definitions when running a single feature unless you tell it to require the whole folder.
Good
cucumber --require folder_with_step_definitions feature_file_I_want_to_run
Real life Example:
cucumber -r features features/courses #whole folder
cucumber -r features features/courses/new_course.feature #Single Feature
Bad
cucumber feature_file_I_want_to_run
#Will hit a wall of Step Definition Missing messages.
cucumber -r /features /features/courses #Will cause it to start looking from Root and not Rails.root causing File Not Found issues
Saturday, 19 May 2012
CSS Basics
I'm a shameless novice at CSS at the moment.
I'm just going through CSS at http://cssxcountry.codeschool.com and Just thought I'd take a second to note down some things that need noting in my head about CSS. This post therefore will be messy and perpetually unfinished. You were warned.
Targetting CSS:
<h1> is caught with h1 { someCSS; }
class="coffee" is caught with .coffee { someCSS; }
and,
id="tea" is caught with #tea
Compound CSS: multi-word classes or IDs
First, if class="some thing"
the CSS for it will NOT be .some thing, it will be .some.thing as it is like having class="some" and class="thing"
Note: I don't know if having multiple classes in the CSS is even allowable.
Text:
center is a possible option for text-align
bold, italic and similar are in font-style
Other:
CSS does not care if it has a space between an attribute and value.
float: right;
float:right;
Both are valid.
Elements in CSS are space separated, whereas classes or IDs are attached. li p.intro#first
ShorthandCSS fragments from http://www.dustindiaz.com/css-shorthand/
Font
element {
font-style: normal;
font-variant:normal;
font-weight: normal;
font-size: inherit;
line-height: normal;
font-family:inherit;
}
font shorthand oddity: http://www.impressivewebs.com/css-font-shorthand-property-cheat-sheet/
The style, variant and weight can be ommited and the line-height is seperated by the / character.
Margin
element {
margin-top: number+unit;
margin-right: number+unit;
margin-bottom: number+unit;
margin-left: number+unit;
}
I'm just going through CSS at http://cssxcountry.codeschool.com and Just thought I'd take a second to note down some things that need noting in my head about CSS. This post therefore will be messy and perpetually unfinished. You were warned.
Targetting CSS:
<h1> is caught with h1 { someCSS; }
class="coffee" is caught with .coffee { someCSS; }
and,
id="tea" is caught with #tea
Compound CSS: multi-word classes or IDs
First, if class="some thing"
the CSS for it will NOT be .some thing, it will be .some.thing as it is like having class="some" and class="thing"
Note: I don't know if having multiple classes in the CSS is even allowable.
Text:
center is a possible option for text-align
bold, italic and similar are in font-style
Other:
CSS does not care if it has a space between an attribute and value.
float: right;
float:right;
Both are valid.
Elements in CSS are space separated, whereas classes or IDs are attached. li p.intro#first
ShorthandCSS fragments from http://www.dustindiaz.com/css-shorthand/
Font
element {
font-style: normal;
font-variant:normal;
font-weight: normal;
font-size: inherit;
line-height: normal;
font-family:inherit;
}
font shorthand oddity: http://www.impressivewebs.com/css-font-shorthand-property-cheat-sheet/
The style, variant and weight can be ommited and the line-height is seperated by the / character.
Margin
element {
margin-top: number+unit;
margin-right: number+unit;
margin-bottom: number+unit;
margin-left: number+unit;
}
Friday, 27 April 2012
CSS positioning and Stacking images in rails.
So you are using Ruby on Rails and you want a method of stacking images on top of each other.
Your answer will probably involve CSS but many of the blog posts and Q&A posts I found weren't too descriptive so here is my shot at explaining this from the perspective of someone who doesn't use CSS often.
<div id="container">
<div id="contained">
</div>
</div>
This does not work with class instead of id.
<div class="container">
<div class="contained">
</div>
</div>
The technique is to have a position:relative parent container, so that all position:absolute items inside are in the same place against the relative container. Note that the container needs a size, it will not take the size of absolute children. My images are 64px*64px big so I have to force my container to be that large or the next HTML element in the flow will overlap it.
In application.css.scss
#container {
position:relative;
width: 64px;
height: 64px;
}
#image {
position: absolute;
top: 0;
left: 0;
}
This lets you place images with the id="image" inside a div of id="container". In my code I stack City.png vertically above Grass.png in the view. Note in versions of Rails before 3.1 you need to use :id => instead of the new syntax id:
<div id="container">
<%= image_tag("Grass.png", id:"image") %>
<%= image_tag("City.png", id:"image") %>
</div>
Your answer will probably involve CSS but many of the blog posts and Q&A posts I found weren't too descriptive so here is my shot at explaining this from the perspective of someone who doesn't use CSS often.
First a short bit on parents in CSS
When using CSS, having one style inside the other makes the top level the parent. In this example the div with the id of "container" is the parent of the div with the id of "contained".<div id="container">
<div id="contained">
</div>
</div>
This does not work with class instead of id.
And the CSS position
There are several good resources explaining position and I will just link to my favourites.
http://www.barelyfitz.com/screencast/html-training/css/positioning/
http://www.barelyfitz.com/screencast/html-training/css/positioning/
Onto the good stuff
Our CSS files are in assets/stylesheets/ and the one we are using is the application wide stylesheet application.css.scssThe technique is to have a position:relative parent container, so that all position:absolute items inside are in the same place against the relative container. Note that the container needs a size, it will not take the size of absolute children. My images are 64px*64px big so I have to force my container to be that large or the next HTML element in the flow will overlap it.
In application.css.scss
#container {
position:relative;
width: 64px;
height: 64px;
}
#image {
position: absolute;
top: 0;
left: 0;
}
This lets you place images with the id="image" inside a div of id="container". In my code I stack City.png vertically above Grass.png in the view. Note in versions of Rails before 3.1 you need to use :id => instead of the new syntax id:
<div id="container">
<%= image_tag("Grass.png", id:"image") %>
<%= image_tag("City.png", id:"image") %>
</div>
Sunday, 22 April 2012
Slim Rails Environment V2
Install Ubuntu Server with whatever settings you like (Default for me)
Remember that when using the xOrg system (xinit), you make it run from terminal with 'xinit' or 'startx'
You can open programs including the terminal from the right click menu in fluxbox.
You cannot copy-paste easily within xOrg unless you use terminator.
Update 24/06/12: !If you are using Bruce Scharlau's vm_template virtual box, and cannot Sudo apt-get anything due to 407 error, /etc/apt/apt.conf has the proxy defined in it and you can simply remove/replace the line as needed.
#System
sudo apt-get install xinit
sudo apt-get install fluxbox
sudo apt-get install build-essential
#Node.js Rails will not run without a Javascript Engine
sudo apt-get install python-software-properties
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
#Rails
sudo apt-get install ruby1.9.1-dev
sudo gem install rails
#Using these three will install all the generic gems
#rails new cookbook
#cd cookbook
#bundle install
##Gem Specific
#Sqlite3
sudo apt-get install sqlite3 libsqlite3-dev
sudo gem install sqlite3
#Cucumber-rails
sudo apt-get install libxml2-dev libxslt-dev
sudo gem install cucumber-rails
#Postgresql gem
#Even if you do not use postgresql on your development machine, by just listing the gem anywhere in your gemfile, you need the libraries to make postgres work for bundle install. This is needed for Heroku.
sudo apt-get install libpq-dev #Note libpq NOT libpg
##Other Programs
#Terminator (Better terminal)
sudo apt-get install terminator
#Google Chrome (web Browser)
sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
sudo apt-get update
sudo apt-get install google-chrome-stable
#sqlitebrowser (SQLite3 browser)
sudo apt-get install sqlitebrowser
#git
sudo apt-get install git
#Komodo ~Broken
~I have not yet got this working on xinit. Use Nedit or nano instead.
Edit: Or if you are using Ubuntu in a VM, start up a shared folder and run Komodo outside the VM
Aded 24/06/12:
Since this is useful and interesting to people, here is how I work:
When working, I have the virtual machine open on 1/3 of my screen. In it I have terminator open, with a tab for all git commands, a tab for all rails, system and developement commands, a tab for running rails s if I am testing in chrome, and a tab for running guard in (guard is a gem that automatically runs all rails tasks on file change) I will open a chrome window at the bottom of this area if I need to look at my app outside testing.
The only two changes I have made to Bruce's VM is I have made a symlink from /media/sf_vm_shared to ~/shared so it is in my home folder, and I have removed the proxy line in /etc/apt/apt.conf since I do not bring my desktop onto campus.
The remaining 2/3 of my screen has komodo edit running in the windows environment which edits the files through the shared c:/vm_shared folder.
Remember that when using the xOrg system (xinit), you make it run from terminal with 'xinit' or 'startx'
You can open programs including the terminal from the right click menu in fluxbox.
You cannot copy-paste easily within xOrg unless you use terminator.
Update 24/06/12: !If you are using Bruce Scharlau's vm_template virtual box, and cannot Sudo apt-get anything due to 407 error, /etc/apt/apt.conf has the proxy defined in it and you can simply remove/replace the line as needed.
#System
sudo apt-get install xinit
sudo apt-get install fluxbox
sudo apt-get install build-essential
#Node.js Rails will not run without a Javascript Engine
sudo apt-get install python-software-properties
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
#Rails
sudo apt-get install ruby1.9.1-dev
sudo gem install rails
#Using these three will install all the generic gems
#rails new cookbook
#cd cookbook
#bundle install
##Gem Specific
#Sqlite3
sudo apt-get install sqlite3 libsqlite3-dev
sudo gem install sqlite3
#Cucumber-rails
sudo apt-get install libxml2-dev libxslt-dev
sudo gem install cucumber-rails
#Postgresql gem
#Even if you do not use postgresql on your development machine, by just listing the gem anywhere in your gemfile, you need the libraries to make postgres work for bundle install. This is needed for Heroku.
sudo apt-get install libpq-dev #Note libpq NOT libpg
##Other Programs
#Terminator (Better terminal)
sudo apt-get install terminator
#Google Chrome (web Browser)
sudo wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
sudo apt-get update
sudo apt-get install google-chrome-stable
#sqlitebrowser (SQLite3 browser)
sudo apt-get install sqlitebrowser
#git
sudo apt-get install git
#Komodo ~Broken
~I have not yet got this working on xinit. Use Nedit or nano instead.
Edit: Or if you are using Ubuntu in a VM, start up a shared folder and run Komodo outside the VM
Aded 24/06/12:
My Workflow
Since this is useful and interesting to people, here is how I work:
When working, I have the virtual machine open on 1/3 of my screen. In it I have terminator open, with a tab for all git commands, a tab for all rails, system and developement commands, a tab for running rails s if I am testing in chrome, and a tab for running guard in (guard is a gem that automatically runs all rails tasks on file change) I will open a chrome window at the bottom of this area if I need to look at my app outside testing.
The only two changes I have made to Bruce's VM is I have made a symlink from /media/sf_vm_shared to ~/shared so it is in my home folder, and I have removed the proxy line in /etc/apt/apt.conf since I do not bring my desktop onto campus.
The remaining 2/3 of my screen has komodo edit running in the windows environment which edits the files through the shared c:/vm_shared folder.
Why not to test everything with Capybara
Firstly, I like Capybara. I think it is nice how easy it is to test with just a few verbs, and you can do things from the perspective of the user. It is no good having the back end for a feature if nobody is ever going to click the button to make it happen. I decided to try do an entire project using just Capybara for testing.
However this comes at a price. Each assertion restarts Rails Server.
This is VERY slow for lots of tests to the point where each test takes about 2 seconds in my current project.
I suppose a drawback some people might make is my tests are tightly bound to the actual view which is another drawback of using Capybara.
Yet another issue I am hitting is organization, all my Capybara tests end up in the same Requests folder which is quite naughty of me.
So, Capybara is slow on many assertions, it links you to the way you display information, and it makes me personally use a disorganised file structure.
Conclusion is I should not use entirely Capybara for the entire project testing. I really need to mix Rspec in there with occasional sprinkles of Capybara.
However this comes at a price. Each assertion restarts Rails Server.
This is VERY slow for lots of tests to the point where each test takes about 2 seconds in my current project.
I suppose a drawback some people might make is my tests are tightly bound to the actual view which is another drawback of using Capybara.
Yet another issue I am hitting is organization, all my Capybara tests end up in the same Requests folder which is quite naughty of me.
So, Capybara is slow on many assertions, it links you to the way you display information, and it makes me personally use a disorganised file structure.
Conclusion is I should not use entirely Capybara for the entire project testing. I really need to mix Rspec in there with occasional sprinkles of Capybara.
Friday, 20 April 2012
Komodo Edit and Chrome on Ubuntu 11.10
Komodo Edit and Chrome have different methods of installing to anything you can get from the apt repository.
I am using Ubuntu 11.10 64bit on a VM Virtual box with guest additions.
The dates in my links are the dates I saw them, as things change over time like the differences of Rails since 2006.
Firstly for Google Chrome:
My source is How to open source (as on 03/04/12)
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - from Google Linux Repositories (as on 03/03/12)
sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
sudo apt-get update
sudo apt-get install google-chrome-stable
To find the newest Komodo Edit version, browse around http://downloads.activestate.com/Komodo/releases/
For Komodo Edit 7.02 x64
Download using chrome: http://downloads.activestate.com/Komodo/releases/7.0.2/Komodo-Edit-7.0.2-9923-linux-x86_64.tar.gz
tar -xvzf Komodo-Edit-7.0.2-9923-linux-x86_64.tar.gz
Then make a .desktop file.
Source: http://www.ubuntugeek.com/how-to-create-desktop-launchers-in-ubuntu-11-10oneiric.html (on 20/04/12)
sudo apt-get install --no-install-recommends gnome-panel
gnome-desktop-item-edit ~/Desktop/ --create-new
This will make a popup where you can set the Icon and App location. The icons to use are in the Share folder, and the application is in the Bin folder.
I am using Ubuntu 11.10 64bit on a VM Virtual box with guest additions.
The dates in my links are the dates I saw them, as things change over time like the differences of Rails since 2006.
Firstly for Google Chrome:
My source is How to open source (as on 03/04/12)
wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - from Google Linux Repositories (as on 03/03/12)
sudo sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
sudo apt-get update
sudo apt-get install google-chrome-stable
To find the newest Komodo Edit version, browse around http://downloads.activestate.com/Komodo/releases/
For Komodo Edit 7.02 x64
Download using chrome: http://downloads.activestate.com/Komodo/releases/7.0.2/Komodo-Edit-7.0.2-9923-linux-x86_64.tar.gz
tar -xvzf Komodo-Edit-7.0.2-9923-linux-x86_64.tar.gz
Then make a .desktop file.
Source: http://www.ubuntugeek.com/how-to-create-desktop-launchers-in-ubuntu-11-10oneiric.html (on 20/04/12)
sudo apt-get install --no-install-recommends gnome-panel
gnome-desktop-item-edit ~/Desktop/ --create-new
This will make a popup where you can set the Icon and App location. The icons to use are in the Share folder, and the application is in the Bin folder.
Thursday, 5 April 2012
Generic Gem Install Error Solving
Installing pg (0.13.2) with native extensions
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
/usr/bin/ruby1.9.1 extconf.rb
checking for pg_config... no
No pg_config... trying anyway. If building fails, please try again with
--with-pg-config=/path/to/pg_config
checking for libpq-fe.h... no
Can't find the 'libpq-fe.h header
*** extconf.rb failed ***
I highlighted the interesting bit. If you are on Ubuntu, the header is generally related to the package you are missing.
If you type libpq in a terminal, it helpfully tells you to try sudo apt-get install libpq
That will deal with this problem and many others like it.
Other variants of the problem are similar to the stack overflow problem: http://stackoverflow.com/q/10198002/193785
Here it is not a .h file but as some other kind of generic library. checking for main() in -lopenal... no
1:Sudo apt-get install openal
2:Sudo apt-get install openal-dev
3:Sudo apt-get install libopenal
One of these three solutions will probably work.
Thursday, 29 March 2012
Something about TDD I never expected.
There is one thing I have always thought about programming, is that to do it, you need a couple of hours and to sit down and get in the zone. You really have to settle in and let it absorb you.
This is a bit of a problem when you have just an hour or less to spare because you know just as you actually get what the piece of code does, you need to give up and set off.
However, with test driven development, I can sit down, run bundle exec guard (A gem that runs all my specs for me when a file changes) and if I finished last while writing spec, I will put a spoof method like ENDED_HERE in the code, and it will flash up, or if tests fail, then I can jump straight to the piece of code that breaks.
I can sit down for just 10 mins at a time and make it pass a couple lines of spec and push up the code and go to work/lunch/friends/pub as needed.
However, with test driven development, I can sit down, run bundle exec guard (A gem that runs all my specs for me when a file changes) and if I finished last while writing spec, I will put a spoof method like ENDED_HERE in the code, and it will flash up, or if tests fail, then I can jump straight to the piece of code that breaks.
I can sit down for just 10 mins at a time and make it pass a couple lines of spec and push up the code and go to work/lunch/friends/pub as needed.
Wednesday, 28 March 2012
Stumbling blocks
I've been bumbling through a few self-made hurdles the last few days and they all unraveled when I sat an unknowledgeable friend next to me and spoke at him as I worked through my problem. This is what I call the rubber duck method.
New knowledge 1)
@thing.user_id = User.find_by_email(params[:legitimate_user_email])
The flaw here is that I this caused me a really hidden error.
I thought assigning it to a user would use the ID since that is how the models for each of these is linked together, but instead it kept returning ID1 instead of throwing an error.
@thing.user_id = User.find_by_email(params[:legitimate_user_email]).id
WOW that was a simple flaw but it didn't show up because it threw no error.
I was almost defeated by 3 letters and I have never been so embarrassed.
New knowledge 2)
Redirect_to :back
the :back parameter is really cool. I was passing a param back to the controller to know where to redirect my users back to, which was causing me to use POST and GET params at the same time, when I could have used :back all along. Code is now prettified and users now cannot redirect themselves to nasty places using an obvious param in the url.
New knowledge 3)
rake db:drop db:create db:migrate db:seed db:test:prepare
I should have a macro for this or something. Saves me time and attention knowing I can chain rake tasks now. Minutes are saved every day.
New knowledge 4)
before_filter do |c|
c.send(:authorize, "admin")
end
Passing params to the before_filter method is really quite awesome and very helpful if you are writing your own permissions from scratch. I had no idea what I was going to do to get round this as there was no way I was going to explicitly name every method. I would miss my deadline by months even attempting it.
New knowledge 5)
require 'rubygems'
require 'factory_girl_rails'
Loading a gem for local use in a file is not only useful when you want to use a gem outside its intended scope, but apparently there are optimization benefits in loading the gem only when needed too! (according to someone on stack overflow, but I haven't tested it and he also said it was a maintenance nightmare!)
New knowledge 6)
Rails.root.join('folder','file_in_folder.rb')
The cross platform version of "%Rails_root%/folder/file_in_folder.rb"
Both allow you to rummage around anywhere inside of your own rails directory but the first works on operating systems that do not use '/' as a separator.
Altogether, I'd say this has been a massively successful week. I've been using I18n.translate aka t ("some.location.in.config.locale_name.yml") which is extremely cool, and I'm expanding my use of capybara and TDD.
Now I write it down, I am learning quite a lot in a short amount of time.
Edit:
New 7)
I didn't think it was from this week as it seems so long ago, but commit logs say otherwise.
<%= collection_select("group", "permission_id", @permission, "id", "name") %>
Selecting from a collection is fun, I'm not sure if it is badly documented or I was looking for all the wrong keywords.
New knowledge 1)
@thing.user_id = User.find_by_email(params[:legitimate_user_email])
The flaw here is that I this caused me a really hidden error.
I thought assigning it to a user would use the ID since that is how the models for each of these is linked together, but instead it kept returning ID1 instead of throwing an error.
@thing.user_id = User.find_by_email(params[:legitimate_user_email]).id
WOW that was a simple flaw but it didn't show up because it threw no error.
I was almost defeated by 3 letters and I have never been so embarrassed.
New knowledge 2)
Redirect_to :back
the :back parameter is really cool. I was passing a param back to the controller to know where to redirect my users back to, which was causing me to use POST and GET params at the same time, when I could have used :back all along. Code is now prettified and users now cannot redirect themselves to nasty places using an obvious param in the url.
New knowledge 3)
rake db:drop db:create db:migrate db:seed db:test:prepare
I should have a macro for this or something. Saves me time and attention knowing I can chain rake tasks now. Minutes are saved every day.
New knowledge 4)
before_filter do |c|
c.send(:authorize, "admin")
end
Passing params to the before_filter method is really quite awesome and very helpful if you are writing your own permissions from scratch. I had no idea what I was going to do to get round this as there was no way I was going to explicitly name every method. I would miss my deadline by months even attempting it.
New knowledge 5)
require 'rubygems'
require 'factory_girl_rails'
Loading a gem for local use in a file is not only useful when you want to use a gem outside its intended scope, but apparently there are optimization benefits in loading the gem only when needed too! (according to someone on stack overflow, but I haven't tested it and he also said it was a maintenance nightmare!)
New knowledge 6)
Rails.root.join('folder','file_in_folder.rb')
The cross platform version of "%Rails_root%/folder/file_in_folder.rb"
Both allow you to rummage around anywhere inside of your own rails directory but the first works on operating systems that do not use '/' as a separator.
Altogether, I'd say this has been a massively successful week. I've been using I18n.translate aka t ("some.location.in.config.locale_name.yml") which is extremely cool, and I'm expanding my use of capybara and TDD.
Now I write it down, I am learning quite a lot in a short amount of time.
Edit:
New 7)
I didn't think it was from this week as it seems so long ago, but commit logs say otherwise.
<%= collection_select("group", "permission_id", @permission, "id", "name") %>
Selecting from a collection is fun, I'm not sure if it is badly documented or I was looking for all the wrong keywords.
Subscribe to:
Posts (Atom)