require 'spec_helper' describe SimpleTaggable do describe "including class" do subject { User.new } it { should have_many(:taggings) } it { should have_many(:tags).through(:taggings) } let(:joker1007) { User.create(name: "joker1007") } let(:tag1) { SimpleTaggable::Models::Tag.create(name: "Tag1") } let(:tag2) { SimpleTaggable::Models::Tag.create(name: "Tag2") } describe "Named Scope" do describe ".tagged_with" do let(:joseph) { User.create(name: "joseph") } before do joker1007.tags << [tag1, tag2] joseph.tags << tag2 end it "should return relation which has given tag string" do expect(User.tagged_with("Tag1")).to eq [joker1007] expect(User.tagged_with("Tag2")).to match_array [joker1007, joseph] expect(User.tagged_with("Tag2", "Tag1")).to match_array [joker1007, joseph] expect(User.tagged_with("Tag1", "Tag3")).to eq [joker1007] end context "Given match_all option" do it "should return relation which has given all tag string" do expect(User.tagged_with("Tag2", "Tag1", match_all: true)).to eq [joker1007] expect(User.tagged_with("Tag1", "Tag3", match_all: true)).to be_empty end end context "Given exclude option" do it "should return relation which has no given tag string" do expect(User.tagged_with("Tag1", exclude: true)).to eq [joseph] expect(User.tagged_with("Tag2", exclude: true)).to be_empty expect(User.tagged_with("Tag3", exclude: true)).to match_array [joker1007, joseph] expect(User.tagged_with("Tag1", "Tag3", exclude: true)).to eq [joseph] expect(User.tagged_with("Tag1", "Tag2", exclude: true)).to be_empty expect(User.tagged_with("Tag2", "Tag3", exclude: true)).to be_empty expect(User.tagged_with("Tag1", "Tag2", "Tag3", exclude: true)).to be_empty end end context "Given match_all and exclude" do it "should raise RuntimeError" do expect { User.tagged_with("Tag1", exclude: true, match_all: true) } .to raise_error(RuntimeError) end end end end describe "#tag_list" do before do joker1007.tags << [tag1, tag2] end it "should return TagList that is initialized by self.tags" do reloaded = User.find(joker1007.id) expect(reloaded.tag_list).to match_array SimpleTaggable::TagList.new("Tag1", "Tag2") end describe "filters and converters" do class TagFilteredUser < User add_tag_filter ->(tag_list, tag) { tag != "FILTERED" } add_tag_filter ->(tag_list, tag) { tag != "filtered" } end class TagConvertedUser < User add_tag_filter ->(tag_list, tag) { tag != "FILTERED" } add_tag_converter ->(tag_list, tag) { tag.upcase } add_tag_converter ->(tag_list, tag) { tag.gsub(/foo/i, "BAR") } end class InheritedUser < TagConvertedUser reset_tag_converters add_tag_filter ->(tag_list, tag) { tag != "FILTERED" } add_tag_converter ->(tag_list, tag) { tag.downcase } end class InheritedUser2 < TagConvertedUser end it "use filter given add_tag_filter method, when initialize TagList" do tag_filtered_user = TagFilteredUser.new(name: "jotaro") tag_filtered_user.tag_list.add("Tag1", "FILTERED", "filtered") expect(tag_filtered_user.tag_list).to match_array SimpleTaggable::TagList.new("Tag1") end it "use converter given add_tag_converter method, when initialize TagList" do inherited_user = InheritedUser.new(name: "jotaro") inherited_user.tag_list.add("Tag1", "FILTERED") expect(inherited_user.tag_list).to match_array SimpleTaggable::TagList.new("tag1", "filtered") end it "inherit parent filters and converters" do inherited_user = InheritedUser2.new(name: "jotaro") inherited_user.tag_list.add("Tag1", "FOO") expect(inherited_user.tag_list).to match_array SimpleTaggable::TagList.new("TAG1", "BAR") end end end describe "#tag_list=" do it" should set TagList" do expect(joker1007.tag_list).to be_empty joker1007.tag_list = SimpleTaggable::TagList.new("Tag1") expect(joker1007.tag_list).to match_array SimpleTaggable::TagList.new("Tag1") end it "can receive Array" do expect(joker1007.tag_list).to be_empty joker1007.tag_list = ["Tag1"] expect(joker1007.tag_list).to match_array SimpleTaggable::TagList.new("Tag1") end it "can receive String" do expect(joker1007.tag_list).to be_empty joker1007.tag_list = "Tag1" expect(joker1007.tag_list).to match_array SimpleTaggable::TagList.new("Tag1") end it "raise ArgumentError if given not TagList nor Array object" do expect { joker1007.tag_list = 1 }.to raise_error(TypeError) end end context "After save" do before do joker1007.tags << tag1 joker1007.instance_variable_set("@tag_list", nil) joker1007.tag_list << "Tag2" end it "create new tags included by tag_list" do expect(joker1007.tag_list).to match_array SimpleTaggable::TagList.new("Tag1", "Tag2") expect { joker1007.save! }.to change { joker1007.reload; joker1007.tags.size } .from(1).to(2) end it "delete old tags included by tag_list" do joker1007.tag_list.clear expect(joker1007.tag_list).to be_empty expect { joker1007.save! }.to change { joker1007.reload; joker1007.tags.size } .from(1).to(0) end end end end