Running with Ruby

Tag: Rails (page 2 of 59)

[ActiveRecord] Get a polymorphic owner class out of the owned object

The question is: how can we retrieve a owners class of a polymorphic association without loading the owner object into memory?

class Source < ApplicationRecord
  self.has_one :state,
    dependent: :delete,
    as: :stateable

class State < ApplicationRecord
  belongs_to :stateable,
    polymorphic: true


There are (at least) two ways to do this. First one is not recommended (as it might fail with multiple namespaces with same class names, etc:

State.last.stateable_type.constantize #=> Source

or a better one that will work out of any scope:

State.last.association(:stateable).klass #=> Source

Trailblazer + Devise: Integrating Devise validatable model with Trailblazer operation + error propagation

Devise is one of those gems that are tightly bound to the Rails stack. It means that as long as you follow the “Rails way” and you do things the recommended way, you should not have any problems.

However, Trailblazer is not the recommended way and the way it works, not always makes it painless to integrate with external gems (note: it’s not a Trailblazer fault, more often poorly designed external gems). Unfortunately Devise is one of those libraries. Models have validations, things happen magically in the controllers and so on.

Most of the time, you can leave it that way, as the scope of what Devise does is pretty isolated (authentication + authorization). But what if you want to integrate it with Trailblazer, for example to provide a custom built password change page? You can do this by following those steps

  • Provide a contract with similar (or the same) validation rules as Devise (this will make it easier to migrate if you decide to drop model validations)
  • Create an operation that will save the contract and propagate changes to the model
  • Copy model errors (if any) into contract errors

Here’s the code you need (I removed more complex validation rules to simplify things):

# Contract object
class Contracts::Update < Reform::Form
  include Reform::Form::ActiveRecord
  # Devise validatable model
  model User

  property :password
  property :password_confirmation

  validates :password,
    presence: true,
    confirmation: true
  validates :password_confirmation,
    presence: true

Operation is fairly simple as well:

class Operations::Update < Trailblazer::Operation
  include Trailblazer::Operation::Model
  contract Contracts::Update
  # Devise validatable model
  model User

  def process(params)
    validate(params[:user]) do
      # When our validations passes, we can try to save contract do |hash|
        # update our user instance
        # and propagate any model based errors to our contract and operation
        model.errors.each { |name, desc| errors.add(name, desc) }

And the best part – controller:

class PasswordsController < BaseController
  def edit
    respond_with(form Operations::Update)

  def update
    respond_with(run Operations::Update)
Olderposts Newerposts

Copyright © 2017 Running with Ruby

Theme by Anders NorenUp ↑