From c1854b8b518bde82b80429636f73496a537c3ad5 Mon Sep 17 00:00:00 2001 From: hukl Date: Sun, 1 Feb 2009 21:32:44 +0100 Subject: added first careful steps for aggregation --- app/helpers/content_helper.rb | 23 +++++++++++++++++++++- app/models/page.rb | 35 ++++++++++++++++++++++++++++++++++ app/views/content/_article.html.erb | 6 ++++++ app/views/content/render_page.html.erb | 2 +- 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 app/views/content/_article.html.erb (limited to 'app') diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb index 0e1df66..046a2db 100644 --- a/app/helpers/content_helper.rb +++ b/app/helpers/content_helper.rb @@ -1,8 +1,29 @@ module ContentHelper - # def date_for_page page page.published_at.to_s(:db) rescue page.created_at.to_s(:db) end + def aggregate? content + options = {} + + if content =~ /]*)>/ + tag = $~.to_s + matched_data = $1.scan(/\w+\=\"[a-zA-Z\s\/_\d]*\"/) + + matched_data.each do |data| + splitted_data = data.split("=") + options[splitted_data[0].to_sym] = splitted_data[1].gsub(/\"/, "") + end + end + + content.sub(tag, render_collection(options)) + end + + def render_collection options + render( + :partial => 'content/article', + :collection => Page.aggregate(options) + ) + end end diff --git a/app/models/page.rb b/app/models/page.rb index 0fcb4a8..3d02e9f 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -4,4 +4,39 @@ class Page < ActiveRecord::Base acts_as_list :column => :revision, :scope => :node_id + + # + def self.aggregate options + + defaults = { + :flags => "", + :path => "", + :limit => 20, + :order_by => "id", + :order_direction => "ASC" + } + + options = defaults.merge options + + pages = Page.all( + :limit => options[:limit], + :order => "#{options[:order_by]} #{options[:order_direction]}" + ) + end end + + +named_scope :flagged_as, lambda { |flags| + conditions = {} + flags.each do |flag| + conditions[flag] = true + end + + { :conditions => conditions } +} \ No newline at end of file diff --git a/app/views/content/_article.html.erb b/app/views/content/_article.html.erb new file mode 100644 index 0000000..1e06787 --- /dev/null +++ b/app/views/content/_article.html.erb @@ -0,0 +1,6 @@ +
+
+
+

<%= article.title %>

+

<%= date_for_page article %>, gregoa

+

<%= article.abstract %>

\ No newline at end of file diff --git a/app/views/content/render_page.html.erb b/app/views/content/render_page.html.erb index 311d61d..b70f90e 100644 --- a/app/views/content/render_page.html.erb +++ b/app/views/content/render_page.html.erb @@ -13,5 +13,5 @@

<%= date_for_page @page %>, gregoa


<%= @page.abstract %>

