Coder Social home page Coder Social logo

Comments (17)

tizoc avatar tizoc commented on June 16, 2024

The README file is outdated, I have to fix that. Forms used to have methods to render all the form fields in one call, but thats not supported anymore. The preferred way of doing it now is to just use some templating system (ERB, HAML, or anything) and iterate over the fields.

For example:

<% form.each do |field| %>
  <tr><td><%= field.label_tag %></td><td><%= field %></td></tr>
<% end %>

from bureaucrat.

activestylus avatar activestylus commented on June 16, 2024

Gotya - I agree with the deprecation. Makes more sense to have people define their own templates.

I do wish there was a way to access the fields individually however. On many forms the flow of the fields are interrupted by other types of random dom elements. Sometimes fields are grouped together differently. More flexibility is needed

I suppose in an ideal world I would be able to do this

<% form = MyForm.new %>
<tr><td><%= form[:title].label_tag %></td><td><%= form[:title] %></td></tr>
</div>

from bureaucrat.

tizoc avatar tizoc commented on June 16, 2024

That works, and is how I render fields 99% of the time. Sorry, I know the documentation is really lacking, but the documentation for Django forms is a good place to start, most of the stuff there applies to Bureaucrat too.

There are some docs here too: http://rubydoc.info/github/tizoc/bureaucrat/frames

from bureaucrat.

tizoc avatar tizoc commented on June 16, 2024

Ok, rubydoc.info is a bit broken right now, it doesn't show the documentation for the Form class, but in Form you have this:

  # Iterates over the fields
  def each
    @fields.each do |name, field|
      yield BoundField.new(self, field, name)
    end
  end

  # Access a named field
  def [](name)
    field = @fields[name] or return nil
    BoundField.new(self, field, name)
  end

from bureaucrat.

activestylus avatar activestylus commented on June 16, 2024

There we go!

% form = SiteForm.new

{{ form[:domain_name].label_tag }}
{{ form[:domain_name].to_s }}

This is really beautiful man. I've also enjoyed picking at your code as it's a lovely example of pure, compositional OO

The last question I have is how to deal with existing models. Right now I am playing with the Cuba framework so my new route looks like this:

on "new" do
  res.write view("sites/new", title: "New Site", site: Site.new, form: SiteForm.new)
end

What is the recommended way to set this up with an edit action? SiteForm.new(site.put_atts_here)

Overall I am curious to see how you integrate this with a working, RESTful app. Perhaps in addition to cleaning up the docs a sample app would be a welcome addition. I can sort out the docs myself if you like and shoot you a pull request. Let me know

In the meantime I'm closing this issue as its been resolved. Thanks for the prompt replies! :)

from bureaucrat.

activestylus avatar activestylus commented on June 16, 2024

Oh one more thing - the widgets are outputting flat name attributes:

<input type="text" name="title" id="id_realname" />

Is there a convention for namespacing the attributes? I'm looking for name="post[title]"

No biggie if there isn't I can hack something up myself. Just trying not to reinvent the wheel here

from bureaucrat.

tizoc avatar tizoc commented on June 16, 2024

Untested example (based on actual code I wrote for an application):

class Base < Bureaucrat::Forms::Form
  extend Bureaucrat::Quickfields

  attr_accessor :edited_object # So that we can access it

  # This method calculates the hash of "initial" values for the form
  # it is useful for forms that "edit" an already existing object.
  def self.initial(object)
    o = Bureaucrat::Utils::StringAccessHash.new
    base_fields.keys.inject(o) do |h, field|
      if object.respond_to?(field)
        value = object.send(field)
        value = value.to_s if value.is_a?(Numeric)
        h[field] = value
      end
      h
    end
  end

  # This method will be used instead of new when we want to "edit"
  # an already existing object. e.g. Forms::User.new_for(Models::User)
  def self.new_for(object, options={})
    options[:initial] = initial(object)
    new(nil, options).tap do |f|
      f.edited_object = object
      f.initialize_formsets(nil)
    end
  end

  # Alternatively, you can override initialize so that it accepts
  # an :object option
  def initialize(data = nil, options = {})
    if self.edited_object = options.fetch(:object, nil)
      options = {
        initial: self.class.initial(self.edited_object)
      }.merge(options)
    end

    super(data, options)
  end

  # On POST routes, we will use this to save changes to the object:
  # if form.valid?
  #   user = form.save(user)
  #   redirect
  # else
  #   .. handle error
  # end
  #
  # or for new records
  #
  # user = form.save(User.new)
  #
  def save(record)
    DB.transaction do # this example assumes Sequel
      populate_object(record) # See Form#populate_object and Field#populate_object
      record.save
    end

    record
  end
