INCLUDE_DATA
As a new but frequent user of the Moq mocking framework for .NET, I was disappointed to find Moq-Contrib to be out of date as I wanted the AutoMockContainer. Performing dependency injection by hand and updating my tests for every code change was a pain. I dug into some source, found a simple fix and it is the patch that follows.
Index: Source/Mvc/HttpContextMock.cs =================================================================== --- Source/Mvc/HttpContextMock.cs (revision 23) +++ Source/Mvc/HttpContextMock.cs (working copy) @@ -58,11 +58,11 @@ this.HttpServerUtility = new HttpServerUtilityMock(); this.HttpSessionState = new HttpSessionStateMock(); - this.ExpectGet(c => c.Application).Returns(this.HttpApplicationState.Object); - this.ExpectGet(c => c.Request).Returns(this.HttpRequest.Object); - this.ExpectGet(c => c.Response).Returns(this.HttpResponse.Object); - this.ExpectGet(c => c.Server).Returns(this.HttpServerUtility.Object); - this.ExpectGet(c => c.Session).Returns(this.HttpSessionState.Object); + this.SetupGet(c => c.Application).Returns(this.HttpApplicationState.Object); + this.SetupGet(c => c.Request).Returns(this.HttpRequest.Object); + this.SetupGet(c => c.Response).Returns(this.HttpResponse.Object); + this.SetupGet(c => c.Server).Returns(this.HttpServerUtility.Object); + this.SetupGet(c => c.Session).Returns(this.HttpSessionState.Object); } /// <summary> Index: Source/Mvc/HttpRequestMock.cs =================================================================== --- Source/Mvc/HttpRequestMock.cs (revision 23) +++ Source/Mvc/HttpRequestMock.cs (working copy) @@ -56,8 +56,8 @@ /// </summary> public HttpRequestMock() { - this.ExpectGet(f => f.Form).Returns(form); - this.ExpectGet(f => f.Headers).Returns(headers); + this.SetupGet(f => f.Form).Returns(form); + this.SetupGet(f => f.Headers).Returns(headers); } } Index: Source/Mvc/HttpResponseMock.cs =================================================================== --- Source/Mvc/HttpResponseMock.cs (revision 23) +++ Source/Mvc/HttpResponseMock.cs (working copy) @@ -57,9 +57,9 @@ this.OutputStream = new Mock<Stream>(); this.Cache = new HttpCachePolicyBaseMock(); - ExpectGet(m => m.Output).Returns(this.Output.Object); - ExpectGet(m => m.OutputStream).Returns(this.OutputStream.Object); - ExpectGet(m => m.Cache).Returns(this.Cache.Object); + SetupGet(m => m.Output).Returns(this.Output.Object); + SetupGet(m => m.OutputStream).Returns(this.OutputStream.Object); + SetupGet(m => m.Cache).Returns(this.Cache.Object); } // TODO: mock other properties.
Ensure that the Moq 4.0 dll is in the Lib/Moq folder before building.
yield is an overlooked, yet powerful feature.
yield places values into an IEnumerable object. To further understand what yield does, here’s an example with trace statements between each yield statement:
//:SimpleYield.cs using System; using System.Collections.Generic; class SimpleYield { static IEnumerable GetValues(){ Console.WriteLine("Returning 1"); yield return 1; Console.WriteLine("Returning 2"); yield return 2; Console.WriteLine("Returning 3"); yield return 3; } static void Main(){ //Iterate over YieldMethod's IEnumerable foreach(int i in GetValues()) Console.WriteLine(i); } }/*Output: Returning 1 1 Returning 2 2 Returning 3 3 *///:~
GetValues( )’s yield statements return hard-coded integer values. Main( ) iterates these values, printing each. Notice how GetValue( )’s trace statements interlace with Main( )’s. A yield statement comes in two different forms, yield return and yield break. yield return places the evaluated expression as the current value of the IEnumerable. yield break marks the end of an iterator:
//:YieldBreak.cs using System; using System.Collections.Generic; class YieldBreak{ static IEnumerable GetValues(){ Console.WriteLine("Returning 1"); yield return 1; Console.WriteLine("Returning 2"); yield return 2; Console.WriteLine("Breaking"); yield break; //Break Here Console.WriteLine("Returning 3"); yield return 3; } static void Main(){ foreach(int i in GetValues()) Console.WriteLine(i); } }/*Output: Returning 1 1 Returning 2 2 Breaking *///:~
yield break prevents remaining code from executing. It reports back to the foreach that there are no values remaining in the IEnumerable. C#’s compiler reports a warning about any unreachable code following yield break. Exercise 1: Use Visual Studio’s debugger to step through (F11) SimpleYield.cs. Follow the code path as the foreach executes. Exercise 2: Create a GetValue( ) method that returns a random number of integer values. Use yield return and yield break.
///: Exercise2.cs using System; using System.Collections.Generic; class Exercise2{ public static IEnumerable GetValues(){ Random rand = new Random(); int current = 0; while (true){ current = rand.Next(20); if (current == 17) yield break; yield return current; } } public static void Main(){ foreach (int i in GetValues()){ Console.WriteLine(i); } } } ///:~
One strong feature of yield is its ability to defer processing. It delays any calculation until absolutely necessary. Deferred processing makes more responsive programs. yield spreads wait time amongst all iterations by creating values only when necessary:
///: DeferredProcessingTime.cs using System; using System.Collections.Generic; using System.Threading; class DeferredProcessingTime{ public static IEnumerable CalculateAtOnce(){ int[] intArray = new int[10]; for (int i = 0; i &amp;lt; 10; i++){ Thread.Sleep(1000); intArray[i] = i; } return intArray; } public static IEnumerable DeferredCalculate(){ for (int i = 0; i &amp;lt; 10; i++){ Thread.Sleep(1000); yield return i; } } public static void Main(){ Console.WriteLine("Calculate at once"); foreach (int i in CalculateAtOnce()) //Ten seconds before printing Console.Write(i); Console.WriteLine("\nUsing Yield"); foreach (int z in DeferredCalculate()) Console.Write(z); //One second between each write } }/*Output: Calculate at once 0123456789 Using Yield 0123456789 *///:~
The above example emulates an algorithm that takes a long time to process by using Thread.Sleep( ) before adding each value. Both foreachs over CalculateAtOnce( ) and DefferedCalculate( ) print the same results to the console. However the execution behavior is noticeably different. CalculateAtOnce( )’s foreach waits for 10 seconds and prints 0 through 9. DeferredCalculate( )’s foreach prints each value per second. Another benefit of yield’s deferred processing is that it does not require a collection stored in memory. yield can iterate over a large set of data without consuming large amounts of memory. Take the following example. You iterate over a set of data with 10 million integer values. Without yield, the entire collection of values must be returned. With yield, each integer value is returned when requested.
///:DeferredProcessingMemory.cs using System; using System.Collections.Generic; using System.Threading; class DeferredProcessingMemory{ public static IEnumerable CalculateAtOnce(){ int[] intArray = new int[10000000]; for (int i = 0; i &amp;lt; 10000000; i++) intArray[i] = i; return intArray; } public static IEnumerable DeferredCalculate(){ for (int i = 0; i &amp;lt; 10000000; i++) yield return i; } public static void Main(){ Console.WriteLine("Using Yield"); IEnumerable deferred = DeferredCalculate(); Console.ReadLine(); //Memory usage: ~2MB Console.WriteLine("Calculating at once"); IEnumerable atOnce = CalculateAtOnce(); Console.ReadLine(); //Memory usage: ~40MB } }/*Output: Using Yield Calculating at once *///:~
Start the Windows Task Manager (Ctrl+Shift+Esc) before running this example. Find your process, and notice the amount of memory usage from using DeferredCalculate( ). Press enter and see the drastic increase that CalculateAtOnce( ) makes; intArray’s 10 million in-memory values are the cause. yield gives potential to handle data sets of any size without concern for memory limitations. Exercise 3: Use yield to iterate over an infinite data set of random integers.
///:Exercise3.cs using System; using System.Collections.Generic; class Exercise3{ public static Random rand = new Random(); public static IEnumerable GetValues(){ while(true) yield return rand.Next(); } public static void Main(){ foreach(int i in GetValues()) Console.WriteLine(i); } } ///:~
Many C# keywords involve the generation of MSIL code, methods, or even classes. yield is no exception. Red Gate’s .NET Reflector shows the generated C# from using the yield statement. The disassembled assembly of SimpleYield.cs contains an extra class implementing IEnumerable.
public class GeneratedClass : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable{ //...CUT... public bool MoveNext(){ switch (this.state){ case 0: this.state = -1; Console.WriteLine("Returning 1"); this.current = 1; this.state = 1; return true; case 1: this.state = -1; Console.WriteLine("Returning 2"); this.current = 2; this.state = 2; return true; case 2: this.state = -1; Console.WriteLine("Returning 3"); this.current = 3; this.state = 3; return true; case 3: this.state = -1; break; } return false; } //...CUT... }
The compiler generates a switch statement to handle executing the code written in your original yielding method. Only one case statement is used for each time MoveNext( ) is called. This is how the deferred processing actually occurs. GetValues( ) is also changed to use the GeneratedClass( ) in place of the original code.
private static IEnumerable GetValues(){ return new GeneratedClass(-2); }
The -2 in the new GeneratedClass( ) call is used to set the initial state. The state’s value is changed when MoveNext( ) is called. Beginning each case, state is set to -1 to prevent further execution if an exception occurs. Just before a case returns, state is assigned the value of the next case. Exercise 4: Write an implementation of yield’s generated code and execute a foreach over it.
//:Exercise4.cs using System; using System.Collections.Generic; using System.Collections; class Exercise4 : IEnumerable,IEnumerable, IEnumerator,IEnumerator, IDisposable{ string current = ""; int state; public IEnumerator GetEnumerator(){ return this; } IEnumerator IEnumerable.GetEnumerator(){ return GetEnumerator(); } public string Current{ get { return current; } } public void Dispose(){} object IEnumerator.Current{ get { return Current; } } public bool MoveNext(){ switch(state){ case 0: state = -1; current = "One"; state = 1; return true; case 1: state = -1; current = "Two"; state = 2; return true; case 2: state = -3; current = "Three"; state = 3; return true; } return false; } public void Reset(){ throw new NotImplementedException(); } public static void Main(){ foreach(string s in new Exercise4()) Console.WriteLine(s); } }/*Output: One Two Three *///:~
Face it, C# is not as regex-friendly as it could be. To do things like find a single regex match involves several lines or some nasty inline code. Using Extension methods, this can be simplified. In another addition to StatenUtil focused on regex, C# becomes a more coder-friendly language.
using System; using System.Collections.Generic; using System.Text.RegularExpressions; namespace StatenUtil.RegexExtensions { public static class StringRegex { public static string RegexReplace(this string source, string regex, string replacement) { Regex r = new Regex(regex); return r.Replace(source, replacement); } public static string Match(this string source, string regex) { Regex r = new Regex(regex); Match m = r.Match(source); return m.Value; } public static string[] Matches(this string source, string regex) { Regex r = new Regex(regex); MatchCollection mc = r.Matches(source); List<string> matches = new List<string>(); foreach(object o in mc) matches.Add(((Match)o).Value); return matches.ToArray(); } public static string RegexRemove(this string source, string regex) { Regex r = new Regex(regex); return r.Replace(source, ""); } } }
This class offers four extension methods to the string class: Replace, Remove, Match first, and Match all. Aside from RegexReplace, the parameters often call for a single regular expression string.
Another addition that C# could use is a string scanner. A string scanner moves through a string one regex at a time matching the beginning of a string. This is useful for parsing languages in the way similar to JSON Parsing in Ruby.
using System; namespace StatenUtil.RegexExtensions { public class StringScanner { public string Remaining { get; set; } public string Match { get; set; } public StringScanner(string input) { Remaining = input; } public string Scan(string regex) { Match = Remaining.Match("^"+regex); if (Match != null) Remaining = Remaining.Substring(Match.Length); return Match; } } }
The StringScanner class constructor takes an input string that it will scan. Having only a Scan method, the class has the single use of moving through the input string as regex matches are made. As Scan finds a match, it returns the matching string. Also, the class has two properties: Remaining and Match. Remaining provides what is left in the string, useful for checking if the end of the input string has been met. Match provides the most recent match of the Scan method.
Yesterday, I spent awhile working on a RubyQuiz Challenge involving the parsing of JSON. Although I did create it with minimal viewing of the solution, I cannot take credit for the code or the idea. I did notice that on the site there was no actual merging of their snippets, so I felt inclined to share.
require "strscan" class JSONParser AST = Struct.new(:value) def parse(input) @input = StringScanner.new(input) parse_value.value ensure @input.eos? or error("Unexpected data") end private def parse_value trim_space parse_object or parse_array or parse_string or parse_number or parse_keyword or error("Invalid Data") ensure trim_space end #Parses colon separated object hashes def parse_object if @input.scan(/\s*\{/) obj = Hash.new more_parts = false while key = parse_string @input.scan(/\s*:\s*/) or error("Expected : separator") obj[key.value] = parse_value.value more_parts = @input.scan(/\s*,\s*/) or break end error("Missing object pair") if more_parts @input.scan(/\s*}/) or error("Unclosed object") AST.new(obj) else false end end def parse_array if @input.scan(/\s*\[/) #Arrays start with [ a = Array.new more_items = false while current = parse_value a << current.value more_items = @input.scan(/\s*,\s*/) or break end error("Missing value") if more_items @input.scan(/s*\]/) or error("Unclosed array") AST.new(a) end end #Parses string objects def parse_string if @input.scan(/"/) s = String.new while current = parse_string_content || parse_string_escape s << current.value end @input.scan(/"/) or error('Unclosed String') AST.new(s) else false end end def parse_string_content @input.scan(/[^\\"]+/) and AST.new(@input.matched) end def parse_string_escape if @input.scan(%r{\\["\\/]}) #slashes and quotations AST.new(@input.matched[-1]) elsif @input.scan(/\\[bfnrt]/) #newlines, tabs, etc AST.new(eval(%Q{"#{@input.matched}"})) elsif @input.scan(/\\u[0-9a-fA-F]{4}/) #Hex integers AST.new([Integer("0x#{@input.matched[2..-1]}")].pack("U")) else false end end def parse_number @input.scan(/-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?\b/) and AST.new(eval(@input.matched)) end def parse_keyword @input.scan(/\b(?:true|false|null)\b/) and AST.new(eval(@input.matched.sub("null","nil"))) end def trim_space @input.scan(/\s+/) end def error(message) raise "#{message}: #{@input.peek(@input.string.length)}" end end
For an in depth explanation of the individual portions in this code, refer to the RubyQuiz Site . One way that I’ve tested this code is by accessing the Twitter search api. The following snippet will print the 20 most recent #neumont tweets:
require 'jsonParser' require 'cgi' require 'open-uri' url = "http://search.twitter.com/search.json?q=%23neumont" parser = JSONParser.new open(url) {|html| @output = html.read} obj = parser.parse(@output) obj["results"].each {|e| puts CGI.unescapeHTML(e["text"])}
For anyone who’s new to the blog, StatenUtil is a personal C# utility library. Consisting mainly of extension methods, its main objective is to simplify frequently used operations. This edition includes adding some Ruby-like looping methods into C#. I understand that Func and Action objects aren’t a real replacement for blocks. However, it’s nice to have some features I miss when not using Ruby.
using System; namespace StatenUtil { public static class Int32Extensions { public static void Times(this int source, Action<int> action) { for (int i = 0; i < source; i++) { action(i); } } public static void UpTo(this int source, int max, Action<int> action) { for (int i = source; i <= max; i++) { action(i); } } public static void DownTo(this int source, int min, Action<int> action) { for (int i = source; i >= min; i--) { action(i); } } public static int[] Range(this int source, int max) { int difference = max - source; if (difference < 0) return new int[0]; int[] ret = new int[difference + 1]; for (int i = 0; i <= difference; i++) ret[i] = source+i; return ret; } } }
This class file revolves around adding functions to the int class. The Times method allows for a specific integer capturing lambda expression to be executed source times. For example, 6.Times(x => Console.WriteLine(x)) would print lines from zero to 6.
UpTo and DownTo are similar to the Times method. However, they loop over a range of integers rather than from zero. Compare these to Ruby’s upto and downto methods.
Range is simply a way to create an array covering a range of integers. The source is the minimum value and max is the largest of the array.
using System; using System.Collections.Generic; namespace StatenUtil { public static class IEnumerableExtensions { public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) { IEnumerator<T> enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) action(enumerator.Current); } } }
Currently, this class file add inline ForEach capabilities to any generic IEnumerable object, similar to Ruby’s each. Although List has this capability, other IEnumerables like arrays do not.
That’s all for now. However, StatenUtil is a work in progress that’s always being amended. In each significant addition, the details will be shared once again.
Recently, I recieved a comment on one of my previous posts, Creating a Socket Server and Client in Ruby, that asked about the next step towards taking the simple example to make a working web server. Well, you’ve been heard and I have written up code to do just that. It handles retrieval and sending of headers, handling GET requests, and responding with status.
class RequestInfo attr_accessor :headers, :method, :resource def initialize @headers = {} end end class ResponseInfo attr_accessor :status, :headers, :body def initialize @headers = {} @body = String.new end end
These classes are short and are designed simply to contain the information coming in and going out of the webserver. RequestInfo’s method is used to obtain the method of the request (GET, etc..). Resource is the requested file from the connecting client. Finally, headers is a map of key value pairs corresponding with headers.
ResponseInfo consists of status, which is the first line returned containing 200 OK or 404 Not Found; body, the content of what’s actually responded with; and headers, the map of headers of the response.
request = RequestInfo.new response = ResponseInfo.new while((current = s.readline).chomp! != "") if current[0,3] == "GET" methodline = current.split request.method = methodline[0] request.resource = methodline[1] elsif current.match ':' headerline = current.split ':',2 request.headers[headerline[0]] = headerline[1] end end
This segment handles populating the RequestInfo object, by going through the sent request line by line from the TCPSocket connection s. It retrieves method, resources, and headers in a single while loop. The headers are retrieved by splitting on the first colon in each line that contains one.
begin File.open("public/#{request.resource}","r") do |file| while(curline = file.gets) response.body << curline end end response.status = "HTTP/1.0 200 OK" response.headers["Content-Type"] = "text/html" response.headers["Content-Length"] = response.body.length.to_s rescue => err puts err response.status = "HTTP/1.0 404 Not Found" response.headers["Content-Type"] = "text/html" response.headers["Content-Length"] = "0" response.body = "" end
Within this segment, we read in a file (looking in a folder called public so the webserver.rb itself cannot be retrieved through a request), appending its contents to the response.body. Afterwards, if all is successful, we respond with a 200 OK along with some other headers like Content-Type and Content-Length. Typically, if there’s an issue it’s because the file cannot be found, so returning a 404 is appropriate.
Note: A suggestion for improving this example is reading the MIME type of the read file so the Content-Type is not hardcoded.
s.write response.status + "\n" response.headers.each {|key,value| s.write "#{key}:#{value}\n"} s.write "\n" + response.body s.close
This writes to the socket connection s, in order, ResponseInfo’s status, headers, and body. Finally, the connection is closed.
class RequestInfo attr_accessor :headers, :method, :resource def initialize @headers = {} end end class ResponseInfo attr_accessor :status, :headers, :body def initialize @headers = {} @body = String.new end end require "socket" serv = TCPServer.new('jstaten.com',7881) loop do Thread.start(serv.accept) do |s| request = RequestInfo.new response = ResponseInfo.new while((current = s.readline).chomp! != "") if current[0,3] == "GET" methodline = current.split request.method = methodline[0] request.resource = methodline[1] elsif current.match ':' headerline = current.split ':',2 request.headers[headerline[0]] = headerline[1] end end if (request.resource == "/") request.resource = "index.html" end begin File.open("public/#{request.resource}","r") do |file| while(curline = file.gets) response.body << curline end end response.status = "HTTP/1.0 200 OK" response.headers["Content-Type"] = "text/html" response.headers["Content-Length"] = response.body.length.to_s rescue => err puts err response.status = "HTTP/1.0 404 Not Found" response.headers["Content-Type"] = "text/html" response.headers["Content-Length"] = "0" response.body = "" end s.write response.status + "\n" response.headers.each {|key,value| s.write "#{key}:#{value}\n"} s.write "\n" + response.body s.close end end end
When the steps are all implemented, you have a working ruby web server. Surely there are improvements to be made upon this creation, but it’s an effective proof-of-concept that can be built off.
I appreciate the feedback from all visitors to my blog, and if you feel that you have any questions or suggestions, feel free to comment away.
Note: Made a few corrections suggested. Thanks!
Remember the Java JAX-WS Web Service discussed what seems like long ago? Currently there is an have an instance of it running on this hosting server (got to love SSH). Experimenting with Ruby has led me to find the simplicity of creating a web service client. The duck typing of the language allows you to not need to generate a bunch of classes to pull in a WSDL (although it is possible using wsdl2r).
require 'soap/wsdlDriver' URL = 'http://jstaten.com:7070/MathExample/MathService?wsdl' begin driver = SOAP::WSDLDriverFactory.new(URL).create_rpc_driver p driver.addInts({:arg0 =>2, :arg1 => 4}).return rescue => err p err.message end
Steping through this code, you’re simply requiring the soap.wsdlDriver library and setting the URL of the WSDL to be read in. The begin statement is for error handling incase something goes wrong. Inside that, you create a new rpc driver using the WSDLDriverFactory. The “driver” within this code is the instance which contains methods pointing to the web service’s exposed operations. After creating the driver, we call a method on it. Because it requires two parameters (the two integers to be added), we pass it a map. The return field from running that method contains the value of the response. Finally, we rescue by printing the error message. If you’d like to test this against the web service in the code, feel free. Just please don’t abuse it.
Working through endless “Wrestles” in CS290, I’ve come to find some common needs for many of my assignments. Because of this, I’ve started to create my own utility DLL (dynamic link library) of functions. I’ll be honest that not all of the ideas were my own, especially Jamie King’s P() method.
For those who have not heard of or used extension methods, here’s a brief overview. Extension methods are simply static methods that are syntactic sugar. To create an extension method, create a static class and within it create a static method having this before your first argument.
public static class MyStaticClass { public static void MyExtensionMethod(this Object source) { } }
After creating this, you can then use it by calling it on any instance that inherits from Object (anything) as instanceName.MyExtensionMethod(). It’s the same as calling, MyStaticClass.MyExtensionMethod(instanceName), just shorter to type and implicitly inserting the parameter, making it feel like a method of the object, rather than a static extension.
Assertion is an effective way of debugging your code. When “wrestling” with new concepts, its a great way to prove things without spewing out a bunch of console.writeline(). These extension methods give you simple Assert methods to call on any object.
using System; using System.Diagnostics; namespace StatenUtil { public static class Asserter { public static void AssertReferenceEquals(this Object source, Object target) { Debug.Assert(Debug.ReferenceEquals(source, target), "Source and target references not equal"); } public static void AssertEquals(this Object source, Object target) { if (source == null) { Debug.Assert(target == null, "Source is null, target is not"); } else { Debug.Assert(source.Equals(target), "Objects are not equal"); } } public static void AssertNull(this Object source) { Debug.Assert(source == null, "Object is not null"); } } }
Another frequet debugging technique is to print out to the console. Adding the P() extension method can simplify the need to write Console.Writeline(). Also, added is the iteration of enumerable objects to eliminate the need to foreach over its members.
using System; using System.Collections; namespace StatenUtil { public static class PrintExtensions { public static void P(this Object source) { P(source, "{0}"); } public static void P(this Object source, string formatString) { if (!(source is String) && source is IEnumerable) { Console.WriteLine(formatString, source); foreach (object o in (IEnumerable)source) o.P(" " + formatString); return; } Console.WriteLine(formatString, source); } } }
In the future, I’ll continue to add additional features to this utility set and share them as the changes become significant. Check back often, as StatenUtil has plenty of life ahead of it. If you have comments or suggestions, please let me know.
I came across a rather interesting discovery today that email is quite simple to send within Ruby. Check it out:
require 'net/smtp' message = 'Hello Dude' Net::SMTP.start('127.0.0.1',25) do |smtp| smtp.send_message(message, 'from@from.com','to@to.com') end
Granted, this is a very simple example, but the principles are still there. Write a message as a string, start a new SMTP connection, tell it where it’s from and going, and send it on its way.
The problem with this method is that you wind up with some very ugly(nonexistent) headers that spam catchers may not like. One way around this is to include them in the message as follows:
require 'net/smtp' message = <<MESSAGE_END From: test@hello.com To: to@to.com Subject: Sample Message Hello, this is a message MESSAGE_END p message Net::SMTP.start('10.245.27.10',25,'localhost') do |smtp| smtp.send_message(message, 'test@hello.com','to@to.com') end
This gives you greater control over the headers. However, I still found this to be a bother for the simple sake of having to type the to field multiple times. That’s the sort of thing that can lead to errors in code (it actually messed me up for a a minute while writing this). So my last bit moves the message into class form, allowing us to keep our sending portion short, clean, and less error prone. This involves two files, emailMessage.rb and email.rb. They are shown below:
emailMessage.rb
class EmailMessage attr_accessor :to attr_accessor :from attr_accessor :message attr_accessor :subject def initialize(attributes) @to = attributes[:to] @from = attributes[:from] @message = attributes[:message] @subject = attributes[:subject] end def to_s <<MESSAGE_END From: #{@from} To: #{@to} Subject: #{@subject} #{@message} MESSAGE_END end end
email.rb
require 'net/smtp' require 'emailMessage' em = EmailMessage.new :to=>;'to@to.com', :from=>;'test@test.com', :subject=>;'mysubject' em.message = 'This is the message' Net::SMTP.start('127.0.0.1',25) do |smtp| smtp.send_message(em.to_s, em.from,em.to) end
We’re back to a short, clean, email.rb that can be used for sending email with most SMTP.
Some SMTP hosts, including Gmail, requires the usage of SSL to send emails. This is not built into the standard Ruby libraries. However, Stephen Chu has a great post covering how to do it in Ruby.
Back with more Ruby, I bring you some database connectivity because that’s always an important thing to know about a language.
This tutorial requires that you have the mysql and dbi gems installed. If you have RubyGems installed, it should be as simple as
#gem install mysql #gem install dbi
However, if you’re having difficulty, surely Google understands.
Also, this requires a MySql database running on your local machine with a database containing a customer table as follows
CREATE TABLE `customer` ( `id` int(11) NOT NULL auto_increment, `name` varchar(30) NOT NULL, `telephone` char(10) default NULL, PRIMARY KEY (`id`), UNIQUE KEY `telephone` (`telephone`) ) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
require 'rubygems' gem 'dbi' require 'dbi' begin con = DBI.connect("DBI:Mysql:DATABASE_NAME:localhost","USER","PASSWORD") result = con.execute "SELECT * FROM customer" result.fetch_hash do |row| printf "ID:%d NAME:%s PHONE:%s\n", row["id"], row["name"], row["telephone"] end result.finish rescue DBI::DatabaseError => e puts "Error, #{e.err}, #{e.errstr}" ensure con.disconnect if con end
Breaking this down into some blocks, the program starts by requiring rubygems and dbi (gem ‘dbi’ allows the dbi libraries to be accessed). DBI is ruby’s interface to use several different databases. In this case we’ll be using MySQL.
The real work begins when we use DBI.connect to create a connection to a database. This connection is what we’ll use to send queries to the database. Be sure to replace DATABASE_NAME, USER, and PASSWORD with the appropriate information for your own database.
Next up, con.execute will return a result set that can be iterated over using fetch_hash. In this case we’ll simply print each result to the console. Notice that rows are hashes that allow you to access information based on column name. Finally, result.finish means we’re done using the result set given to us.
The rescue section simply makes sure to notify of an error if something goes wrong. Also, ensure does just what it says, ensures that the connection is closed if it exists.
Surely the output right now is rather boring because you don’t have any data in your table. Lets put some in, and lets do it with a prepared statement. That way when you build a Ruby app with user input, you’re less susceptible to SQL injection.
cmd = con.prepare "INSERT INTO customer(name,telephone) VALUES(?,?)" cmd.execute "Bobby","2229998888"
Remember working with result.fetch_hash? What about if you want the entire dataset? What about just the first row? You’re in luck, Ruby makes it easy.
#returns an array of DBI::Row objects result.select_all "SELECT * FROM customer" #returns the first row result.select_one "SELECT * FROM customer"
Database access with Ruby is an important skill to know if you’re dealing with storing any sort of information. With this brief overview, grasping the idea should be straight forward.