Вопрос

I've been trying to wrap my head around this single table inheritance example. I understand the concept behind it, but am not sure from reading other posts around the web & on this site how to make it work for my example. I'm using STI because i've got two types of projects - public and private. The logic behind them is the same and the data they store in the database will be identical whether public or private. I just intend to implement some authorization & roles for users in the future that differ slightly based on whether the project is public or private. So my question is, what steps are still needed to make this work...so far I've:

1) added a type_column to projects via a migration...my project model is

PROJECT.RB

class Project < ActiveRecord::Base
  has_many :users
  has_many :versions, dependent: :destroy
  validates :title, presence: true, length: { maximum: 100 }
  validates :background, presence: true
  validates :user_id, presence: true

  default_scope -> { order('created_at DESC') }
end

2) I created separate classes for PublicProjects & PrivateProjects...those models are:

PUBLIC_PROJECT.RB

class PublicProject < Project
end

PRIVATE_PROJECT.RB

class PrivateProject < Project
end

So now i'm wondering what needs to be re-factored in my controller (i'd like to keep the single Projects controller)...and then also what needs changing in my 'new' form view. Step by step help on the code that would make this work would be much appreciated. The controller/view files are:

PROJECTS_CONTROLLER.RB

class ProjectsController < ApplicationController
  before_filter :signed_in_user, only: [:create, :new, :edit, :update]

  def new
    @project = Project.new
  end

  def show
     @project = Project.find(params[:id])
     @user = User.where(:id => @project.user_id).first
  end

  def index
    @projects = Project.paginate(page: params[:page])
  end

  def create
    @project = current_user.projects.build(project_params)
    if @project.save
      flash[:success] = "Welcome to your new project."
      redirect_to @project
    else
      render 'new'
    end
  end

  def edit

  end

  def update
    @project = Project.find(params[:id])
    if @project.update_attributes(params[:project])
      flash[:success] = "Project Created"
      redirect_to @project
    else
      render 'edit'
    end
  end

  def destroy
    User.find(params[:id]).destroy
    flash[:success] = "Project destroyed"
    redirect_to users_path
  end

  private

    def project_params
      params.require(:project).permit(:title, :background)
    end

end

NEW.HTML.ERB (NEW PROJECTS VIEW W/ FORM)

<% provide(:title, 'New Project') %>
<h1>Create a new project</h1>

<div class="row-fluid">
  <div class="col-md-5 no-pad offset3">

    <%= bootstrap_form_for @project do |f| %>

      <%= render 'shared/error_messages', object: f.object %>

      <%= f.text_field :title %>

      <%= f.text_area :background %>

      <div class="row-fluid">
        <div class="no-pad col-md-6">
          <h5>Is this project public or private?</h5>
          <div class="btn-group">
            <button type="button" class="btn btn-default"><%= image_tag "globe.png" %> Public</button>
            <button type="button" class="btn btn-default"><%= image_tag "lock.png" %> Private</button>
          </div>
          <script>
          $(".btn-group > .btn.btn-default").click(function(){
              $(".btn-group > .btn.btn-default").removeClass("active");
              $(this).addClass("active");
          });
          </script>
        </div>
        <div class="col-md-6">
          Some static graphics
        </div>
      </div>

      <br clear="all"><br/>
      <%= f.submit "Create your project", class: "btn btn-lg btn-primary" %>
    <% end %>
  </div>

</div>

Lastly, i've seen some STI examples that are getting into the routes file (although I've seen that this isn't recommended as often). but just in case:

ROUTES.RB

ProductionApp::Application.routes.draw do
  resources :users
  resources :sessions, only: [:new, :create, :destroy]

  resources :projects do
    resources :versions
  end

  # get "static_pages/home"
  # get "static_pages/help"
  # get "static_pages/about"
  #The original routes above map to...
  root  'static_pages#home'
  match '/signup',  to: 'users#new',            via: 'get'
  match '/signin',  to: 'sessions#new',         via: 'get'
  match '/signout', to: 'sessions#destroy',     via: 'delete'
  match '/help',    to: 'static_pages#help',    via: 'get'
  match '/about',   to: 'static_pages#about',   via: 'get'
  match '/contact', to: 'static_pages#contact', via: 'get'
end

Thanks a lot for any help,

Это было полезно?

Решение

I am not sure about the authentication, but instead of using additional classes for public and private, you could just create a type field that tells you whether or not the project is public or private something like is_public.

The other option is to use a enum release in rails 4 - really simple and straight forward. This is my preferred option, but you need to be working on the latest version of rails.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top