Module: Railspress::HasFocalPoint

Extended by:
ActiveSupport::Concern
Included in:
ContentElement, Post
Defined in:
app/models/concerns/railspress/has_focal_point.rb

Instance Method Summary collapse

Instance Method Details

#clear_image_override(context, attachment_name = default_focal_attachment) ⇒ Object

Clear override for context (revert to focal point)



166
167
168
169
# File 'app/models/concerns/railspress/has_focal_point.rb', line 166

def clear_image_override(context, attachment_name = default_focal_attachment)
  fp = send(:"#{attachment_name}_focal_point")
  fp.clear_override(context)
end

#focal_point(attachment_name = default_focal_attachment) ⇒ Hash

Get focal point as hash

Parameters:

  • attachment_name (Symbol) (defaults to: default_focal_attachment)

    Attachment name

Returns:

  • (Hash)

    { x: Float, y: Float }



117
118
119
120
# File 'app/models/concerns/railspress/has_focal_point.rb', line 117

def focal_point(attachment_name = default_focal_attachment)
  fp = send(:"#{attachment_name}_focal_point")
  fp.to_point
end

#focal_point_css(attachment_name = default_focal_attachment) ⇒ String

Get CSS object-position value

Parameters:

  • attachment_name (Symbol) (defaults to: default_focal_attachment)

    Attachment name

Returns:

  • (String)

    CSS property value



127
128
129
130
# File 'app/models/concerns/railspress/has_focal_point.rb', line 127

def focal_point_css(attachment_name = default_focal_attachment)
  fp = send(:"#{attachment_name}_focal_point")
  fp.to_css
end

#has_focal_point?(attachment_name = default_focal_attachment) ⇒ Boolean

Check if focal point differs from center

Returns:

  • (Boolean)


134
135
136
137
# File 'app/models/concerns/railspress/has_focal_point.rb', line 134

def has_focal_point?(attachment_name = default_focal_attachment)
  fp = send(:"#{attachment_name}_focal_point")
  fp.offset_from_center?
end

#has_image_override?(context, attachment_name = default_focal_attachment) ⇒ Boolean

Check if context has custom override (not using focal point)

Returns:

  • (Boolean)


152
153
154
155
# File 'app/models/concerns/railspress/has_focal_point.rb', line 152

def has_image_override?(context, attachment_name = default_focal_attachment)
  fp = send(:"#{attachment_name}_focal_point")
  fp.has_override?(context)
end

#image_css_for(context, attachment_name = default_focal_attachment) ⇒ String

Get CSS for displaying image in a context

Returns object-position CSS for focal point or crop region. Host apps use this with standard Rails image_tag:

<%= image_tag @post.image_for(:hero), style: @post.image_css_for(:hero) %>

Parameters:

  • context (Symbol, String)

    Context name (e.g., :hero, :card)

  • attachment_name (Symbol) (defaults to: default_focal_attachment)

    Attachment name

Returns:

  • (String)

    CSS property value(s)



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'app/models/concerns/railspress/has_focal_point.rb', line 207

def image_css_for(context, attachment_name = default_focal_attachment)
  override = image_override(context, attachment_name)

  case override&.dig(:type)
  when "crop"
    # Custom crop region - calculate center of crop for object-position
    region = override[:region]&.with_indifferent_access
    if region
      x_offset = (region[:x].to_f + region[:width].to_f / 2) * 100
      y_offset = (region[:y].to_f + region[:height].to_f / 2) * 100
      "object-position: #{x_offset.round(1)}% #{y_offset.round(1)}%"
    else
      focal_point_css(attachment_name)
    end
  when "upload"
    # Custom upload - center it (no focal point data for uploaded images)
    "object-position: 50% 50%"
  else
    # Default: use focal point
    focal_point_css(attachment_name)
  end
end

#image_for(context, attachment_name = default_focal_attachment) ⇒ ActiveStorage::Attached, ActiveStorage::Blob

Get the appropriate image for a context

Returns the original attachment or a custom uploaded blob. Host apps use this with standard Rails image_tag:

<%= image_tag @post.image_for(:hero), style: @post.image_css_for(:hero) %>

Parameters:

  • context (Symbol, String)

    Context name (e.g., :hero, :card)

  • attachment_name (Symbol) (defaults to: default_focal_attachment)

    Attachment name

Returns:

  • (ActiveStorage::Attached, ActiveStorage::Blob)

    The image to display



182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'app/models/concerns/railspress/has_focal_point.rb', line 182

def image_for(context, attachment_name = default_focal_attachment)
  override = image_override(context, attachment_name)

  if override&.dig(:type) == "upload" && override[:blob_signed_id].present?
    begin
      ActiveStorage::Blob.find_signed!(override[:blob_signed_id])
    rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveRecord::RecordNotFound
      send(attachment_name) # Fallback to original if blob not found
    end
  else
    send(attachment_name)
  end
end

#image_override(context, attachment_name = default_focal_attachment) ⇒ Hash?

Get override for specific context

Parameters:

  • context (Symbol, String)

    Context name (e.g., :hero, :card)

  • attachment_name (Symbol) (defaults to: default_focal_attachment)

    Attachment name

Returns:

  • (Hash, nil)

    Override data or nil



145
146
147
148
# File 'app/models/concerns/railspress/has_focal_point.rb', line 145

def image_override(context, attachment_name = default_focal_attachment)
  fp = send(:"#{attachment_name}_focal_point")
  fp.override_for(context)
end

#reset_focal_point!(attachment_name = default_focal_attachment) ⇒ Object

Reset focal point to center



232
233
234
235
# File 'app/models/concerns/railspress/has_focal_point.rb', line 232

def reset_focal_point!(attachment_name = default_focal_attachment)
  fp = send(:"#{attachment_name}_focal_point")
  fp.reset!
end

#set_image_override(context, data, attachment_name = default_focal_attachment) ⇒ Object

Set override for context



159
160
161
162
# File 'app/models/concerns/railspress/has_focal_point.rb', line 159

def set_image_override(context, data, attachment_name = default_focal_attachment)
  fp = send(:"#{attachment_name}_focal_point")
  fp.set_override(context, data)
end