Skip to content

Fix/image order #497

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Fix/image order #497

wants to merge 8 commits into from

Conversation

knzwats
Copy link

@knzwats knzwats commented Mar 1, 2019

Summary

If there is a sheet without any images attached, indices for image files are messed up and crammed.

I had to have a proper sheet indices as a hash and later refer to it to correctly resolve the sheet that the image belongs.

My code might look wonky but it works!

here's the rake test result:

Finished in 9.867465s, 16.9243 runs/s, 222.4482 assertions/s.

167 runs, 2195 assertions, 0 failures, 0 errors, 7 skips

You have skipped tests. Run with --verbose for details.
Coverage report generated for Unit Tests to /Users/atsushikanazawa/Projects/roo/coverage. 1656 / 1898 LOC (87.25%) covered.

my evnviroinments are:

System Version: macOS 10.14 (18A391)
Kernel Version: Darwin 18.0.0

ruby version:

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin18]

Microsoft excel version:

Version 16.22 (190211) 

Other Information

I attached an excel file that contains 2 kangaroos on sheet 1 and 3.
If you run it with older code, it tells you that sheet 1 and 2 have kangaroos.

Copy link
Member

@chopraanmol1 chopraanmol1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for opening this PR. I think we should handle mapping logic in Roo::Excelx::Sheet and Roo::Excelx::Relationships.

  1. Roo::Excelx::Relationships : Add new method to filter based on type. Similar to

    def include_type?(type)
    to_a.any? do |_, rel|
    rel["Type"]&.include? type
    end
    end

  2. Roo::Excelx::Sheet : Add images method to lazy load following

    @images = Images.new(image_rels[sheet_index]).list
    while retreiving mapping details from @rels

  3. Move kangaroos.xlsx file to test/files folder. As we ignore test/files while building gem to reduce size.

    spec.files.reject! { |fn| fn.include?('test/files') }

@@ -0,0 +1,11 @@
require "test_helper"
require 'pry'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@knzwats
Copy link
Author

knzwats commented Mar 1, 2019

will do, thanks!

- created a method that returns "Target" attribute based on passed type
- created "images" method on sheet class, that resolves the correct index by said "Target" attribute and regex
- moved excel file to test/files
- changed test file name because this is about indices of images, not ordering
@knzwats
Copy link
Author

knzwats commented Mar 1, 2019

I fixed the code!

But I want to elaborate test cases a little bit more when I get to office(I don't have Excel installed on any of my cumputers thus cannot modify excel files at home).

Any test scenarios do you have in your mind?
Thanks!

@coveralls
Copy link

coveralls commented Mar 1, 2019

Coverage Status

Coverage increased (+0.05%) to 94.418% when pulling a16ab56 on knzwats:fix/image_order into 4ec1104 on roo-rb:master.

@@ -19,6 +19,12 @@ def include_type?(type)
end
end

def target(type)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

target is a confusing name for what this method is doing.

We also need relevant test cases for the newly added method.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name should signify that we are returning target(s) while filtering relations on Type attribute. If it doesn't signify the above then it is confusing in nature.

@@ -96,6 +93,16 @@ def dimensions
@sheet.dimensions
end

def images
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method should be memoized.

def images
  @images ||= begin
     ...
  end
end

def images
target = @rels.target("drawing")
match = /[a-zA-Z]+([0-9]+).xml/.match target
if match
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this condition? Images class already handles nil as file_path

@@ -455,7 +455,6 @@ def process_zipfile_entries(entries)
nr = Regexp.last_match[1].to_i
image_rels[nr - 1] = "#{@tmpdir}/roo_image_rels#{nr}"
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert unnecessary cosmetic changes

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry about that

@knzwats knzwats changed the title Fix/image order [WIP]Fix/image order Mar 14, 2019
- sort the images hash because its order was messed up too
- added new test case which tests the said order
@knzwats
Copy link
Author

knzwats commented Mar 14, 2019

Fixed!

But I have few questions.

I just noticed the order of image resources are like this if you have multiple images:

{"rId3"=>"roo_media_image3.jpeg", "rId2"=>"roo_media_image2.jpeg", "rId1"=>"roo_media_image1.jpeg", "rId4"=>"roo_media_image4.jpeg"}

It looks like it's random and I thought we'd better sort it by its number, so I coded just so it does.
Sorting a hash does not make much sense, but sheet#images method is only used inside excelx#images as far as I grepped, and keys are discarded so it is effectively an array, because keys are not exposed anyway:

def images(sheet = nil)
  images_names = sheet_for(sheet).images.map(&:last)
  images_names.map { |iname| image_files.find { |ifile| ifile[iname] } }
end

I bumped into this problem in my job and sorted images based on its names outside of roo.
Do you think sorting is necessary?

And I'd love to write some tests on relationship#filter_by_type method.
Should I add new test method to roo/excelx/relationships_spec.rb or create a brand new testcase?
Is there any excelx file or specific scenario to test relationship#filter_by_type in your mind because I do not know roo's internal design or its edge cases.

Thanks!
@chopraanmol1

@knzwats knzwats changed the title [WIP]Fix/image order Fix/image order Mar 14, 2019
@knzwats
Copy link
Author

knzwats commented Apr 2, 2019

hello?

@rels.filter_by_type(type: "drawing").map do |target|
match = /[a-zA-Z]+([0-9]+).xml/.match target
Images.new(image_rels[match[1].to_i - 1]).list
end.reduce({}, :merge).sort.to_h
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if it fails?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants