jul is a nolife

Thursday, April 3 2008

Add an id to your has_and_belongs_to_many join table

If you want to define a model for your has_and_belongs_to_many join table, you really need to care, because if your table has an id primary key, then the join will not work.

Imagine that you have two tables Product and Keyword and you want to link these with a product_keywords You will create a migration :


 create_table :product_keywords do |t|
      t.column :product_id, :integer
      t.column :keyword_id, :integer
    end

You need an id because you want easily access the table throught a model


class ProductKeyword < ActiveRecord::Base
  belongs_to :product
  belongs_to :keyword
  # something like voting for keyword in product
  has_many :votes
end

Then if you want to access the keywords with Product model


class Product < ActiveRecord::Base
 has_and_belongs_to_many :keywords, 
:class_name=>"Keyword", 
:join_table=>"product_keywords", 
:foreign_key=>"product_id", 
:association_foreign_key=>"keyword_id"
end

This actually doesn't work! Why? When the SQL statements will ask for the keywords columns, it will get all columns, including product_keywords. Since we have an id for keyword AND for product_keywords, the id results are not clear. We need to force the keywords column only.


class Product < ActiveRecord::Base
 has_and_belongs_to_many :keywords, 
:class_name=>"Keyword", 
:join_table=>"product_keywords", 
:foreign_key=>"product_id", 
:association_foreign_key=>"keyword_id", 
:select=>"keywords.*",
:insert_sql=>'INSERT INTO product_keywords (product_id, keyword_id) VALUES (#{id}, #{record.id})'

end

Friday, February 29 2008

Rails problems and errors : Expected ... to define ...


Expected /your/rails/dir/someclass.rb to define Someclass

It seems that this error appears when something is missing, to know what is missing exactly, try to run

 
$ script/console 

then


 >> Someclass

It will give you details about the problem.

Wednesday, July 11 2007

Second Life web service with rails (1/2)

In this first part, we will see how to communicate with an in-world object from a ruby on rails application thanks to XML-RPC. At the beginning, we define a second life structure (app/models/second_life_struct.rb) which represent the API format of second life :


class SecondLifeStruct < ActionWebService::Struct
  member "Channel", :string
  member "StringValue", :string
  member "IntValue", :int
end

Next, we create a new rails API (app/apis/second_life_api.rb) which use the structure :

class SecondLifeApi < ActionWebService::API::Base
  inflect_names false
  api_method "llRemoteData", :expects=>[SecondLifeStruct], :returns=>[SecondLifeStruct]
end

Before continuing, let's see the object LSL script which receive communication :


default
{
  state_entry()
    {
     llOpenRemoteDataChannel(); 
    }

    remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval) 
    {
      if(type==REMOTE_DATA_CHANNEL) {
	llOwnerSay("Communication channel: "+(string)channel);
      } 

      if(type==REMOTE_DATA_REQUEST) {
        llOwnerSay(sval);
        llRemoteDataReply(channel,message_id,"Everything is alright",0);
      }
    }
}

Communication channel is an unique key which permit to communicate back with this object from the Linden's webservice. We must copy this key for loading our rails web page (/second_life/test_object?channel=key)

We just have to define the controller now:

class SecondLifeController < ApplicationController
  web_client_api :second_life, :xmlrpc, "http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi", :timeout=>90

  def test_object
    canal=params[:channel]
    begin
      resultat=second_life.llRemoteData(SecondLifeStruct.new("Channel"=>canal,"StringValue"=>"Hello World!","IntValue"=>"0"))
      render :text=>resultat["StringValue"]
    rescue
     render :text=>"Object doesn't respond"
    end
  end
end

That's all! When we load the page, second life object says "Hello World!" In the next post, we will see how to communicate in the other way : from in-world object to rails application.

More informations about second life XML-RPC format here.