tcocca / active_pdftk

ruby wrapper for the pdftk command line utility for working with editable pdf files
MIT License
46 stars 37 forks source link

First contact #1

Closed elmatou closed 13 years ago

elmatou commented 13 years ago

Hi Tom, I just find your gem, and am pretty happy to see somebody doing exactly what I was about to do. If you agree, I will be happy to help you with "pdftk_forms" (and to add some features I need). I'm gonna post several issues tickets (for an easier follow up of topics) on points we could discuss on.

See you

tcocca commented 13 years ago

Wow, nice timing. I just published 0.1.0 about 1 hour ago, you logged the first ticket within 30 min. What else are you looking for in the gem?

~ Tom

elmatou commented 13 years ago

Hi, First off all, thx for your work, it is very understandable and usefull. I need a gem very object oriented, and keeping all the flexibility of pdftk. At this point I'm working on an abstraction layer, a Form object which hold all the wrapper information, and all the current works on the form. Using the Field object for the content representation and the Wrapper object in order to interact with pdftk. Basicly I prefer higher abstraction (I'll integrate this code in a very bigger app). this could be :

module PdftkForms
  class Form
    def initialize template
      @pdftk = Wrapper.new
      @template = template
    end

    def fields
      @fields ||= @pdftk.fields(@template)
    end

    # we could use a method_missing stategy to dynamicly define setter and getter for fields
    def get(field_name)
      #TODO check if several inputs with same names are allowed
      @fields.select {|f| f.name == field_name}.first
    end

    def set(field_name, value)
      get(field_name).value = value
    end

    def save(path = nil)
      #TODO Flatten should be an option
      @pdftk.fill_form(@template, path || @template + '.filled', fields_to_fill)
    end

    def save!
      save(@template)
    end

    def to_fdf(path = nil)
      Fdf.new(fields_to_fill).save_to(path || @template.sub('.pdf', '.fdf'))
    end

    def to_xfdf(path = nil)
      Xfdf.new(fields_to_fill).save_to(path || @template.sub('.pdf', '.xfdf'))
    end

    # Generate a PDF where the input are filled with there name.
    # Helpfull for autogenerated forms with horrorfull input names.
    def dummy_filling!
      fields.each { |f| f.value = f.name.to_s if f.type == 'Text'}
    end

    private

    def fields_to_fill
      hash = {}
      fields.each do |f|
        hash[f.name.to_s] = f.value.to_s if f.value
      end
      hash
    end
  end

  class Field
  end

  class Wrapper
    # Addition for magic fdf || xfdf support
    def version
      call_pdftk("--version").scan(/pdftk (\S*) a Handy Tool/).to_s
    end
  end
end

and then you use simply with :

@bnc = PdftkForms::Form.new('bnc.pdf')
# your loggic here
@bnc.dummy_filling!
@bnc.set('A54bis', 'shoe')
@bnc.save

What do you think about this !?

tcocca commented 13 years ago

The method_missing for automatic getter/setter methods for fields could work like the following (note this is not tested, just working it out in my mind) and don't forget the respond_to? I definitely like this form level abstraction. Are you working on a pull request for this? If not I can try and work on this soon.

 def method_missing(method_name, *args)
  field_name = method_name.to_s.delete('=')
  if @fields.any? {|f| f.name == field_name}
    if method_name.to_s =~ /=/
      set(field_name, *args)
    else
      get(field_name)
    end
  else
   super
  end
end

def respond_to?(method_name, include_private = false)
  field_name = method_name.to_s.delete('=')
  if @fields.any? {|f| f.name == field_name}
    true
  else
    super
  end
end

Also, for the wrapper xfdf support I like your version call and would add this to it:

class Wrapper
  # Addition for magic fdf || xfdf support
  def xfdf_support?
    version.to_f >= 1.40
  end

  def version
    call_pdftk("--version").scan(/pdftk (\S*) a Handy Tool/).to_s
  end
end

This looks pretty cool though, the set method would need to work slightly differently though. I think I would just add another attr_access to field for like "user_value" or something because right now value holds the default value for the field which we wouldn't want to lose. But I like this. I might work on the Form abstraction a touch more, but please feel free to for and submit a pull request for this stuff.

~ Tom

elmatou commented 13 years ago

Great ! I'm glad we have the same point of view. It is 9pm in France, and will work on the implementation tomorrow morning I'll send you a pull request tomorrow afternoon GMT+1 (have to work and tests also).

See you

tcocca commented 13 years ago

Closing this just to clean up since there is already another pull request in for this stuff.