- <%= @page.body %> + <%= aggregate?(@page.body) %> \ No newline at end of file -- cgit v1.3 From 7a5555b1ac542e5fd5680cefaba3574677ecaa46 Mon Sep 17 00:00:00 2001 From: hukl Date: Mon, 2 Feb 2009 00:22:54 +0100 Subject: aggregation spike with flags associated to pages Page has now a named_scope :with_flags which accepts an array of flag names and returns corresponding pages. Can be chained with order and limit --- app/models/flag.rb | 3 +++ app/models/page.rb | 22 +++++++++++----------- db/migrate/20090201211159_create_flags.rb | 13 +++++++++++++ ...0090201211523_add_join_table_for_flags_pages.rb | 15 +++++++++++++++ test/fixtures/flags.yml | 7 +++++++ test/unit/flag_test.rb | 8 ++++++++ 6 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 app/models/flag.rb create mode 100644 db/migrate/20090201211159_create_flags.rb create mode 100644 db/migrate/20090201211523_add_join_table_for_flags_pages.rb create mode 100644 test/fixtures/flags.yml create mode 100644 test/unit/flag_test.rb (limited to 'app') diff --git a/app/models/flag.rb b/app/models/flag.rb new file mode 100644 index 0000000..6d67377 --- /dev/null +++ b/app/models/flag.rb @@ -0,0 +1,3 @@ +class Flag < ActiveRecord::Base + has_and_belongs_to_many :pages +end diff --git a/app/models/page.rb b/app/models/page.rb index 3d02e9f..d5d888f 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -1,9 +1,19 @@ class Page < ActiveRecord::Base belongs_to :node + has_and_belongs_to_many :flags acts_as_list :column => :revision, :scope => :node_id + named_scope :with_flags, lambda {|flag_names| + if (flags = Flag.find_all_by_name(flag_names)).empty? + {} + else + {:include => :flags, :conditions => ['flags_pages.flag_id IN (?)', flags.map(&:id)] } + end + } + + # "#{options[:order_by]} #{options[:order_direction]}" ) end -end - - -named_scope :flagged_as, lambda { |flags| - conditions = {} - flags.each do |flag| - conditions[flag] = true - end - - { :conditions => conditions } -} \ No newline at end of file +end \ No newline at end of file diff --git a/db/migrate/20090201211159_create_flags.rb b/db/migrate/20090201211159_create_flags.rb new file mode 100644 index 0000000..3b9da43 --- /dev/null +++ b/db/migrate/20090201211159_create_flags.rb @@ -0,0 +1,13 @@ +class CreateFlags < ActiveRecord::Migration + def self.up + create_table :flags do |t| + t.string :name + + t.timestamps + end + end + + def self.down + drop_table :flags + end +end diff --git a/db/migrate/20090201211523_add_join_table_for_flags_pages.rb b/db/migrate/20090201211523_add_join_table_for_flags_pages.rb new file mode 100644 index 0000000..99eb9c9 --- /dev/null +++ b/db/migrate/20090201211523_add_join_table_for_flags_pages.rb @@ -0,0 +1,15 @@ +class AddJoinTableForFlagsPages < ActiveRecord::Migration + def self.up + create_table :flags_pages, :id => false do |t| + t.integer :flag_id + t.integer :page_id + end + add_index :flags_pages, [:flag_id] + add_index :flags_pages, [:page_id] + end + + def self.down + remove_table :flags_pages + end + +end diff --git a/test/fixtures/flags.yml b/test/fixtures/flags.yml new file mode 100644 index 0000000..157d747 --- /dev/null +++ b/test/fixtures/flags.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + name: MyString + +two: + name: MyString diff --git a/test/unit/flag_test.rb b/test/unit/flag_test.rb new file mode 100644 index 0000000..49b0d96 --- /dev/null +++ b/test/unit/flag_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class FlagTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end -- cgit v1.3 From 5a8c9154d504c5376e807716c0cfcb76ef766d88 Mon Sep 17 00:00:00 2001 From: hukl Date: Mon, 2 Feb 2009 00:37:42 +0100 Subject: made the whole aggregate helper exception safe by always falling back to the original content if something went wrong. only executing substitution if tag is found --- app/helpers/content_helper.rb | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/helpers/content_helper.rb b/app/helpers/content_helper.rb index 046a2db..3cf3488 100644 --- a/app/helpers/content_helper.rb +++ b/app/helpers/content_helper.rb @@ -7,17 +7,22 @@ module ContentHelper def aggregate? content options = {} - if content =~ /]*)>/ - tag = $~.to_s - matched_data = $1.scan(/\w+\=\"[a-zA-Z\s\/_\d]*\"/) - - matched_data.each do |data| - splitted_data = data.split("=") - options[splitted_data[0].to_sym] = splitted_data[1].gsub(/\"/, "") + begin + if content =~ /]*)>/ + tag = $~.to_s + matched_data = $1.scan(/\w+\=\"[a-zA-Z\s\/_\d]*\"/) + + matched_data.each do |data| + splitted_data = data.split("=") + options[splitted_data[0].to_sym] = splitted_data[1].gsub(/\"/, "") + end + + content.sub(tag, render_collection(options)) end + + rescue + content end - - content.sub(tag, render_collection(options)) end def render_collection options -- cgit v1.3 From d0c3cd743e8500f643ff54b93e4a599c7e16b9d1 Mon Sep 17 00:00:00 2001 From: hukl Date: Mon, 2 Feb 2009 21:02:18 +0100 Subject: more comments with alternate queries --- app/models/page.rb | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/models/page.rb b/app/models/page.rb index d5d888f..fee20a8 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -5,6 +5,24 @@ class Page < ActiveRecord::Base acts_as_list :column => :revision, :scope => :node_id + # Alternativ Queries with one or two inner joins. Loading the Flags themselves + # would be another query. Could be faster on larger data sets. + # + # Single Join: + # + # Page.find( + # :all, + # :joins => 'JOIN flags_pages on pages.id = flags_pages.page_id', + # :include => :flags, + # :conditions => ['flags_pages.flag_id IN (?)', [1,2]] + # ) + # Two inner joins: + # + # Page.find( + # :all, + # :joins => :flags_pages, + # :conditions => ['flags_pages.flag_id IN (?)', [1,2]] + # ) named_scope :with_flags, lambda {|flag_names| if (flags = Flag.find_all_by_name(flag_names)).empty? {} @@ -12,12 +30,9 @@ class Page < ActiveRecord::Base {:include => :flags, :conditions => ['flags_pages.flag_id IN (?)', flags.map(&:id)] } end } - - - + # "", - :path => "", :limit => 20, :order_by => "id", :order_direction => "ASC" @@ -34,7 +48,7 @@ class Page < ActiveRecord::Base options = defaults.merge options - pages = Page.all( + pages = Page.with_flags(options[:flags].split(/\s/)).all( :limit => options[:limit], :order => "#{options[:order_by]} #{options[:order_direction]}" ) -- cgit v1.3