On Dec 20, 7:00 am, Garry Hill <[email protected]> wrote:
> Hi all,
>
> I'm developing a CMS system based on Sequel that uses the concept of
> 'revisions' to manage the publish workflow and need some advice about
> the best way to implement this in Sequel.
>
> Let me explain a bit more. The editable content of the CMS is held in
> a table called simply "content". When a user decides to make some
> changes live the system duplicates the "content" table into another
> table named after the next revision number, e.g. "revision_023". This
> "revision_023" table is then used by the Content model in place of
> "content" on the public site, thus sand-boxing the published content
> from the edited content.
I should prefix my advice by saying that creating non-temporary tables
at runtime is almost always a bad idea. I can see how it seems like a
quick fix, but it will likely bite you later. An alternative is a
simple "revision" column in the content table. To create a new
version, instead of copying the table, you can just copy the rows for
the current version, via something like:
DB[:content].insert([:revision, :column1, :column2, ...],
DB[:content].select(:revision+1, :column1, :column2, ...).
where(:revision=>CURRENT_REVISION))
With either strategy, if you want it affecting the base dataset for
the model, you just do:
# Multiple tables
Content.dataset = DB[:revision_023]
# Single table with revision column
Content.dataset = DB[:content].where(:revision=>23)
If you want to continue using the same identifier hacking, don't
alias, use super:
DB.extend_datasets do
def quote_identifier_append(sql, name)
if name == :content or name == "content"
name = Content.current_revision_table
end
super
end
end
I think a better tactic for that strategy would be to use a custom
object as the FROM table:
crt = Object.new
def crt.sql_literal(ds)
Content.current_revision_table.to_s
end
Content.dataset = DB.from(crt)
> As a system it works really, really well but my current method for
> dynamically changing the table name within a certain context is very
> fragile and very hacky. Basically I have this monkey patch:
This design in general is very fragile and hacky. :)
> Content.dataset #=> #<Sequel::Mysql2::Dataset: "SELECT * FROM
> `content`">
>
> Content.with_revision(23) do
> Content.dataset #=> #<Sequel::Mysql2::Dataset: "SELECT * FROM
> `revision_023`">
>
> Content.with_revision(24) do
> Content.dataset #=> #<Sequel::Mysql2::Dataset: "SELECT * FROM
> `revision_024`">
>
> Content.with_editable do
> Content.dataset #=> #<Sequel::Mysql2::Dataset: "SELECT * FROM
> `content`">
> end
> end
> end
>
> Does anyone know the right way to code this into a self-contained
> Sequel plugin? Any ideas greatly appreciated...
Like I said above, I think it is a bad strategy. However, if you want
to do it anyway, assuming you don't care about threading issues, you
could use the custom FROM table object and do:
class Content
def with_revision(v)
ov = current_revision_table
self.current_revision_table = :"revision_#{sprintf('%03', v)}"
ensure
self.current_revision_table = ov
end
def with_editable
ov = current_revision_table
self.current_revision_table = :content
ensure
self.current_revision_table = ov
end
end
All code above is untested, use at your own risk.
Jeremy
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sequel-talk?hl=en.