Nov 27
Auto kostet Kosten
admin, 27. November 2008

Also Politiker bekommen ja ein Auto, und vielleicht auch einen Chaffeur, gestellt. Für uns, die wir die Politiker bezahlen, schaut das ein bisschen anders aus. Hier mein Beispiel:

Kosten für Auto

Kaufpreis Seat Toledo (BJ 1992): 1600
Typisierung 250
Zulassung 230
Versicherung (jährlich) 465
Zulassungsvignette (jährlich) 35
Parkschein (jährlich) 68
Autobahnvignette A (jährlich) 78
Autobahnvignette CH (jährlich) 27
ÖAMTC (jährlich) 65
Reparatur ca. (jährlich) 300
Benzin ca. (monatlich) 100

Also mein Auto hat mich im Einkauf 1600 Euro gekostet, wobei ich gleichmal 480 Euro Erpressungsgelder abdrücken durfte (Typisierung + Zulassung). Im Jahr kommt mich das Auto, also Erpressungsgelder und notwendige Abgaben zusammen, auf ca. 2238 Euro. Das sind ca. 190 Euro im Monat.

Also ich hab ein Auto, weil man hier in Vorarlberg ein Auto braucht. Ohne Auto ist man total aufgeschmissen. Und mein Auto macht nochnichtmal so irre Spass zu fahren, ich mein das ist Baujahr 1992, das ist eher anstrengend.

Nov 12
Morgenstund ist ungesund
admin, 12. November 2008

“Boah krass” hab ich mir beim Aufwachen heut morgen gedacht, “da bin ich jetz echt mal voll früh von selbst aufgewacht”. Entspannt aufgestanden, ne Uhr gesucht: 1/2 10 Uhr. höhö

Über Shanghai nachgedacht, und das verdammte Geldproblem. Was mach ich danach? Wie komm ich wieder zu Kohle, ohne so einen schlafraubenden Dodeljob machen zu müssen wie 90% meiner arbeitenden Mitmenschen?

Oder sollte ich mein Geld nicht lieber für was sinnvolleres ausgeben, Feldenkrais Trainings zum Beispiel?

Keiner kennt die Antwort …

Nov 6

What I’m showing here is how to make a multiple file attachment for one or more models (it’s DRY) that integrate with active scaffold. I build on the great contribution http://www.practicalecommerce.com/blogs/post/432-Multiple-Attachments-in-Rails by Brian Getting.

What I did is this:

- integrated the multiple attachment handling with active scaffold
- DRYed up the code
- removed the post limit

And it looks something like this:

Which is quite a change in the end. Be sure to have attachment_fu and active_scaffold in your plugins-forlder. Let’s go through the parts:

First some obvious prerequisites: generate the models and get the db going. Remember to configure your config/database.yml or your rake will chocke. ;-)

script/generate model post title:string description:text
script/generate model attachment size:integer height:integer width:integer parent_id:integer attachable_id:integer position:integer content_type:string filename:string thumbnail:string attachable_type:string
rake db:create
rake db:migrate

Since I’m using local filestorage here, make sure there’s an uploads directory in public.

Now for the models themselves, set up the relations as follows

app/models/post.rb

has_many  :attachments, :as => :attachable, :dependent => :destroy

app/models/attachment.rb

belongs_to :attachable, :polymorphic => true
 
has_attachment :storage => :file_system,
                 :path_prefix => 'public/uploads',
                 :max_size => 1.megabyte

app/controllers/application.rb

protected
 
def process_file_uploads(owner)
  params[:attachment].each do |key, value|
  # only process files that got a size (and thus are not nil or empty etc)
  next unless value.size > 0
    attachment = Attachment.create({:uploaded_data => params[:attachment][key]})
    owner.attachments << attachment
  end
  owner.save
end

I moved process_file_uploads into the ApplicationController, so that it’s accessible from every model and controller that needs access to it. The checks for the valid params have been a bit bogus, and actually it did not work for the update in some cases. So I just test for size. If there’s a size, there’s a file, easy as pie. In the end I save the owner, something rails can’t live without, it seems.

app/controllers/posts_controller.rb I created this by hand (no need for a rails scaffold here)

active_scaffold :post do |config|
  config.columns = [:title, :description, :attachments]
  config.create.multipart = true
  config.update.multipart = true
end
 
def before_create_save(record)
  process_file_uploads(record)
end
 
def before_update_save(record)
  process_file_uploads(record)
end

Well this code got pretty concise. I basically removed 30 lines of code and wrote it so active scaffold can take care of almost everything. I just used before_create_save and before_update_save to hook into the saving process and take care of the attachments. Like before, I had to tell the forms that they are multipart/formdata.

