Merge pull request #6921 from SuperTux88/cleanup-status_message

Cleanup StatusMessage
This commit is contained in:
Jonne Haß 2016-07-17 09:27:00 +02:00
commit 3281f2a72d
No known key found for this signature in database
GPG key ID: F347E0EB47AC70D6
13 changed files with 79 additions and 90 deletions

View file

@ -112,6 +112,7 @@ before.
* Use Poltergeist instead of Selenium [#6768](https://github.com/diaspora/diaspora/pull/6768) * Use Poltergeist instead of Selenium [#6768](https://github.com/diaspora/diaspora/pull/6768)
* Redesigned the landing page and added dedicated notes for podmins [#6268](https://github.com/diaspora/diaspora/pull/6268) * Redesigned the landing page and added dedicated notes for podmins [#6268](https://github.com/diaspora/diaspora/pull/6268)
* Moved the entire federation implementation into its own gem. 🎉 [#6873](https://github.com/diaspora/diaspora/pull/6873) * Moved the entire federation implementation into its own gem. 🎉 [#6873](https://github.com/diaspora/diaspora/pull/6873)
* Remove `StatusMessage#raw_message` [#6921](https://github.com/diaspora/diaspora/pull/6921)
## Bug fixes ## Bug fixes
* Destroy Participation when removing interactions with a post [#5852](https://github.com/diaspora/diaspora/pull/5852) * Destroy Participation when removing interactions with a post [#5852](https://github.com/diaspora/diaspora/pull/5852)

View file

@ -59,7 +59,6 @@ class Post < ActiveRecord::Base
end end
def root; end def root; end
def raw_message; ""; end
def mentioned_people; []; end def mentioned_people; []; end
def photos; []; end def photos; []; end

View file

@ -29,8 +29,8 @@ class Reshare < Post
:message, :nsfw, :message, :nsfw,
to: :absolute_root, allow_nil: true to: :absolute_root, allow_nil: true
def raw_message def text
absolute_root.try(:raw_message) || super absolute_root.try(:text) || ""
end end
def mentioned_people def mentioned_people

View file

@ -8,23 +8,18 @@ class StatusMessage < Post
include PeopleHelper include PeopleHelper
acts_as_taggable_on :tags acts_as_taggable_on :tags
extract_tags_from :raw_message extract_tags_from :text
validates_length_of :text, :maximum => 65535, :message => proc {|p, v| I18n.t('status_messages.too_long', :count => 65535, :current_length => v[:value].length)} validates_length_of :text, :maximum => 65535, :message => proc {|p, v| I18n.t('status_messages.too_long', :count => 65535, :current_length => v[:value].length)}
# don't allow creation of empty status messages # don't allow creation of empty status messages
validate :presence_of_content, on: :create, if: proc {|sm| sm.author && sm.author.local? } validate :presence_of_content, on: :create
has_many :photos, :dependent => :destroy, :foreign_key => :status_message_guid, :primary_key => :guid has_many :photos, :dependent => :destroy, :foreign_key => :status_message_guid, :primary_key => :guid
has_one :location has_one :location
has_one :poll, autosave: true has_one :poll, autosave: true
# a StatusMessage is federated before its photos are so presence_of_content() fails erroneously if no text is present
# therefore, we put the validation in a before_destory callback instead of a validation
before_destroy :absence_of_content
attr_accessor :oembed_url attr_accessor :oembed_url
attr_accessor :open_graph_url attr_accessor :open_graph_url
@ -42,29 +37,23 @@ class StatusMessage < Post
end end
def self.user_tag_stream(user, tag_ids) def self.user_tag_stream(user, tag_ids)
owned_or_visible_by_user(user). owned_or_visible_by_user(user).tag_stream(tag_ids)
tag_stream(tag_ids)
end end
def self.public_tag_stream(tag_ids) def self.public_tag_stream(tag_ids)
all_public. all_public.tag_stream(tag_ids)
tag_stream(tag_ids)
end end
def raw_message def self.tag_stream(tag_ids)
read_attribute(:text) || "" joins(:taggings).where("taggings.tag_id IN (?)", tag_ids)
end
def raw_message=(text)
write_attribute(:text, text)
end end
def nsfw def nsfw
self.raw_message.match(/#nsfw/i) || super text.try(:match, /#nsfw/i) || super
end end
def message def message
@message ||= Diaspora::MessageRenderer.new raw_message, mentioned_people: mentioned_people @message ||= Diaspora::MessageRenderer.new(text, mentioned_people: mentioned_people)
end end
def mentioned_people def mentioned_people
@ -72,7 +61,7 @@ class StatusMessage < Post
create_mentions if self.mentions.empty? create_mentions if self.mentions.empty?
self.mentions.includes(:person => :profile).map{ |mention| mention.person } self.mentions.includes(:person => :profile).map{ |mention| mention.person }
else else
Diaspora::Mentionable.people_from_string(self.raw_message) Diaspora::Mentionable.people_from_string(text)
end end
end end
@ -84,7 +73,7 @@ class StatusMessage < Post
## ---- ---- ## ---- ----
def create_mentions def create_mentions
ppl = Diaspora::Mentionable.people_from_string(self.raw_message) ppl = Diaspora::Mentionable.people_from_string(text)
ppl.each do |person| ppl.each do |person|
self.mentions.find_or_create_by(person_id: person.id) self.mentions.find_or_create_by(person_id: person.id)
end end
@ -103,7 +92,7 @@ class StatusMessage < Post
end end
def text_and_photos_blank? def text_and_photos_blank?
self.raw_message.blank? && self.photos.blank? text.blank? && photos.blank?
end end
def queue_gather_oembed_data def queue_gather_oembed_data
@ -132,22 +121,10 @@ class StatusMessage < Post
} }
end end
protected
def presence_of_content
if text_and_photos_blank?
errors[:base] << "Cannot create a StatusMessage without content"
end
end
def absence_of_content
unless text_and_photos_blank?
errors[:base] << "Cannot destory a StatusMessage with text and/or photos present"
end
end
private private
def self.tag_stream(tag_ids)
joins(:taggings).where('taggings.tag_id IN (?)', tag_ids) def presence_of_content
errors[:base] << "Cannot create a StatusMessage without content" if text_and_photos_blank?
end end
end end

View file

@ -42,7 +42,7 @@ class PostPresenter < BasePresenter
if @post.message if @post.message
@post.message.plain_text_for_json @post.message.plain_text_for_json
else else
@post.raw_message @post.text
end end
end end

View file

@ -222,7 +222,7 @@ module Diaspora
DiasporaFederation::Entities::StatusMessage.new( DiasporaFederation::Entities::StatusMessage.new(
author: status_message.diaspora_handle, author: status_message.diaspora_handle,
guid: status_message.guid, guid: status_message.guid,
text: status_message.raw_message, text: status_message.text,
photos: status_message.photos.map {|photo| photo(photo) }, photos: status_message.photos.map {|photo| photo(photo) },
location: status_message.location ? location(status_message.location) : nil, location: status_message.location ? location(status_message.location) : nil,
poll: status_message.poll ? poll(status_message.poll) : nil, poll: status_message.poll ? poll(status_message.poll) : nil,

View file

@ -161,9 +161,20 @@ module Diaspora
end end
def self.status_message(entity) def self.status_message(entity)
save_status_message(entity).tap do try_load_existing_guid(StatusMessage, entity.guid, author_of(entity)) do
entity.photos.map do |photo| StatusMessage.new(
ignore_existing_guid(Photo, photo.guid, author_of(photo)) { save_photo(photo) } author: author_of(entity),
guid: entity.guid,
text: entity.text,
public: entity.public,
created_at: entity.created_at,
provider_display_name: entity.provider_display_name
).tap do |status_message|
status_message.location = build_location(entity.location) if entity.location
status_message.poll = build_poll(entity.poll) if entity.poll
status_message.photos = save_or_load_photos(entity.photos)
status_message.save!
end end
end end
end end
@ -228,6 +239,12 @@ module Diaspora
) )
end end
private_class_method def self.save_or_load_photos(photos)
photos.map do |photo|
try_load_existing_guid(Photo, photo.guid, author_of(photo)) { save_photo(photo) }
end
end
private_class_method def self.receive_relayable(klass, entity) private_class_method def self.receive_relayable(klass, entity)
save_relayable(klass, entity) { yield }.tap {|relayable| relay_relayable(relayable) if relayable } save_relayable(klass, entity) { yield }.tap {|relayable| relay_relayable(relayable) if relayable }
end end
@ -243,24 +260,6 @@ module Diaspora
end end
end end
private_class_method def self.save_status_message(entity)
try_load_existing_guid(StatusMessage, entity.guid, author_of(entity)) do
StatusMessage.new(
author: author_of(entity),
guid: entity.guid,
raw_message: entity.text,
public: entity.public,
created_at: entity.created_at,
provider_display_name: entity.provider_display_name
).tap do |status_message|
status_message.location = build_location(entity.location) if entity.location
status_message.poll = build_poll(entity.poll) if entity.poll
status_message.save!
end
end
end
private_class_method def self.retract_if_author_ignored(relayable) private_class_method def self.retract_if_author_ignored(relayable)
parent_author = relayable.parent.author.owner parent_author = relayable.parent.author.owner
return unless parent_author && parent_author.ignored_people.include?(relayable.author) return unless parent_author && parent_author.ignored_people.include?(relayable.author)

View file

@ -120,7 +120,7 @@ module Diaspora
delegate :empty?, :blank?, :present?, to: :raw delegate :empty?, :blank?, :present?, to: :raw
# @param [String] raw_message Raw input text # @param [String] text Raw input text
# @param [Hash] opts Global options affecting output # @param [Hash] opts Global options affecting output
# @option opts [Array<Person>] :mentioned_people ([]) List of people # @option opts [Array<Person>] :mentioned_people ([]) List of people
# allowed to mention # allowed to mention
@ -147,8 +147,8 @@ module Diaspora
# to Redcarpet # to Redcarpet
# @option opts [Hash] :markdown_render_options Override default options # @option opts [Hash] :markdown_render_options Override default options
# passed to the Redcarpet renderer # passed to the Redcarpet renderer
def initialize raw_message, opts={} def initialize(text, opts={})
@raw_message = raw_message @text = text
@options = DEFAULTS.deep_merge opts @options = DEFAULTS.deep_merge opts
end end
@ -211,12 +211,12 @@ module Diaspora
# this length. If not given defaults to 70. # this length. If not given defaults to 70.
def title opts={} def title opts={}
# Setext-style header # Setext-style header
heading = if /\A(?<setext_content>.{1,200})\n(?:={1,200}|-{1,200})(?:\r?\n|$)/ =~ @raw_message.lstrip heading = if /\A(?<setext_content>.{1,200})\n(?:={1,200}|-{1,200})(?:\r?\n|$)/ =~ @text.lstrip
setext_content setext_content
# Atx-style header # Atx-style header
elsif /\A\#{1,6}\s+(?<atx_content>.{1,200}?)(?:\s+#+)?(?:\r?\n|$)/ =~ @raw_message.lstrip elsif /\A\#{1,6}\s+(?<atx_content>.{1,200}?)(?:\s+#+)?(?:\r?\n|$)/ =~ @text.lstrip
atx_content atx_content
end end
heading &&= self.class.new(heading).plain_text_without_markdown heading &&= self.class.new(heading).plain_text_without_markdown
@ -236,7 +236,7 @@ module Diaspora
end end
def raw def raw
@raw_message @text
end end
def to_s def to_s
@ -245,8 +245,8 @@ module Diaspora
private private
def process opts, &block def process(opts, &block)
Processor.process(@raw_message, @options.deep_merge(opts), &block) Processor.process(@text, @options.deep_merge(opts), &block)
end end
end end
end end

View file

@ -61,7 +61,7 @@ describe UsersController, :type => :controller do
it 'renders xml if atom is requested' do it 'renders xml if atom is requested' do
sm = FactoryGirl.create(:status_message, :public => true, :author => @user.person) sm = FactoryGirl.create(:status_message, :public => true, :author => @user.person)
get :public, :username => @user.username, :format => :atom get :public, :username => @user.username, :format => :atom
expect(response.body).to include(sm.raw_message) expect(response.body).to include(sm.text)
end end
it 'renders xml if atom is requested with clickalbe urls' do it 'renders xml if atom is requested with clickalbe urls' do
@ -77,7 +77,7 @@ describe UsersController, :type => :controller do
it 'includes reshares in the atom feed' do it 'includes reshares in the atom feed' do
reshare = FactoryGirl.create(:reshare, :author => @user.person) reshare = FactoryGirl.create(:reshare, :author => @user.person)
get :public, :username => @user.username, :format => :atom get :public, :username => @user.username, :format => :atom
expect(response.body).to include reshare.root.raw_message expect(response.body).to include reshare.root.text
end end
it 'do not show reshares in atom feed if origin post is deleted' do it 'do not show reshares in atom feed if origin post is deleted' do

View file

@ -591,6 +591,19 @@ describe Diaspora::Federation::Receive do
expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid) expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid)
end end
it "receives a status message only with photos and without text" do
entity = DiasporaFederation::Entities::StatusMessage.new(status_message_entity.to_h.merge(text: nil))
received = Diaspora::Federation::Receive.perform(entity)
status_message = StatusMessage.find_by!(guid: status_message_entity.guid)
expect(received).to eq(status_message)
expect(status_message.author).to eq(sender)
expect(status_message.text).to be_nil
expect(status_message.photos.map(&:guid)).to include(photo1.guid, photo2.guid)
end
it "does not overwrite the photos if they already exist" do it "does not overwrite the photos if they already exist" do
received_photo = Diaspora::Federation::Receive.photo(photo1) received_photo = Diaspora::Federation::Receive.photo(photo1)
received_photo.text = "foobar" received_photo.text = "foobar"

View file

@ -122,10 +122,10 @@ describe Diaspora::Fetcher::Public do
end end
end end
it 'copied the text correctly' do it "copied the text correctly" do
@data.each do |post| @data.each do |post|
entry = StatusMessage.find_by_guid(post['guid']) entry = StatusMessage.find_by_guid(post["guid"])
expect(entry.raw_message).to eql(post['text']) expect(entry.text).to eql(post["text"])
end end
end end

View file

@ -24,7 +24,7 @@ STR
describe "#format" do describe "#format" do
context "html output" do context "html output" do
it "adds the links to the formatted message" do it "adds the links to the formatted message" do
fmt_msg = Diaspora::Mentionable.format(@status_msg.raw_message, @people) fmt_msg = Diaspora::Mentionable.format(@status_msg.text, @people)
@people.each do |person| @people.each do |person|
expect(fmt_msg).to include person_link(person, class: "mention hovercardable") expect(fmt_msg).to include person_link(person, class: "mention hovercardable")
@ -32,7 +32,7 @@ STR
end end
it "should work correct when message is escaped html" do it "should work correct when message is escaped html" do
raw_msg = @status_msg.raw_message raw_msg = @status_msg.text
fmt_msg = Diaspora::Mentionable.format(CGI.escapeHTML(raw_msg), @people) fmt_msg = Diaspora::Mentionable.format(CGI.escapeHTML(raw_msg), @people)
@people.each do |person| @people.each do |person|
@ -45,7 +45,7 @@ STR
p.first_name = "</a><script>alert('h')</script>" p.first_name = "</a><script>alert('h')</script>"
p.save! p.save!
fmt_msg = Diaspora::Mentionable.format(@status_msg.raw_message, @people) fmt_msg = Diaspora::Mentionable.format(@status_msg.text, @people)
expect(fmt_msg).not_to include(p.first_name) expect(fmt_msg).not_to include(p.first_name)
expect(fmt_msg).to include("&gt;", "&lt;", "&#39;") # ">", "<", "'" expect(fmt_msg).to include("&gt;", "&lt;", "&#39;") # ">", "<", "'"
@ -54,7 +54,7 @@ STR
context "plain text output" do context "plain text output" do
it "removes mention markup and displays unformatted name" do it "removes mention markup and displays unformatted name" do
fmt_msg = Diaspora::Mentionable.format(@status_msg.raw_message, @people, plain_text: true) fmt_msg = Diaspora::Mentionable.format(@status_msg.text, @people, plain_text: true)
@people.each do |person| @people.each do |person|
expect(fmt_msg).to include person.first_name expect(fmt_msg).to include person.first_name
@ -64,7 +64,7 @@ STR
end end
it "leaves the name of people that cannot be found" do it "leaves the name of people that cannot be found" do
fmt_msg = Diaspora::Mentionable.format(@status_msg.raw_message, []) fmt_msg = Diaspora::Mentionable.format(@status_msg.text, [])
expect(fmt_msg).to eql @test_txt_plain expect(fmt_msg).to eql @test_txt_plain
end end
end end

View file

@ -91,7 +91,7 @@ describe StatusMessage, type: :model do
end end
end end
context "emptyness" do context "emptiness" do
it "needs either a message or at least one photo" do it "needs either a message or at least one photo" do
post = user.build_post(:status_message, text: nil) post = user.build_post(:status_message, text: nil)
expect(post).not_to be_valid expect(post).not_to be_valid
@ -109,14 +109,14 @@ describe StatusMessage, type: :model do
post.photos << photo post.photos << photo
expect(post).to be_valid expect(post).to be_valid
expect(post.message.to_s).to be_empty expect(post.message.to_s).to be_empty
expect(post.raw_message).to eq "" expect(post.text).to be_nil
expect(post.nsfw).to be_falsy expect(post.nsfw).to be_falsey
expect(post.errors.full_messages).to eq([]) expect(post.errors.full_messages).to eq([])
end end
it "doesn't check for content when author is remote (federation...)" do it "also checks for content when author is remote" do
post = FactoryGirl.build(:status_message, text: nil) post = FactoryGirl.build(:status_message, text: nil)
expect(post).to be_valid expect(post).not_to be_valid
end end
end end