First of all we have to have a working JRuby built from the latest version of trunk. After JRuby is working we need to install a few gems. Follow these commands and you'll be good:
jruby %JRUBY_HOME%\bin\gem install camping --no-ri --no-rdoc --include-dependenciesThis installs Camping, ActiveRecord, ActiveSupport, Markaby, Builder, Metaid and ActiveRecord-JDBC. We don't generate RDoc or RI for these gems, since that's one part of JRuby that still is pretty slow.
jruby %JRUBY_HOME%\bin\gem install ActiveRecord-JDBC --no-ri --no-rdoc
The Blog application
The first thing the blog application needs is a database. I will use MySQL, but other databases may work through the JDBC-adapter, but there is still some work to be done in this area. I will have my MySQL server on localhost, so change the configuration if you do not have this setup. You'll need a database for the blog application. I've been conservative and named the database "blog" and the user "blog" with the password "blog". Easy to remember, but not so good for production.
Update: As azzoti mentioned, you have to set your classpath to include the MySQL JDBC-driver, which can be downloaded from http://www.mysql.org/.
Now, open up a new Ruby file and call it blog.rb. The name of the file is important; it has to have the same name as the Camping application. Now, first of all we include the dependencies:
require 'rubygems'These statements include Rubygems, Camping, Camping session support, ActiveRecord-JDBC and Java support. It also includes the Java class named java.lang.System for later use. The next step is to include some configuration for our application.
require 'camping'
require 'camping/session'
require_gem 'ActiveRecord-JDBC'
require 'active_record/connection_adapters/jdbc_adapter'
require 'java'
include_class 'java.lang.System'
These statements first names our application with the Camping.goes-statement. This includes some fairly heavy magic, including reopening the file and rewriting the source to include more references to the Camping framework. But this line is all that is needed. The next line establishes our connection to the database, and it follows standard JDBC naming of the parameters. Of course, these should be in a YAML file somewhere, but for now we make it easy. The last part makes sure we have Session support in our Blog application.Camping.goes :Blog
Blog::Models::Base.establish_connection :adapter => 'jdbc', :driver => 'com.mysql.jdbc.Driver',
:url => 'jdbc:mysql://localhost:3306/blog', :username => 'blog', :password => 'blog'
module Blog
include Camping::Session
end
Now we need to define our model, and this is easily done since Camping uses ActiveRecord:
The first part of this code defines a helper method that either sets the schema to the block given, or returns an earlier defined schema. The second part defines our model, which includes Post, Comment and User, and their relationships.module Blog::Models
def self.schema(&block)
@@schema = block if block_given?
@@schema
end
class Post < Base; belongs_to :user; end
class Comment < Base; belongs_to :user; end
class User < Base; end
end
The schema is also part of the application, and we'll later see that Camping can automatically create it if it doesn't exist (that's why we didn't need to create any tables ourselves, just the database).
This defines the three tables needed by our blog system. Note that the names of the tables include the name of the application as a prefix. This is because Camping expects more than one application to be deployed in the same container, using the same database.Blog::Models.schema do
create_table :blog_posts, :force => true do |t|
t.column :id, :integer, :null => false
t.column :user_id, :integer, :null => false
t.column :title, :string, :limit => 255
t.column :body, :text
end
create_table :blog_users, :force => true do |t|
t.column :id, :integer, :null => false
t.column :username, :string
t.column :password, :string
end
create_table :blog_comments, :force => true do |t|
t.column :id, :integer, :null => false
t.column :post_id, :integer, :null => false
t.column :username, :string
t.column :body, :text
end
end
When we have defined the schema, it's time to define our controller actions. In Camping, each action is a class, and each action class define a method for get, one for post, etc. These classes will be defined inside the module Blog::Controllers. The first action we create will be the Index action. It looks like this:
This defines a class that inherits from an anonymous class defined by the R method. What it really does, is bind the Index action to the /-path. It uses ActiveRecord to get all posts and then renders the view with the name index.class Index < R '/'
def get
@posts = Post.find :all
render :index
end
end
The Add-action adds a new Post, but only if there is a user in the @state-variable, which acts as a session. If something is posted to it, it creates a new Post from the information and redirects to the View-action:
class AddAs you can see, there's not much to it. Instance variables in the controller will be available to the view later on. Note that this action doesn't inherit from any class at all. This means it will only be available by an URL with it's name in it.
def get
unless @state.user_id.blank?
@user = User.find @state.user_id
@post = Post.new
end
render :add
end
def post
post = Post.create :title => input.post_title, :body => input.post_body,
:user_id => @state.user_id
redirect View, post
end
end
We need a few more controllers. View and Edit are for handling Posts. Comment adds new comments to an existing Post. Login and Logout are pretty self explanatory. And Style returns a stylesheet for all pages. Note that Style doesn't render anything, it just sets @body to a string with the contents to return.
Also note how easy it is to define routing rules with the help of regular expressions to the R method.class View < R '/view/(\d+)'
def get post_id
@post = Post.find post_id
@comments = Models::Comment.find :all, :conditions => ['post_id = ?', post_id]
render :view
end
end
class Edit < R '/edit/(\d+)', '/edit'
def get post_id
unless @state.user_id.blank?
@user = User.find @state.user_id
end
@post = Post.find post_id
render :edit
end
def post
@post = Post.find input.post_id
@post.update_attributes :title => input.post_title, :body => input.post_body
redirect View, @post
end
end
class Comment
def post
Models::Comment.create(:username => input.post_username,
:body => input.post_body, :post_id => input.post_id)
redirect View, input.post_id
end
end
class Login
def post
@user = User.find :first, :conditions => ['username = ? AND password = ?', input.username, input.password]
if @user
@login = 'login success !'
@state.user_id = @user.id
else
@login = 'wrong user name or password'
end
render :login
end
end
class Logout
def get
@state.user_id = nil
render :logout
end
end
class Style < R '/styles.css'
def get
@headers["Content-Type"] = "text/css; charset=utf-8"
@body = %{
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
body {
font-family: Utopia, Georga, serif;
}
h1.header {
background-color: #fef;
margin: 0; padding: 10px;
}
div.content {
padding: 10px;
}
div.post {
background-color: #ffa;
border: 1px solid black;
padding: 20px;
margin: 10px;
}
}
end
end
Next up, we have to create our views. Since Camping uses Markaby, we do it in Ruby, in the same file. Views are methods in the module Blog::Views with the same name as referenced inside the controllers call to render. There is a special view called layout which get called for all views, if you don't specify otherwise in the call to render. It looks like this:
As you can see, standard HTML tags are defined by calling a method by that name. The contents of the tag is created inside the block sent to that method, and if it makes sense to give it content as an argument, this works too. Title, for example. If you give a block to it, it will evaluate this and add the result as the title, but in this case it's easier to just provide a string. Note how a link is created, by the method R (another method R this time, since this is in the Views module). Finally, the contents of the layout gets added by appending the result of a yield to self.def layout
html do
head do
title 'Blog'
link :rel => 'stylesheet', :type => 'text/css',
:href => '/styles.css', :media => 'screen'
end
body do
h1.header { a 'Blog', :href => R(Index) }
div.content do
self << yield
end
end
end
end
The index view is the first we'll see when visiting the application, and it looks like this:
I've also added a call that writes out the current time in milliseconds, from Java's System class, to show that we're actually in Java land now, and potentially could base much of our application on data from Java. We check if there are any posts, and if so iterate over them and write them out with a partial called _post. We also create a link to add more posts. The rest of the views look like this:def index
if @posts.empty?
p 'No posts found.'
else
for post in @posts
_post(post)
end
end
p { a 'Add', :href => R(Add) }
p "Current time in millis is #{System.currentTimeMillis}."
end
And the three partials:def login
p { b @login }
p { a 'Continue', :href => R(Add) }
end
def logout
p "You have been logged out."
p { a 'Continue', :href => R(Index) }
end
def add
if @user
_form(post, :action => R(Add))
else
_login
end
end
def edit
if @user
_form(post, :action => R(Edit))
else
_login
end
end
def view
_post(post)
p "Comment for this post:"
for c in @comments
h1 c.username
p c.body
end
form :action => R(Comment), :method => 'post' do
label 'Name', :for => 'post_username'; br
input :name => 'post_username', :type => 'text'; br
label 'Comment', :for => 'post_body'; br
textarea :name => 'post_body' do; end; br
input :type => 'hidden', :name => 'post_id', :value => post.id
input :type => 'submit'
end
end
In my opinion, this code is actually much easier to read than HTML and most of it is fairly straight forward. One interesting part is the add and edit methods, which checks if a user is logged in, otherwise uses the _login-partial instead of showing the real content.def _login
form :action => R(Login), :method => 'post' do
label 'Username', :for => 'username'; br
input :name => 'username', :type => 'text'; br
label 'Password', :for => 'password'; br
input :name => 'password', :type => 'text'; br
input :type => 'submit', :name => 'login', :value => 'Login'
end
end
def _post(post)
div.post do
h1 post.title
p post.body
p do
a "Edit", :href => R(Edit, post)
a "View", :href => R(View, post)
end
end
end
def _form(post, opts)
p do
text "You are logged in as #{@user.username} | "
a 'Logout', :href => R(Logout)
end
form({:method => 'post'}.merge(opts)) do
label 'Title', :for => 'post_title'; br
input :name => 'post_title', :type => 'text',
:value => post.title; br
label 'Body', :for => 'post_body'; br
textarea post.body, :name => 'post_body'; br
input :type => 'hidden', :name => 'post_id', :value => post.id
input :type => 'submit'
end
end
Finally, we will define a create-method for Camping, which is responsible for creating the tables for our model:
def Blog.create
Camping::Models::Session.create_schema
unless Blog::Models::Post.table_exists?
ActiveRecord::Schema.define(&Blog::Models.schema)
Blog::Models::User.create(:username => 'admin', :password => 'camping')
end
end
This first creates a table for the session information, and then checks if the Post-table exists; if not all the tables in the schema defined before is created.
Now you have seen the complete application. If you have no interest in writing this by hand, the complete code can be found here.
Running the application
To run a Camping application, you need to run the camping executable that has been installed into your %JRUBY_HOME%\bin on your application file. In my case I run it like this:
jruby %JRUBY_HOME%\bin\camping blog.rbin the directory where my blog.rb exists and I very soon have a nice application at http://localhost:3301/blog which works wonderfully. Startup is a little bit slow, but as soon as WEBrick has started listening the application is very snappy. You can try changing your blog.rb-file too; Camping will automatically update your application without having to restart the server. As I said above, I included a call to System.currentTimeMillis, to show that we are actually using Java in this blog-application. If that isn't apparent from the call to System, remember that we are actually using JDBC to talk to our database, and very soon you will be able to use the ActiveRecord-JDBC adapter to connect to any databases Java can talk too. That's a brigth future.
74 kommentarer:
Works a treat Ola! fantastic stuff.
If using MySql you'll need the MySql jdbc connector jar from http://dev.mysql.com/downloads/connector/j/3.1.html
unzip somewhere and setup on the classpath, for example for me on windows:
set CLASSPATH=C:\dev\mysql-connector-java-3.1.13\mysql-connector-java-3.1.13-bin.jar
I got a error running blog.rb
C:\jruby\bin>jruby .\camping blog.rb
c:/jruby/lib/ruby/site_ruby/1.8/rubygems/version.rb:144:in `max': stack level to
o deep (SystemStackError)
from c:/jruby/lib/ruby/site_ruby/1.8/rubygems/version.rb:144:in `<=>'
from c:/jruby/lib/ruby/site_ruby/1.8/rubygems/version.rb:184:in `>'
from c:/jruby/lib/ruby/site_ruby/1.8/rubygems/version.rb:184
from c:/jruby/lib/ruby/site_ruby/1.8/rubygems/specification.rb:10:in `ca
ll'
from c:/jruby/lib/ruby/site_ruby/1.8/rubygems/version.rb:281:in `satisfy
?'
from c:/jruby/lib/ruby/site_ruby/1.8/rubygems/version.rb:271:in `satisfi
ed_by?'
from c:/jruby/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:187:in `al
l?'
from c:/jruby/lib/ruby/site_ruby/1.8/rubygems/version.rb:272:in `each'
... 376 levels...
from c:/jruby/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_supp
ort/dependencies.rb:140:in `load'
from c:/jruby/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_supp
ort/dependencies.rb:140:in `load'
from .\camping:18
any idea?
Purpureleaf: I'm not totally sure what could cause that. Are you sure you've set your JRUBY_HOME? Try to execute the command from that directory instead, so you bin\jruby bin\camping blog.rb.
Of course you have to move the blog.rb-file too.
Good luck.
thanks, it works like a charm.
BTW, I think jruby can have a better way to manage classpath.
It is not a good idea to add all jars to system variable
You spilled coffee on my dry socks. ;(
WEBrick reports following error
!! trouble loading blog: [SyntaxError] blog.rb:0: Invalid char `\273' in expression
Best to copy and paste
http://opensource.ologix.com/blog.rb
Saving it imports invisible illegal characters.
Actually, it is my editor that seems to be the source.
http://redhanded.hobix.com/inspect/campingGetsAllJavayPlacingItAtTheVeryEpicenterOfHate.html
LOL
While using SVN rev. 2232 of JRuby, I get the following error:
$ jruby $JRUBY_HOME/bin/gem install camping --no-ri --no-rdoc --include-dependencies
Bulk updating Gem source index for: http://gems.rubyforge.org
ERROR: While executing gem ... (NoMethodError)
undefined method `rubygems_version' for 0.9.7:Gem::Version
Curiously, I can install Rails without problems using the same JRuby version. Can you tell us what revision of JRuby you used?
Ugo!
This is a general problem with JRuby (and MRI too, but not so often). It seems that sometimes the symbol tables get scrambled when working with lots of data. This used to happen on MacOS X in 1.8.1, and has been seen from and to in every version of JRuby fast enough to run RubyGems.
My solution when it happens is to just repeat the action. It usually works the next time around.
Good luck! I'm looking forward to your talk on RailsConfEU!
I tried it many times yesterday with no luck. Tried again once this morning and it worked.
Maybe I shouldn't have tried it when my MacBook was tired after a long day's work. ;)
I am getting the following error
C:\rnd\my-ruby-projects>jruby %JRUBY_HOME%\bin\camping blog.rb
Exception in thread "main" java.lang.Error: unexpected type class org.jruby.ast.
CallNode at c:/rnd/jruby-trunk/lib/ruby/gems/1.8/gems/camping-1.5/bin/camping:[3
6,36]:[1017,1020]
at org.jruby.internal.runtime.methods.EvaluateCallable.procArityOf(Evalu
ateCallable.java:95)
at org.jruby.internal.runtime.methods.EvaluateCallable. init (EvaluateCa
llable.java:57)
at org.jruby.ast.IterNode.getCallable(IterNode.java:106)
at org.jruby.evaluator.EvaluateVisitor$IterNodeVisitor.execute(EvaluateV
isitor.java:1327)
at org.jruby.evaluator.EvaluationState.executeNext(EvaluationState.java:
274)
at org.jruby.evaluator.EvaluationState.begin(EvaluationState.java:320)
at org.jruby.internal.runtime.methods.EvaluateCallable.internalCall(Eval
uateCallable.java:67)
at org.jruby.internal.runtime.methods.AbstractCallable.call(AbstractCall
able.java:64)
at org.jruby.runtime.ThreadContext.yieldInternal(ThreadContext.java:496)
at org.jruby.runtime.ThreadContext.yieldCurrentBlock(ThreadContext.java:
436)
at org.jruby.evaluator.EvaluateVisitor$Yield2.execute(EvaluateVisitor.ja
va:2077)
at org.jruby.evaluator.EvaluationState.executeNext(EvaluationState.java:
274)
at org.jruby.evaluator.EvaluationState.begin(EvaluationState.java:320)
at org.jruby.RubyObject.eval(RubyObject.java:445)
at org.jruby.internal.runtime.methods.DefaultMethod.internalCall(Default
Method.java:111)
at org.jruby.internal.runtime.methods.AbstractMethod.call(AbstractMethod
.java:58)
at org.jruby.RubyObject.callMethod(RubyObject.java:367)
at org.jruby.RubyObject.callMethod(RubyObject.java:311)
at org.jruby.RubyObject.callInit(RubyObject.java:456)
at org.jruby.RubyClass.newInstance(RubyClass.java:174)
at sun.reflect.GeneratedMethodAccessor34.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jruby.runtime.callback.ReflectionCallback.execute(ReflectionCallb
ack.java:140)
at org.jruby.internal.runtime.methods.CallbackMethod.internalCall(Callba
ckMethod.java:79)
at org.jruby.internal.runtime.methods.AbstractMethod.call(AbstractMethod
.java:58)
at org.jruby.RubyObject.callMethod(RubyObject.java:367)
at org.jruby.RubyObject.callMethod(RubyObject.java:319)
at org.jruby.evaluator.EvaluateVisitor$CallNodeVisitor.execute(EvaluateV
isitor.java:574)
at org.jruby.evaluator.EvaluationState.executeNext(EvaluationState.java:
274)
at org.jruby.evaluator.EvaluationState.begin(EvaluationState.java:320)
at org.jruby.evaluator.EvaluateVisitor$IterNodeVisitor.execute(EvaluateV
isitor.java:1332)
at org.jruby.evaluator.EvaluationState.executeNext(EvaluationState.java:
274)
at org.jruby.evaluator.EvaluationState.begin(EvaluationState.java:320)
at org.jruby.RubyObject.eval(RubyObject.java:445)
at org.jruby.Ruby.loadScript(Ruby.java:838)
at org.jruby.runtime.load.ExternalScript.load(ExternalScript.java:50)
at org.jruby.runtime.load.LoadService.load(LoadService.java:180)
at org.jruby.RubyKernel.load(RubyKernel.java:622)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jruby.runtime.callback.ReflectionCallback.execute(ReflectionCallb
ack.java:140)
at org.jruby.internal.runtime.methods.CallbackMethod.internalCall(Callba
ckMethod.java:79)
at org.jruby.internal.runtime.methods.AbstractMethod.call(AbstractMethod
.java:58)
at org.jruby.RubyObject.callMethod(RubyObject.java:367)
at org.jruby.RubyObject.callMethod(RubyObject.java:319)
at org.jruby.evaluator.EvaluateVisitor$FCallNodeVisitor.execute(Evaluate
Visitor.java:1077)
at org.jruby.evaluator.EvaluationState.executeNext(EvaluationState.java:
274)
at org.jruby.evaluator.EvaluationState.begin(EvaluationState.java:320)
at org.jruby.Ruby.eval(Ruby.java:210)
at org.jruby.Main.runInterpreter(Main.java:176)
at org.jruby.Main.runInterpreter(Main.java:145)
at org.jruby.Main.run(Main.java:111)
at org.jruby.Main.main(Main.java:86)
I still have the same above problem.Can somebody troubleshoot it?
Thx
I believe camping uses an unsupported syntax.
I changed
opts.on("-h", "--host HOSTNAME", "Host for web server to bind to (default is all IPs)") { |conf.host| }
opts.on("-p", "--port NUM", "Port for web server (defaults to #{conf.port})") { |conf.port| }
opts.on("-d", "--database FILE", "Database file (defaults to #{conf.db})") { |conf.db| }
opts.on("-l", "--log FILE", "Start a database log ('-' for STDOUT)") { |conf.log| }
to
opts.on("-h", "--host HOSTNAME", "Host for web server to bind to (default is all IPs)") { |h| conf.host= h }
opts.on("-p", "--port NUM", "Port for web server (defaults to #{conf.port})") { |p| conf.port = p }
opts.on("-d", "--database FILE", "Database file (defaults to #{conf.db})") { |d| conf.db = d }
opts.on("-l", "--log FILE", "Start a database log ('-' for STDOUT)") { |l| conf.log = l }
in camping.
Do I need to make coding changes to camping?
even
jruby .\camping foo.rb
gives the same error.
I did a svn update of Jruby and did install camping again as explained in the tutorial. It doesn't help.
I got the follwing error when I try to run
gem install camping --no-ri --no-rdoc --include-dependencies
ERROR: Error installing gem camping[.gem]: No metadata found!
I did the changes in the camping file. In blog.rb, I only put "require 'rubygems'", but I got the following error:
!! trouble loading blog: not a Camping app, no Blog module found
c:/fredWork/jruby/lib/ruby/gems/1.8/gems/camping-1.5/bin/camping:91:in `method_m
issing': undefined method `abort' for main:Object (NoMethodError)
from c:/fredWork/jruby/lib/ruby/gems/1.8/gems/camping-1.5/bin/camping:91
from ..\bin\camping:18:in `load'
from ..\bin\camping:18
Any idea of how to fix the problem?
require 'rubygems'
require 'camping'
require 'camping/session'
gives:
C:\fredWork\jruby\blog>jruby %JRUBY_HOME%\bin\camping blog.rb
!! trouble loading blog: [TypeError] undefined superclass 'Base'
c:/fredWork/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27
c:/fredWork/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27
c:/fredWork/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `requi
re'
c:/fredWork/jruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `requi
re'
C:/fredWork/jruby/blog/blog.rb:3
c:/fredWork/jruby/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_support/
dependencies.rb:140:in `load'
c:/fredWork/jruby/lib/ruby/gems/1.8/gems/activesupport-1.3.1/lib/active_support/
dependencies.rb:140:in `load'
c:/fredWork/jruby/lib/ruby/gems/1.8/gems/camping-1.5/lib/camping/reloader.rb:61:
in `load_app'
c:/fredWork/jruby/lib/ruby/gems/1.8/gems/camping-1.5/lib/camping/reloader.rb:40:
in `initialize'
c:/fredWork/jruby/lib/ruby/gems/1.8/gems/camping-1.5/bin/camping:88:in `new'
c:/fredWork/jruby/lib/ruby/gems/1.8/gems/camping-1.5/bin/camping:88
c:\fredWork\jruby\bin\camping:18:in `collect!'
c:/fredWork/jruby/lib/ruby/gems/1.8/gems/camping-1.5/bin/camping:89
c:\fredWork\jruby\bin\camping:18:in `load'
c:\fredWork\jruby\bin\camping:18
c:/fredWork/jruby/lib/ruby/gems/1.8/gems/camping-1.5/bin/camping:91:in `method_m
issing': undefined method `abort' for Object:0x650892 @gempath_searcher=Gem:
:GemPathSearcher:0x17dc1cb @lib_dirs={2850225=>"c:/fredWork/jruby/lib/ruby/gems/
1.8/gems/builder-2.0.0/{lib,bin}", 25252664=>"c:/fredWork/jruby/lib/ruby/gems/1.
8/gems/markaby-0.5/{lib,bin}", 25068634=>"c:/fredWork/jruby/lib/ruby/gems/1.8/ge
...
bindir="bin", @email="why@ruby-lang.org", @required_ruby_version=Gem::Version:
:Requirement:0x15b0333 @version=nil, @requirements=[[">", #Gem::Version:0x23756
@version="0.0.0">]]>, @autorequire="metaid", @loaded=true, @date=Fri Feb 17 00:
00:00 CET 2006, @extra_rdoc_files=[], @authors=["why the lucky stiff"], @summary
="slight metaprogramming helpers", @default_executable=nil, @extensions=[]>, #G
em::Specification:0x12368df @homepage=nil, @name="sources", @executables=[], @ru
byforge_project=nil, @cert_chain=nil, @rubygems_version="0.9.0", @requirements=[
], @has_rdoc=false, @signing_key=nil, @rdoc_options=[], @loaded_from="c:/fredWor
k/jruby/lib/ruby/gems/1.8/specifications/sources-0.0.1.gemspec", @test_files=[],
@files=["lib/sources.rb"], @platform="ruby", @specification_version=1, @version
=Gem::Version:0x2f2295 @version="0.0.1">, @dependencies=[], @require_paths=["l
ib"], @post_install_message=nil, @bindir="bin", @email=nil, @required_ruby_versi
on=Gem::Version::Requirement:0x878c4c @version=nil, @requirements=[[">", Gem
::Version:0x23756 @version="0.0.0">]]>, @autorequire="sources", @loaded=false, @
date=Sat Jul 29 00:00:00 CEST 2006, @extra_rdoc_files=[], @authors=[], @summary=
"This package provides download sources for remote gem installation", @default_e
xecutable=nil, @extensions=[]>]>> (NoMethodError)
from c:/fredWork/jruby/lib/ruby/gems/1.8/gems/camping-1.5/bin/camping:91
from c:\fredWork\jruby\bin\camping:18:in `load'
from c:\fredWork\jruby\bin\camping:18
Exception in thread "main" java.lang.Error: unexpected type class org.jruby.ast.
CallNode at D:/jruby-0.9.1/lib/ruby/gems/1.8/gems/camping-1.5/bin/camping:[36,36
]:[1017,1020]
at org.jruby.internal.runtime.methods.EvaluateCallable.procArityOf(Evalu
ateCallable.java:85)
at org.jruby.internal.runtime.methods.EvaluateCallable.(EvaluateCa
llable.java:57)
at org.jruby.ast.IterNode.getCallable(IterNode.java:113)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:836)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:933)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:222)
at org.jruby.internal.runtime.methods.EvaluateCallable.internalCall(Eval
uateCallable.java:67)
at org.jruby.internal.runtime.methods.AbstractCallable.call(AbstractCall
able.java:64)
at org.jruby.runtime.ThreadContext.yieldInternal(ThreadContext.java:552)
at org.jruby.runtime.ThreadContext.yieldCurrentBlock(ThreadContext.java:
499)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:1365)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:810)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:933)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:222)
at org.jruby.RubyObject.eval(RubyObject.java:453)
at org.jruby.internal.runtime.methods.DefaultMethod.internalCall(Default
Method.java:112)
at org.jruby.internal.runtime.methods.AbstractMethod.call(AbstractMethod
.java:58)
at org.jruby.RubyObject.callMethod(RubyObject.java:379)
at org.jruby.RubyObject.callMethod(RubyObject.java:323)
at org.jruby.RubyObject.callInit(RubyObject.java:461)
at org.jruby.RubyClass.newInstance(RubyClass.java:174)
at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.jruby.runtime.callback.ReflectionCallback.execute(ReflectionCallb
ack.java:140)
at org.jruby.internal.runtime.methods.CallbackMethod.internalCall(Callba
ckMethod.java:79)
at org.jruby.internal.runtime.methods.AbstractMethod.call(AbstractMethod
.java:58)
at org.jruby.RubyObject.callMethod(RubyObject.java:379)
at org.jruby.RubyObject.callMethod(RubyObject.java:331)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:305)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:841)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:490)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:933)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:222)
at org.jruby.RubyObject.eval(RubyObject.java:453)
at org.jruby.Ruby.loadScript(Ruby.java:863)
at org.jruby.runtime.load.ExternalScript.load(ExternalScript.java:50)
at org.jruby.runtime.load.LoadService.load(LoadService.java:180)
at org.jruby.RubyKernel.load(RubyKernel.java:637)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.jruby.runtime.callback.ReflectionCallback.execute(ReflectionCallb
ack.java:140)
at org.jruby.internal.runtime.methods.CallbackMethod.internalCall(Callba
ckMethod.java:79)
at org.jruby.internal.runtime.methods.AbstractMethod.call(AbstractMethod
.java:58)
at org.jruby.RubyObject.callMethod(RubyObject.java:379)
at org.jruby.RubyObject.callMethod(RubyObject.java:331)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:679)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:933)
at org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:222)
at org.jruby.Ruby.eval(Ruby.java:235)
at org.jruby.Main.runInterpreter(Main.java:177)
at org.jruby.Main.runInterpreter(Main.java:146)
at org.jruby.Main.run(Main.java:111)
at org.jruby.Main.main(Main.java:86)
Payday Loans No Hassle Payday Loans - Payday Loans and Payday Advance Loans online with no hassle
Atomic SEO The Most Powerful Search Engine Marketing Company On The Web!
Atomic SEO I really like this blog it's very informative and a good source of information.
Atomic SEO I really like this blog when I first signed up here i wasn't sure were to post...
Atomic SEO I really like this blog when I first signed up here i wasn't sure were to post...
Atomic SEO I ended up at this blog on acident how can I ecome a full time member...
Joe Schroeder Nice blog. Check out my blog on the truth about making money from home
charlottesville virginia real estate Was reallt ammazing to look at X-mas time this year...
Atlantic City Tickets Show, Concert & Event ticket for all of Atlantic City!
For more information1. Betta fish have superbly developed eyesight and therefore they swim to the top of the tank whenever they see a human hand hovering over it to place the food in.2. Another name for betta fish is the Siamese fighting fish and its name is pronounced in the same way as when we say the Greek letter beta, it is for this reason that some misspell the name and is why you often see it written beta fish, which is the American way. Some think that the name has something to do with the Greek letter, but it is actually derived from the Thai word ikan bettah. Betta fish are known as pla-kad in Thailand and live in shallow freshwater. 3. Because of the fantastic colours of the male betta fish and other advantages, they are the most popular aquarium fish. This of course doesnt mean you can just put them in the tank and not look after them, they need a lot of looking after.4. Betta fish actually originate from the Southeast Asia, Thailand, Malaysia and China.5. They grow to about 3 inches and have a relatively short lifespan of about 2 years, but some live up to 4 years, it has been known that in well looked after aquariums, some have lived over 6 years.6. When the male betta fish is in his aggressive stage he will puff himself out. During this puffing out he raises his gill covers and fins to make himself look...For more information
You really have a nice blog setup here. I hope mine will be as good. Phone Books
I recently discovered a really good website on making money.If interested in making money then I suggest you look there.
Annuaire Adulte
Good post.
I was searching the internet for cheap internet phone service (Voip) and found a company called Via Talk. They are cheaper and just as good as Vonage.
They are now offering 1 year phone service Free when you purchase 1 year – for a limited time. Check it out at Via Talk
Nice blog.
If you’re interested in free weight loss tips please visit this site.
Hey you have a very good blog.
If by any chance you need weight loss help check out by blog: Weight Loss Tips
I recently visited a really informative website on making money.
If you are interested in making money then I suggest you look there.
I recently visited a really informative website on making money.
If you are interested in making money then I suggest you look there.
FREE Business Advertising Tips The Most Powerful Internet Classified Advertising Methods On The Web! "TOP" Rated Money Making Website! A Must See!!!
Hey cool blog. Have you used squidoo yet? I've been doing product review there.
Here are just a few of them:
Burn The Fat Feed The Muscle Review
Fat Loss 4 Idiots Review
AllPSPGames Review
PSP Blender Review
Satellite TV Elite Review
The Simple Golf Swing Review
Jamorama Review
Well hope you liked my reviews and you should check out squidoo sometime it is a lot easier than bloggin.
Hey cool blog. Have you used squidoo yet? I've been doing product review there.
Here are just a few of them:
Burn The Fat Feed The Muscle
Fat Loss 4 Idiots
All PSP Games
PSP Blender
Satellite TV Elite
The Simple Golf Swing
Jamorama
Well hope you liked my reviews and you should check out squidoo sometime it is a lot easier than bloggin.
Greg
What can we not do with blogs? Reading posts as these stir the creative force in me but what do you think would be the future of blogs with the arrival of web 2.0 platform? Stay-safe-on-the-net
Top Shopping , Health, & Entertainment Site 2 Spendless is another great find online that features key discounts and specials that the web has to offer. One of the health specials is about the American Consultants Rx discount prescription cards. It is "free". Don't forget to check out the job section as well if you are looking for a fresh employment start.This site has it all...
New interesting things to learn.Sure will be back soon.--------------------------- Herbal Remedies
For many years, it was thought that Irritable Bowel Syndrome may have been caused by stress. Today it is believed that, while stress may be a trigger for IBS, it may not be the cause. Rather, the symptoms may get worse when you are under stress: when you travel, attend social events or change your daily routine. Your symptoms may also get worse if you do not eat enough healthy foods or after you have eaten a big meal. Read more about how to clean your intestines and colon to help relieve IBS symptoms.
Are there any good sites on lodging tourism travel?I recently found one really informative website on lodging tourism travel .If you know of other good sites about lodging tourism travel , I would appreciate your thoughts and any additional URL you may wish to share on this page.
Hey I liked the blog.
I got a site on XoftSpySE Review which is a antispyware to protect your computer.
Hope you like my site also.
Dog Gifts Hi, found a great gift site for you, has all breeds and made in the USA.
Great site buddy . Really I like ur site I think u r also a Java Developer like me any ways I have some reference books of java which are readable .... Following are the books
Programmer's Guide to Java
Certification A Comp. Primer SE
By Khalid A. Mughal, Rolf W. Rasmussen Publisher : Addison Wesley
Pub Date : August 04, 2003
Java™ Development on PDAs
Building Applications PocketPC
By Daryl Wilding-McBride Publisher : Addison Wesley
Pub Date : June 05, 2003
Learning Java™, 2nd Edition
Publisher : O'Reilly Pub Date : July 2002
Pub Date : June 05, 2003
Jython for Java Programmers
By Robert W. Bill Publisher : New Riders Publishing
Pub Date : December 21, 2001
Enterprise JavaBeans, 3rd Edition
By Richard Monson-Haefel Publisher : O'Reilly
Pub Date : September 2001
Java 1.5 Tiger: A Developer's Notebook
By David Flanagan, Brett McLaughlin Publisher : O'Reilly
Pub Date : June 2004
Java Tutorials Index 1
Java Data Objects
By David Jordan, Craig Russell Publisher : O'Reilly
Pub Date : April 2003
Java™ Extreme Programming Cookbook
By Eric M. Burke, Brian M. Coyner Publisher : O'Reilly
Pub Date : March 2003
Java™ Performance Tuning, 2nd Edition
By Jack Shirazi Publisher : O'Reilly
Pub Date : January 2003
Java™ Performance Tuning, 2nd Edition
By Jack Shirazi Publisher : O'Reilly
Pub Date : January 2003
JavaScript & DHTML Cookbook
By Danny Goodman Publisher : O'Reilly
Pub Date : April 2003
Java Servlet & JSP Cookbook
By Bruce W. Perry Publisher : O'Reilly
Pub Date : January 2004
Java Tutorials Index 2
This is a great Blog! Pardon if I landed on the wrong blog.
As a newbie I just can’t help sharing the following
url with you. It made al the difference to my financial
Situation. For only $7.00 you get your own
ATM Machine. Just follow the link below!
Lose Weight FAST with Pure Hoodia I enjoyed your blog. I look forward to more good things. http://www.yourweightlossclub.com/free-hoodia-pills.html
Free Discount Prescription Drug Cards Here is another
site that features no cost prescription cards that can be downloaded.
Prescription Cards Prescription assistance online for uninsured.
Prescription Cards Prescription assistance online for uninsured.
Web Promotion Software The Most Powerful Search Engine Marketing Software On The Web!
Hi,
Nice blog and layout.... Interested in link exchange?
Mystery,
Home Based Online Internet Businesses & Marketing - Earn Or Make Money Online - Google - Search Engines - Search Engine Marketing
Hi,
Nice blog and layout.... Interested in link exchange?
Mystery,
Home Based Online Internet Businesses & Marketing - Earn Or Make Money Online - Google - Search Engines - Search Engine Marketing
Hi,
Nice blog and layout.... Interested in link exchange?
Mystery,
Home Based Online Internet Businesses & Marketing - Earn Or Make Money Online - Google - Search Engines - Search Engine Marketing
Nice blog and layout! I was wondering if you do link exchange....
make money online
home based business
internet marketing
online advertising
work from home
better business bureau florida
search engine marketing
queerclick
online stock trading
marketingtool.com
real estate agent
brand
cnn money
msn money
credit cards
google
adwords au.weather.yahoo.com refsrc
oreillynet.com
affordable web hosting
yahoo
real estate agents
msn
myspace layouts
zagat survey
survey topsurveysite.com
online survey topsurveysite.com
kohls.com survey
pandaexpress.com survey
paid surveys
myspace surveys
Orange County SEO Companies The First time I called Atomic SEO, I was impressed with the level of expertise that I had percieved. They Got me Results and thats all I asked for so in Orange County and you need seo these are the guys to go too Orange County SEO Experts . Orange County SEO Experts as well... Orange County SEO services orange county website promoters
Woodland Park Real Estate The Most Powerful Search On The Web!
Online EBooks for Internet Marketing.
ghjgggh
test
Affordable SEO Set it and forget it, we do it all for you! Build links and build your web presence in the search engines.
Free Background Check I recently found this site. It's pretty good. You can sign up for free and conduct your own background check or people search.
Great blog. What an excellent discussion. #1 Home Based Business Opportunity
free Special website The Most Powerful website Marketing On The Web!
There are many ways to make money online. Going into niche markets:
I hope I helped you ;-)
You can sign up with this url :D http://bux.to/?r=bachhuy
Vietnam tour: http://www.footprintsvietnam.com
There are most definitely plenty of ways to make money online, but it all depends on how much effort you have in you in order to do what you gotta do!
-Kelly
Hey, you have nailed quite a few points in your story. By the way, have you used squidoo yet? I've been trying it out over there.
Here are some references:
Fat Loss 4 Idiots Diet Review
Fat Loss 4 Idiots
Well hope you liked my review and you should try out squidoo one day cos it is easier than using a blog.
Warm Regards,
Paul
Nice and informative post on this topic.
Your article is well written and provide important information on the specific topic.
I have no word to say that awsome... keep it up and Thanks alot
Skicka en kommentar