app/controllers/attachments_controller.rb

active_scaffold :attachments do |config|
 config.action_links.add 'send_myfile', :label => 'Download', :type => :record, :popup => true
end
 
def send_myfile
  attachment = Attachment.find(params[:id])
  send_file(attachment.full_filename, :type => attachment.content_type, :filename => attachment.filename)
end
 
def destroy
  @attachment = Attachment.find(params[:id])
  @attachment.destroy
  asset = @attachment.attachable
end

Here the destroy is important. It’s the old way to do it, but works pretty swell.

app/views/attachments/_attachment.html.erb

	<li id="attachment_&lt;%= attachment.id %&gt;">&lt;%= attachment.filename %&gt;
&lt;%= link_to_remote "Remove", :url  =&gt; attachment_path(:id =&gt; attachment), :method =&gt; :delete, :html =&gt; { :title  =&gt; "Remove this attachment" } %&gt;</li>

So here I have a file with again DRYed up content. Actually it’s mostly Brian’s code, but here it doesn’t need to be copied to each and every view that uses the multiple attachment functionality.

app/views/attachments/destroy.rjs

page.hide "attachment_#{@attachment.id.to_s}"
page.remove "attachment_#{@attachment.id.to_s}"
page &lt;&lt; "if ($('attachment_data').disabled) { $('attachment_data').disabled = false };"

This also got a bit smaller, mainly because I don’t check for a max. amount of allowed uploads.

app/views/active_scaffold_overrides/_attachments_form_column.rhtml

&lt;% fields_for Attachment.new do |attachment| -%&gt;
 
	<label for="attachment_data">Attach Files:</label>
	&lt;%= attachment.file_field :data %&gt;
 
&lt;% end -%&gt;
<ul id="pending_files">
	&lt;% if @record.attachments.size &gt; 0 -%&gt;
	&lt;%= render :partial =&gt; "attachments/attachment", :collection =&gt; @record.attachments %&gt;
	&lt;% end -%&gt;</ul>
<script type="text/javascript"><!--mce:0--></script>

I created the active_scaffold_overrides folder, just like it’s recommended in the neat documentation of active scaffold. Here I provide the code (again, it’s mostly Brian’s, I just DRYd it up and moved it to a DRYer place) that active scaffold needs to display the upload functionality. I also just copied the MultSelector code, so there’s this “max” parameter left, I just feed it a high enough number, like 100.

Well that’s basically all, remember to put in the config/routes.rb:

map.resources :posts, :active_scaffold =&gt; true do |post|
  post.resources :attachments, :active_scaffold =&gt; true
end
map.resources :attachments

I use this funky new nested routing stuff here. :-)

remember to load the ajax and active_scaffold javascripts in app/views/layouts/application.html.erb (delete index.html from public)

 &lt;%= javascript_include_tag :defaults %&gt;
 &lt;%= active_scaffold_includes %&gt;

and into public/javascripts/application.js append the following:

// -------------------------
// Multiple File Upload
// -------------------------
function MultiSelector(list_target, max) {
  this.list_target = list_target;this.count = 0;this.id = 0;if( max ){this.max = max;} else {this.max = -1;};this.addElement = function( element ){if( element.tagName == 'INPUT' && element.type == 'file' ){element.name = 'attachment[file_' + (this.id++) + ']';element.multi_selector = this;element.onchange = function(){var new_element = document.createElement( 'input' );new_element.type = 'file';this.parentNode.insertBefore( new_element, this );this.multi_selector.addElement( new_element );this.multi_selector.addListRow( this );this.style.position = 'absolute';this.style.left = '-1000px';};if( this.max != -1 && this.count >= this.max ){element.disabled = true;};this.count++;this.current_element = element;} else {alert( 'Error: not a file input element' );};};this.addListRow = function( element ){var new_row = document.createElement('li');var new_row_button = document.createElement( 'a' );new_row_button.title = 'Remove This Image';new_row_button.href = '#';new_row_button.innerHTML = 'Remove';new_row.element = element;new_row_button.onclick= function(){this.parentNode.element.parentNode.removeChild( this.parentNode.element );this.parentNode.parentNode.removeChild( this.parentNode );this.parentNode.element.multi_selector.count--;this.parentNode.element.multi_selector.current_element.disabled = false;return false;};new_row.innerHTML = element.value.split('/')[element.value.split('/').length - 1];new_row.appendChild( new_row_button );this.list_target.appendChild( new_row );};
}

I have a WORKING example for download :-)