end

As for namespacing, there is no convention, and right now Bureaucrat doesn't take advantage of how Rack interprets nested attributes (I don't think it is likely to happen, at least not by default).

from bureaucrat.

tizoc avatar tizoc commented on June 16, 2024

Btw, forms support a "prefix" option, thats something you can use to differentiate fields that belong to one form or another (thats the intended use).

from bureaucrat.

tizoc avatar tizoc commented on June 16, 2024

Sorry, one correction:

Forms::User.new_for(Models::User)

should have been

Forms::User.new_for(Models::User[params[:id]])

What new_for expects is an instance.

from bureaucrat.

activestylus avatar activestylus commented on June 16, 2024

Thanks a bunch, the example is very helpful. I can see myself taking a lot of that above code and factoring into a module for re-use.

I will definitely be kicking the tires a bit more on this as its a lot more robust than I originally thought. If I run into any gotchas I will post em here. Hopefully my questions will help drive your reboot of documentation :)

BTW you really could use a proper promotional page for this once the docs are somewhat sorted. If you need a hand I got some design skillz. You can see my handiwork on the Slim site http://www.slim-lang.com, Merb http://www.merbivore.com (holy crap they really butchered my design :)) I can help you with logos/icons / layout if you need it

Cheers

from bureaucrat.

tizoc avatar tizoc commented on June 16, 2024

Awesome, the slim site in particular looks great.

And yes, I would say Bureaucrat is pretty robust by now, I have been using it in every project as a very-core component. I don't use 100% of the implemented features, but for the stuff I use, it is pretty well battle-tested.

Regarding promotion, I don't promote it because it lacks documentation. It lacks documentation because there are some things I want to change (so I don't want to document things that I will not support in the future), and a few missing components. Then I haven't done those things because I'm lazy, and also spent time on other stuff, oh well. With Fiasco it is the opposite, I focused on documenting things first, made a homepage, etc, but then I decided I wanted to change things and never got to finishing it. I have been slowly leaving Ruby behind for doing work, so, that also affects my motivation.

from bureaucrat.

activestylus avatar activestylus commented on June 16, 2024

Leaving Ruby?? Blasphemy!

Don't tell me the community has lost yet another decent programmer to nodejs :p

from bureaucrat.

tizoc avatar tizoc commented on June 16, 2024

Btw, you may also be interested in Scrivener: http://github.com/soveran/scrivener

It was made by a coworker (the same guy behind cuba, ohm, etc) and is a more lightweight version of the concept behind Bureaucrat (but it focuses only on validation, anything related to HTML is left out).

from bureaucrat.

tizoc avatar tizoc commented on June 16, 2024

No, no nodejs here. For web stuff I have always been a Python guy. The only reason I do Ruby is that it is the main language being used at my Job. And well, Ruby isn't bad, just not my tool of choice.

from bureaucrat.

activestylus avatar activestylus commented on June 16, 2024

I like Python - a lot actually. It's the closest thing to Ruby I have worked with.

I dig Ruby because it's so flexible. The features I like from other languages (like Python decorators) are actually pretty easy to implement. for example http://yehudakatz.com/2009/07/11/python-decorators-in-ruby/

Thanks a lot for the scrivener link. Looks nice and lightweight. Since you plan on migrating I may just dig up the guts of this gem and put together a stripped down version for html rendering

from bureaucrat.

tizoc avatar tizoc commented on June 16, 2024

I really don't like Yehuda's implementation of decorators (both in terms of implementation, interface, performance, etc they are also global).

Ruby is flexible, but I think a lot of its flexibility is wrong-headed, thats why I try to write Ruby code in the most plain way possible. Anyway, it just came to me that this is a github issue and not my inbox, so, not the place for rants :)

re: migrating, thats not what is happening, I don't belong to tribes! I just learn and use tools to do my work.

from bureaucrat.

activestylus avatar activestylus commented on June 16, 2024

Not the place for rants? Have you seen this? :p

rails/rails@3756a3f

That's about all the geekery I'm good for today. Time to enjoy the weekend.

from bureaucrat.

Related Issues (1)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.