Design rubies on rails

Sorry in advance for the long post. I've been working in Ruby on Rails for about 6 months and am trying to apply design patterns from java / C # to problems in RoR. I feel like there are better ways to do the same in RoR, but unfortunately I'm just a noob. So here is one of the main problems I am trying to find a Ruby oriented pattern for. Any guidance would be much appreciated.

There is a lot of "common" behavior in my application controllers. In many cases, there is controller-specific initialization (i.e. setting the user_id attribute of the object for the current user, filtering the write-once attributes) and authorizing actions based on the object instance and the current user. Thus, many models and controllers look something like this:

class Object < ActiveRecord::Base

  ...

  def authorize_action(user, action)
    [:show,:create].include?(action) || self.created_by_user_id == user.id # only the user who created can update/delete
  end

  def init_new(signed_in_user)
    self.created_by_user_id = signed_in_user.id
    if self.location_id.nil?
      self.location_id = signed_in_user.default_location_id
    end
  end

end


ObjectController < ApplicationController

  before_action :set_object, only: [:show, :edit, :update, :destroy]
  before_action :authorize_action, only: [:show, :edit, :update, :destroy]
  ...

  def new
    @object = Object.new
    @object.parent_id = params[:parent_id] # nested resource, assign parent_id from request url
    @object.created_by_user_id = current_user.id
  end

  def edit
  end

  def create
    @object  = Object.new(object_create_params)
    @object.parent_id = params[:parent_id] # nested resource, assign parent_id from request url
    @object.created_by_user_id = current_user.id
    @object.save
  end

  def update
    @hunting_plot_user_access.update(object_update_params)
  end

  def destroy
    @object.destroy
  end

  private

  set_object
    @object = Object.find(params[:id])
  end

  def object_create_params
    params.require(:object).permit(:location_id, :attribute_1, :attribute_2)
  end

  def object_update_params
    params.require(:object).permit(:attribute_1, :attribute_2)
  end

  def authorize_action
    raise Exceptions::NotAuthorized unless @object.authorize_action?(current_user, action_name)        
  end

end

      

I would like to move the general "flow" of each general activity into the general logic. For example, to create a new instance of any given object, the controller must instantiate, call the init_new method on the instance (all models have this method), potentially use controller-specific changes, allow the action, and save the object to the instance.

I must think this is a fairly common design problem. I am kicking solutions that use a combination of adding "virtual" methods and custom callbacks to the ApplicationController class, but it seems to me that I am trying to set a square snap to a round hole.

Does anyone have any suggested articles, blog posts, etc. that might solve the same problem?

+3


source to share


1 answer


Inheritance is one way:

class BaseController < ApplicationController

  before_filter :some_common_thing

  def some_common_thing
    # common code
  end

end

class ObjectController < BaseController

  # just the code that is unique to this controller

end

      



... with the caveat that you don't go too far - here is a good article on inheritance in ruby (although it applies to any OO language)

0


source







All Articles