Skip to content

Commit

Permalink
Adding belongs_to associations
Browse files Browse the repository at this point in the history
  • Loading branch information
jgdavey committed Nov 16, 2009
1 parent 6106473 commit ec28b4b
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 15 deletions.
26 changes: 20 additions & 6 deletions lib/tabletastic.rb
Expand Up @@ -14,6 +14,7 @@ def get_id_for(collection)
end

class TableBuilder
@@association_methods = %w[to_label display_name full_name name title username login value to_s]

def initialize(collection, template)
@collection, @template = collection, template
Expand Down Expand Up @@ -66,7 +67,14 @@ def tds_for_row(record)
end

def cell_for(record, method_or_attribute)
record.send(method_or_attribute)
result = record.send(method_or_attribute)
return result if result.is_a?(String)
to_string = detect_string_method(result)
result.send(to_string) if to_string
end

def detect_string_method(association)
@@association_methods.detect { |method| association.respond_to?(method) }
end

def cell(method_or_attribute)
Expand All @@ -80,16 +88,22 @@ def fields
if @collection.empty?
@fields = []
else
@fields = @collection.first.class.content_columns.map(&:name)
object = @collection.first
associations = object.class.reflect_on_all_associations(:belongs_to) if object.class.respond_to?(:reflect_on_all_associations)
@fields = object.class.content_columns.map(&:name)
if associations
associations = associations.map(&:name)
@fields += associations
end
@fields -= %w[created_at updated_at created_on updated_on lock_version version]
@fields.map!(&:to_sym)
end
end

private

def content_tag(name, content = nil, options = nil, escape = true, &block)
@template.content_tag(name, content, options, escape, &block)
end
def content_tag(name, content = nil, options = nil, escape = true, &block)
@template.content_tag(name, content, options, escape, &block)
end
end
end
end
31 changes: 31 additions & 0 deletions spec/spec_helper.rb
Expand Up @@ -59,13 +59,44 @@ class ::Post
def id
end
end
class ::Author
end

def mock_everything
# Sometimes we need a mock @post object and some Authors for belongs_to
@post = mock('post')
@post.stub!(:class).and_return(::Post)
@post.stub!(:id).and_return(nil)
@post.stub!(:author)
::Post.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
::Post.stub!(:human_name).and_return('Post')

@fred = mock('user')
@fred.stub!(:class).and_return(::Author)
@fred.stub!(:name).and_return('Fred Smith')
@fred.stub!(:id).and_return(37)

::Author.stub!(:find).and_return([@fred])
::Author.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
::Author.stub!(:human_name).and_return('Author')
::Author.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :options => {}, :klass => Post, :macro => :has_many) if column_name == :posts }

@freds_post = mock('post')
@freds_post.stub!(:class).and_return(::Post)
@freds_post.stub!(:title).and_return('Fred\'s Post')
@freds_post.stub!(:body)
@freds_post.stub!(:id).and_return(19)
@freds_post.stub!(:author).and_return(@fred)
@freds_post.stub!(:author_id).and_return(@fred.id)
@fred.stub!(:posts).and_return([@freds_post])
@fred.stub!(:post_ids).and_return([@freds_post.id])

@mock_reflection_belongs_to_author = mock('reflection', :options => {}, :name => :author, :klass => ::Author, :macro => :belongs_to)

::Post.stub!(:reflect_on_association).and_return do |column_name|
@mock_reflection_belongs_to_author if column_name == :author
end

::Post.stub!(:reflect_on_all_associations).with(:belongs_to).and_return([])
end
end
56 changes: 47 additions & 9 deletions spec/tabletastic_spec.rb
Expand Up @@ -114,6 +114,19 @@
output_buffer.should have_table_with_tag("tr.odd")
output_buffer.should have_table_with_tag("tr.even")
end

context "when collection has associations" do
it "should handle belongs_to associations" do
::Post.stub!(:reflect_on_all_associations).with(:belongs_to).and_return([@mock_reflection_belongs_to_author])
@posts = [@freds_post]
@output_buffer = ""
table_for(@posts) do |t|
concat(t.data)
end
output_buffer.should have_table_with_tag("th", "Author")
output_buffer.should have_table_with_tag("td", "Fred Smith")
end
end
end

context "with a list of attributes" do
Expand All @@ -132,19 +145,44 @@
end

context "with a block" do
before do
table_for(@posts) do |t|
t.data do
concat(t.cell(:title))
concat(t.cell(:body))
context "and normal columns" do
before do
table_for(@posts) do |t|
t.data do
concat(t.cell(:title))
concat(t.cell(:body))
end
end
end

it "should include the data for the fields passed in" do
output_buffer.should have_table_with_tag("th", "Title")
output_buffer.should have_tag("td", "The title of the post")
output_buffer.should have_tag("td", "Lorem ipsum")
end
end

it "should include the data for the fields passed in" do
output_buffer.should have_table_with_tag("th", "Title")
output_buffer.should have_tag("td", "The title of the post")
output_buffer.should have_tag("td", "Lorem ipsum")
context "and normal/association columns" do
before do
::Post.stub!(:reflect_on_all_associations).with(:belongs_to).and_return([@mock_reflection_belongs_to_author])
@posts = [@freds_post]
table_for(@posts) do |t|
t.data do
concat(t.cell(:title))
concat(t.cell(:author))
end
end
end

it "should include normal columns" do
output_buffer.should have_table_with_tag("th:nth-child(1)", "Title")
output_buffer.should have_table_with_tag("td:nth-child(1)", "Fred's Post")
end

it "should include belongs_to associations" do
output_buffer.should have_table_with_tag("th:nth-child(2)", "Author")
output_buffer.should have_table_with_tag("td:nth-child(2)", "Fred Smith")
end
end
end
end
Expand Down

0 comments on commit ec28b4b

Please sign in to comment.