Archivos para Junio 2009

30
Jun
09

Mandando archivos a otra aplicacion de Rails

El problema: ActiveResource es muy bueno para hacer que dos aplicaciones
de Rails se comuniquen satisfactoriamente, sin embargo, una vez que se
habla de file uploads y de soporte para multipart, la cosa se complica
un poco, ya que ActiveResource no tien soporte para esto.

Contexto: Railsy-fu es una aplicacion que usa el plugin attachment-fu
para poder hacer file uploads. (Ver el post anterior). RailsyResource es
una aplicacion que usa los web services de de Railsy-fu. RailsyResource
es la que se va a encargar de hacer los file uploads.

En este ejemplo, una mensaje puede o no tener un attachment. Vamos a
tener que primero hacer el upload a Railsy-fu y después tomar el id de
ese file para relacionarlo con la aplicación.

Como no podemos usar ActiveResource, vamos a tener que hacer un post
desde RailsyResource a Railsy-fu con multipart. Para poder hacer esto,
existe la ‘gem httpclient’. (Instalarla… gem i httpclient).

El procedimiento es asi…

1) Instanciamos el objeto Httpclient
clnt = HTTPClient.new

2) El archivo que se va a ser uploaded, tiene un filename del tipo
RackMultipart0123456789 y se encuentra en /tmp/ comúnmente. Como es un
archivo temporal, no podemos renombrarlo ahi mismo en /tmp/ , entonces
debemos de copiar el archivo a una carpeta temporal dentro del
RAILS_ROOT
name = params[:message][:file].original_filename
directory = "#{RAILS_ROOT}/public/temp/"
path = File.join(directory, name)
File.open(path, "w+") { |f| f.write(params[:message][:file].read) }

3) Ya que ha sido creado el archivo con su nombre original, lo mandamos
por post/put a el web service de Railsy-fu.
body = { :uploaded_data => File.open("#{RAILS_ROOT}/public/temp/" + name), :message => ‘yeah!!!’, :apikey => ‘12312312312312312123123′}
res = clnt.post(‘http://railsyfu.com/files.xml’, body)

4) Necesitaremos el file_id de ese archivo que acabamos de guardar para
poder relacionarlo con el objeto. Para hacer esto vamos a parsear el
response (con libxml-ruby, es más rápido según esto).
doc = XML::Document.string(res.content)
file_id = doc.root.find_first(‘id’).content #por ejemplo <id> 145 </id>

5) Y se lo anhadimos al objeto message.
@message.file_id = file_id

Falta despues hacer revisar si es que se no se hizo un attachment, asi
que todo lo anterior deberia de estar dentro de un if que hace esta
verificacion.

Por ultimo, borramos el archivo temporal que hicimos.
if @message.save
File.delete("#{RAILS_ROOT}/public/temp/" + name) if params[:message][:file] and File.exists?("#{RAILS_ROOT}/public/temp/" + name)

24
Jun
09

Testing Attachment fu

Quick post de como hacer el testing a attachment fu:

1.- Hacemos una carpeta dentro de fixtures que se llame files:
mkdir test/fixtures/files

2.- …incluimos algun archivo doc, imagen lo que sea.

3.- Dentro del test hacemos el load de esta forma

test &quot;should create person&quot; do
fdata = fixture_file_upload(‘/files/doctestfile.doc’, ‘application/msword’)
assert_difference(‘Person.count’) do
post :create, :resume =&gt; {
:person_id =&gt; 1,
:uploaded_document =&gt; fdata
},:html =&gt; { :multipart =&gt; true }
end
end

y ya… creo que ya

23
Jun
09

Usando attachment fu para para hacer uploads de documentos

Es muy parecido a lo de las imágenes.

Primero se instalamos el plugin…


ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu

Se genera el modelo del documento…


ruby script/generate model Document record_id:integer record_type:string filename:string content_type:string size:integer

rake db:migrate para las migraciones. Y ahora se anhade lo siguiente al model de ‘Document’. Las opciones completas de lo que se puede hacer están acá: http://wiki.github.com/technoweenie/attachment_fu.


class Document < ActiveRecord::Base
belongs_to :record, :polymorphic => true
has_attachment :content_type => ['application/pdf', 'application/msword', 'text/plain'],
:storage => :file_system,
:path_prefix => 'public/records'

validates_as_attachment
end

Los últimos pasos son agregar el metodo uploaded_document= a los modelos que se relacionan con los archivos. Por ejemplo: Person.rb tiene un documento.


class Person < ActiveRecord::Base

has_one :document, :dependent => :destroy, :as => :record

validates_presence_of :title
validates_length_of :title, :in => 1..100
validates_length_of :rating, :in => 0..10, :allow_nil => true

def uploaded_document=(data)
unless data.blank?;
document.destroy if document
self.reload
create_document :uploaded_document => data ##dudas en esta parte... :uploaded_data???
end
end

end

Para aceptar uploads en la vista se tiene que incluir esto en la forma.


<% form_for @movie, :html => {:multipart => true} do |f| %>

...

Document
<%= f.file_field :uploaded_document %>

ejemplo de liga al documento: <%= link_to “Document”, person.document.public_filename if person.document %>

Bueno ciao.

16
Jun
09

Shigoto notes #1

Para las migraciones…

rake db:create
rake db:migrate

me salio este error…

undefined method `reenable’ for <Rake::Task db:schema:dump =>
[environment]>:Rake::Task

eso significa que tengo que actualizar rake probablemente…

(estoy en ubuntu)

sudo aptitude remove rake
sudo gem install rake

06
Jun
09

Stack overflow topbar

<!– aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa –>
<div id="topbar">
<div id="hlinks">
<a href="/users/recent/9082"><img src="/content/img/so/replies-off.png" width="15" height="10" title="you have no new replies"></a>

<a href="/users/9082/wallyqs" rel="canonical">wallyqs</a>&nbsp;
<span class="reputation-score" title="reputation score">123</span>
<span title="7 bronze badges"><span class="badge3">●</span>
<span class="badgecount">7</span></span>
<span class="link-separator">|</span>
<a href="/users/logout?returnurl=%2f">logout</a>
<span class="link-separator">|</span>
<a href="/about">about</a> <span class="link-separator">|</span>
<a href="/faq">faq</a>
</div>
<!– aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa –>