Rails 3 Lernen mit d:evolute

Angelegt von suung Mon, 06 Jun 2011 11:21:00 GMT

Aus den Archiven unserer Software - Abteilung d:evolute ein Einsteiger - Guide fuer Rails (3)

- rails_lernen.pdf

Automatically Create Relations with Inherited Resources and/or Rails3 Magic

Angelegt von suung Tue, 25 Jan 2011 14:04:00 GMT

If you have a resource (in my case that's Document and want to add or create a related resource (in my case Style) and you use Inherited Resources, your controller may look like this:

class DocumentController < InheritedResources::Base

  respond_to :html, :pdf

end

There is nothing going on, because InheritedResources will do the job for you: providing 'automatically' scaffold functionality.

Okay, in most cases you will not want that, you want to add something.

In my case that is, as I mentioned, to add or create a related 'Style' in the create-action

To override the create action, you could

def create
  super do
    @style=Style.create(params[:style])
    ...
  end
end

- in general.

Inherited Resources skips the 'super' giving you \create!' which can take the block.

Anyway, to really add a new style to the @document (that is used by the magic), i would have to do something like this:

 

 

  def create

    if params[:style]

      @style = Style.create(params[:style])

      @document = Document.new(params[:document])

      @document.style_id = @style.id if @style

    end

    create!

  end
I think, that speeks for itself.
Two thing here are not necessary:
  1. params[:style] and the if condition (because inherited resources could already check that)
  2. @document = Document.new (because inherited resources already did that in fact

To get rid of it, we use a other trick:

 

class Document < ActiveRecord::Base

  belongs_to :style  

  accepts_nested_attributes_for(:style)

end

This will let the style-attribute take a Hash that can lead to a full create, which is nice.
It's an Rails3 Feature.

With IR again, you can

class DocumentsController &lt; InheritedResources::Base



    protected



    def begin_of_association_chain

      case

      when params[:style_id]

        Style.find(params[:style_id]).try(:documents)

      when params[:style]

        Style.create!(params[:style]).try(:documents)

      else

        Document

      end

    end

  end

Fileupload with Mongoid and Paperclip

Angelegt von andi Sun, 12 Dec 2010 16:05:00 GMT

Last week, a new gem - ’mongoid-paperclip was released. If you are already used to paperclip, you might in deed be sad if you use mongoid and have to disclaim the convenience of paperclip if you want to add file upload to one of your documents.

Anyway, i’m forming a habit of having a closer look at new gems, and at least check out the codebase as far as necessary to know what i’m dealing with. In the case of mongoid-paperclip I was particularly interested, and I was not too much surprised to find out that it’s actually a very easy implementation.

You don’t have to care about how complicated a gem or library you rely on is, as long as it works fine, but i often see people dismiss an external library in the moment it doesn’t perfectly fit their needs. But often code is not that complicated, and it would be worth to have a look, find out how easy it is to tweak it, go for it, and be happy and independent.

To illustrate how easy a gem like this can be, I’d like to give you some code, and show you what the gem actually does.

But first you have to know, how to use mongoid-paperclip. See this example, and keep in mind, that you can use ‘has_attached_file’ exactly the way you’re used to with paperclip, so checkout the paperclip docs if you’re unsure. I keep it with the most easy example without any additional options.

class Profile
  include Mongoid::Document
  include Mongoid::Paperclip

  has_attached_file :avatar
end

Aside from the gemspec and readme, yhe code is actually all in one file, in lib/mongoid_paperclip.rb.

First thing that happens, is to require Paperclip, and output a note if it cannot be loaded.

begin
  require "paperclip"
rescue LoadError
  puts "Mongoid::Paperclip requires that you install the Paperclip gem."
  exit
end

Second is, deactivating Paperclips default logger, because it depends on ActiveRecord.

Paperclip.options[:log] = false

Therefore, if Rails is loaded and a logger specified, we can use this.

if defined?(Rails)
  if Rails.respond_to?(:logger)
    Paperclip.options[:log] = Rails.logger
  end
end

And now we come to the Mongoid::Paperclip module itself. As you see its less then 15 lines of code, and what it does is basically to include paperclip, and to pass the params to paperclips ‘has_attached_file method. Last step is to make sure that mongoid knows about the necessary fields, because paperclip can not deal with mongoids dynamic attributes.

    module ClassMethods

      def has_attached_file(field, options = {})

        include ::Paperclip
        include ::Paperclip::Glue

        has_attached_file(field, options)

        field(:"#{field}_file_name",    :type => String)
        field(:"#{field}_content_type", :type => String)
        field(:"#{field}_file_size",    :type => Integer)
        field(:"#{field}_updated_at",   :type => DateTime)
      end
    end
  end

Well, this was pretty easy to understand, and you might want to come back on it in similar situations.

Problems with Rails 3 Generators 'invoke' and migration templates

Angelegt von suung Fri, 03 Dec 2010 14:47:00 GMT

I want to generate migrations.

It seems, nobody has ever thought about that because in Rails 3 there is idea, that I have to create the timestamp on my own like this:

 

def self.next_migration_number(dirname) if ActiveRecord::Base.timestamped_migrations Time.now.utc.strftime("%Y%m%d%H%M%S") else "%.3d" % (current_migration_number(dirname) + 1) end end

So some people suggest another solution

class ActsAsTaggableOnMigrationGenerator < Rails::Generators::Base

 

    invoke "migration", %(add_fields_to_tags name:string label:string)
  end

but that really does not work for me, it leads to

 

/usr/lib/ruby/gems/1.8/gems/activesupport-3.0.1/lib/active_support/whiny_nil.rb:48:in `method_missing': undefined method `name' for nil:NilClass (NoMethodError)

from /usr/lib/ruby/gems/1.8/gems/thor-0.14.4/lib/thor/invocation.rb:116:in `invoke_task'

from /usr/lib/ruby/gems/1.8/gems/thor-0.14.4/lib/thor/group.rb:224:in `dispatch'

from /usr/lib/ruby/gems/1.8/gems/thor-0.14.4/lib/thor/invocation.rb:109:in `send'

from /usr/lib/ruby/gems/1.8/gems/thor-0.14.4/lib/thor/invocation.rb:109:in `invoke'

:)

Update:

This worked:

invoke "migration", "add_fields_to_tags" "name:string label:string")

Do i use Mongoid, Mongomapper or Mongomatic as my Ruby ORM for MongoDB?

Angelegt von andi Tue, 23 Nov 2010 17:50:00 GMT

Now that I had a first chance to use MongoDB (through Mongoid) in the wilderness, I decided to move back and reflect on the alternative ORMs for Mongo in Ruby. Which mostly means Mongomapper, though, with Mongomatic, we have a third player in the game.

I found some pretty interesting ressources on this topic. First of all, Peter Cooper passes the question of what mapper to use, to the authors of both, Mongoid and Mongomapper. I recommend to read the article, or at least the yellow boxes featuring the authors opinions. But don’t get confused about the statement Mongoid would support Rails 3, while Mongomapper is still focussing on Rails 2. They are both Rails 3 compatible.

It remains to say that Mongoid is definitley following the style of ActiveRecord, making use of ActiveModel wherever possible and having a Arel-like Query Api, while MongoMapper is rather having its source in the DataMapper world. There is another interesting comparision on the Antrarestrader Blog.

I recommend you to read on by yourself, but i try to put together what i learned about this two orms for mongo:

mongoid:

  • better support for embedded documents
  • better support for very large documents (>500kb)
  • closer to activerecord, by making use of active model and an arel like query syntax
  • very nice and lean documentation to be found on the project website..

mongomapper:

  • better support for reference associations
  • supposedly it has a bigger community, or at least still had a bigger community last summer
  • better plugin interface

mongomatic

  • supposedly it’s faster. there is a benchmark posted on some blog. The benchmark itself can be downloaded on Github
  • it says it focusses on simplicity

Refactoring Redmine to be more agile and ajaxified

Angelegt von suung Mon, 27 Sep 2010 14:38:00 GMT

I did some redmine tweaking this weekend.

The goal was, to make it more agile. Agile in this terms means:

  • You can list issues, that follow each other easily
  • You need much less clicks, to get an overview over issue details and look into them, while browsing
  • You can add and edit (sub) issues inline

I think these are main goals, people address in plugins now or not at all.

I came up with some mayor changes, that should be done in core redmine, to fit my needs:

1) Pack Views into helpers and partials

I want to be able to toggle through single sections if my issue - create flow.
Therefore i created some helpers, that added divs and toggle - links with Javascript around the specific section (.e.g. in issues/show)

Doing this, i saw, that redmine is amazingly unflexible here. You even get problems toggling single sections, because of cascaded divs that have been added there just for design purpose (the background color of some parts of the issue and such)

So the tasks would be:

  • move sections into partials
  • wrap everything into sections

2) Make Controllers AJAX-agnostic

Take Redmine and try to render issues/show or issues/new in a modalbox via AJAX.
It works, most controllers contain a block like this:

respond_to do |format|

  format.html {#normal render behaviour}
  format.js {#render some attributes partial}

end

But
a) not every action has this block
b) it sometimes doesn't do, what you actually want to do.

If you want to render any action via xhr, you need two things to do:

a) skip the layout on xhr - requests

b) change the return - to behaviour slightly, to pass redirect_to or return_to.

Why the latter is needed - take a look at this example:

  1. You create an issue in an inline div.
  2. After you created the div, it should NOT redirect to issues show.
  3. Instead ideally it would know, where you have been and render only a bit of javascript, that magically loads the right row in some table.
  4. The same for error handling

So what is to do:

  • Also with the goal to be compatible with new Rails 3 goodness (responds_with...): Remove all respond_to - blocks and replace them with a Responder, that can handle those things.
  • Replace all links, that should be UI-context agnostic to pass parameters for redirect_to and others

Go with a plugin!

Plugins could do this as well (and we will come up with some plugins, eventually) but the problem is:

To add some simple line of code to let's say every action of your Issues-Controller would require
a) a hook at every place, where you want to do that
b) to copy the whole controller into your plugin (which likely is not compatible with others!)

One of the great things in Redmine is the list of hooks. Hooks are a way to inject code at exactly one single position.
A hook can for example add things to the bottom of the issue_details_list

in the code it looks similar to this:

call_hook(:issue_details_bottom) # or so

I will be about to paste a complete list of hooks soon.
Sadly, this pattern is not followed consequently enough.
A plugin can only be as good, as the positions for the hooks are chosen.
According to the above suggested refactorings, I would recommend:
  1. Go through controllers and views
  2. Create a ViewHook for every (now toggable and named) section in the view
  3. Create a hook for the corresponding Responder (or block, that responds to the browser) in the controllers.

 

Refactoring Redmine

Redmine is about to become really great. The code base is not lacking of basic principles. And even if you try to add more complex logic, than you see realized in redmine, you will find some methods, already prepared for or partially supporting your goal.
 
Eric Davis wrote a book about Refactoring Redmine. Will read it and review.

Things to consider when starting a new Rails app

Angelegt von niklas Sun, 26 Sep 2010 08:48:00 GMT

Quick notes to get you started with Rails 3 and stop repeating the same tasks over and over again (sounds a lot like a memo for me...) more...

Rails 3

Angelegt von andi Wed, 24 Feb 2010 13:14:00 GMT

Well, to avoid people from telling me they do not know what rails 3.0 will be shipped out with, here’s the link to the full release notes:

http://guides.rails.info/3_0_release_notes.html

I allow myself to quote the pretty self confident introduction to their new release:

Rails 3.0 is ponies and rainbows! It’s going to cook you dinner and fold your laundry. You’re going to wonder how life was ever possible before it arrived. It’s the Best Version of Rails We’ve Ever Done!

I don’t want to go in to any detail about rails 3, because it’s pretty much described on the page that you’ll see when you follow the link above. So go ahead :)

Rails Plugins

Angelegt von andi Wed, 24 Feb 2010 13:01:00 GMT

While reading an article about how the behavior of Rails Plugins will change with Rails 3.0 , i stumbled upon this new page ’railsplugins.org’ that engine yard has created to keep track about which plugins are compatible with rails 3, with ruby 1.9, if they run with jruby and if they are thread safe.

Though there are many more requirements one could have on rails plugin, like a solid test coverage, and a proper re-usability (e.g. a slightly different approach then the one the plugin was originally designed for, should still be easy to solve with the plugin), it’s a good start, and a nice list of plugins, currently counting 145.

After all, we should somehow always have an more complex overview over all those plugins, and collect all interesting meta-information, and remember at least which plugin we use in which application. A good start could be to extract this plugin list, and store it in some kind of database for its own, to be able to connect it with our own meta-information.

Who needs help on building a custom scraper, to scrape out the plugin list :)?

Rails 3 ist draussen

Angelegt von suung Mon, 22 Feb 2010 06:14:00 GMT

Rails 3 ist draussen und es gibt viele tolle neue Aenderungen.

Alles ganz toll.

 

Lies mehr ->