Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Review Requested] Add scaffold_controller generator #83

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ Gemfile*.lock
pkg/*
test/dummy/log/*
test/dummy/tmp/*
test/tmp/*
.rvmrc
9 changes: 7 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
require "bundler/gem_tasks"

require 'rake/testtask'
require "rails/version"

task :default => [:test]

Rake::TestTask.new(:test) do |test|
test.libs << 'test'
test.test_files = FileList['test/*_test.rb']

# Do not test generators for Rails < 3.2
test.test_files = FileList['test/*_test.rb'].reject do |file|
file.include?('generator') && Rails::VERSION::STRING < '3.2'
end

test.verbose = true
end
1 change: 1 addition & 0 deletions gemfiles/Gemfile.rails3-0
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ gemspec :path => '../'

gem 'railties', '~> 3.0.11'
gem 'activerecord', '~> 3.0.11'
gem "minitest", "~> 4.0"
1 change: 1 addition & 0 deletions gemfiles/Gemfile.rails3-2
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ gemspec :path => '../'

gem 'railties', '~> 3.2.13'
gem 'activerecord', '~> 3.2.13'
gem "minitest", "~> 4.0"
70 changes: 70 additions & 0 deletions lib/generators/rails/collection_representer_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module Rails
module Generators
class CollectionRepresenterGenerator < Rails::Generators::NamedBase
source_root File.expand_path("../templates", __FILE__)

argument :properties, :type => :array, :default => [],
:banner => "property[:class[:extend]] property[:class[:extend]]"

class_option :format, :default => :json, :banner => "--format=JSON",
:desc => "Use different formats JSON, JSON::HAL or XML"

def generate_representer_file
template('collection_representer.rb', file_path)
end

private

def format
options[:format].upcase
end

def property_options
PropertyBuilder.new(properties)
end

def file_path
base_path = 'app/representers'
File.join(base_path, class_path, "#{file_name.pluralize}_representer.rb")
end

class PropertyBuilder
include Enumerable

def initialize(properties)
@raw = properties
end

def each(&block)
properties_with_options.each(&block)
end

private

def properties_with_options
properties.map do |(name, klass, representer)|
p = [name_option(name)]
p << hash_option(:class, klass)
p << hash_option(:extend, representer)

p.compact.join(', ')
end
end

def name_option(name)
return unless name
"property :#{name}"
end

def hash_option(key, value)
return unless key && value
":#{key} => #{value.classify}"
end

def properties
@raw.map { |p| p.split(':') }
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/generators/rails/scaffold_controller_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'rails/generators/named_base'
require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
require 'rails/generators/resource_helpers'

module Rails
module Generators
class ScaffoldControllerGenerator
source_root File.expand_path('../templates', __FILE__)

hook_for :representer, default: true
hook_for :collection_representer, default: true
end
end
end
7 changes: 7 additions & 0 deletions lib/generators/rails/templates/collection_representer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<% module_namespacing do -%>
module <%= class_name.pluralize %>Representer
include Representable::JSON::Collection

items extend: <%= class_name %>Representer, class: <%= class_name %>
end
<% end %>
48 changes: 48 additions & 0 deletions lib/generators/rails/templates/controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<% if namespaced? -%>
require_dependency "<%= namespaced_file_path %>/application_controller"

<% end -%>
<% module_namespacing do -%>
class <%= controller_class_name %>Controller < ApplicationController
include Roar::Rails::ControllerAdditions
respond_to :json

before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]

def index
@<%= plural_table_name %> = <%= orm_class.all(class_name) %>

respond_with @<%= plural_table_name %>, :represent_with => <%= controller_class_name %>Representer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we go the Controller::represents way here and set this on the class level instead of using :represent_with in every action? This option was meant to be a work-around if you need to customise an edge case.

Do you use ::represents at all?

end

def show
respond_with @<%= singular_table_name %>, :represent_with => <%= class_name %>Representer
end

def create
@<%= singular_table_name %> = consume! <%= class_name %>.new, :represent_with => <%= class_name %>Representer
@<%= singular_table_name %>.save

respond_with @<%= singular_table_name %>, :represent_with => <%= class_name %>Representer
end

def update
consume! @<%= singular_table_name %>, :represent_with => <%= class_name %>Representer
@<%= singular_table_name %>.save

respond_with @<%= singular_table_name %>, :represent_with => <%= class_name %>Representer
end

def destroy
@<%= orm_instance.destroy %>

head :no_content
end

private

def set_<%= singular_table_name %>
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
end
end
<% end -%>
2 changes: 2 additions & 0 deletions lib/generators/rails/templates/representer.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<% module_namespacing do -%>
module <%= class_name %>Representer
include Roar::Representer::<%= format %>
<% property_options.each do |property| %>
<%= property -%>
<% end %>
end
<% end -%>
6 changes: 6 additions & 0 deletions lib/roar/rails/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ class Railtie < ::Rails::Railtie

include UrlMethods # provide an initial #default_url_options.
end

Railtie.generators do |app|
Railtie::Rails::Generators.configure! app.config.generators
Railtie::Rails::Generators.hidden_namespaces.uniq!
require 'generators/rails/scaffold_controller_generator'
end
end
end
end
Expand Down
1 change: 1 addition & 0 deletions roar-rails.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ Gem::Specification.new do |s|
s.add_development_dependency "activerecord"
s.add_development_dependency "sqlite3"
s.add_development_dependency "tzinfo" # FIXME: why the hell do we need this for 3.1?
s.add_development_dependency "pry" # FIXME: why the hell do we need this for 3.1?
end
31 changes: 31 additions & 0 deletions test/collection_representer_generator_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'test_helper'
require 'rails/generators'
require 'generators/rails/collection_representer_generator'

class CollectionRepresenterGeneratorTest < Rails::Generators::TestCase
destination File.join(Rails.root, "tmp")
setup :prepare_destination
tests Rails::Generators::CollectionRepresenterGenerator

test "create a representer with correct class_name" do
run_generator %w(singer)

assert_file representer_path('singer'), /module SingersRepresenter/
end

test "create a representer with collection support" do
run_generator %w(singer)

assert_file representer_path('singer'), /include Representable::JSON::Collection/
end

test "extend the correct representer" do
run_generator %w(singer)

assert_file representer_path('singer'), /items extend: SingerRepresenter, class: Singer/
end

def representer_path(name)
"app/representers/#{name.pluralize}_representer.rb"
end
end
45 changes: 45 additions & 0 deletions test/controller_scaffold_generator_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require 'test_helper'
require 'rails/generators/test_case'

require 'generators/rails/scaffold_controller_generator'

class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
if Rails::VERSION::STRING >= "4.0"
tests Rails::Generators::ScaffoldControllerGenerator
arguments %w(Post title body:text)
destination File.expand_path('../tmp', __FILE__)
setup :prepare_destination

test 'controller content' do
run_generator

assert_file 'app/controllers/posts_controller.rb' do |content|
assert_instance_method :index, content do |m|
assert_match /@posts = Post\.all/, m
assert_match /respond_with @posts, :represent_with => PostsRepresenter/, m
end

assert_instance_method :show, content do |m|
assert_match /respond_with @post, :represent_with => PostRepresenter/, m
end

assert_instance_method :create, content do |m|
assert_match /@post = consume! Post\.new, :represent_with => PostRepresenter/, m
assert_match /@post\.save/, m
assert_match /respond_with @post, :represent_with => PostRepresenter/, m
end

assert_instance_method :update, content do |m|
assert_match /consume! @post, :represent_with => PostRepresenter/, m
assert_match /@post\.save/, m
assert_match /respond_with @post, :represent_with => PostRepresenter/, m
end

assert_instance_method :destroy, content do |m|
assert_match /@post\.destroy/, m
assert_match /head :no_content/, m
end
end
end
end
end
13 changes: 12 additions & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@
require "dummy/config/environment"
require "rails/test_help" # adds stuff like @routes, etc.
require "roar/rails/test_case"
require "active_support/test_case"

require "bundler/setup"
require "rails/version"

if Rails::VERSION::STRING > "4.0"
require "active_support/testing/autorun"
else
require "test/unit"
end


Singer = Struct.new(:name)

Expand All @@ -15,4 +26,4 @@
ActionController.add_renderer :hal do |js, options|
self.content_type ||= Mime::HAL
js.is_a?(String) ? js : js.to_json
end
end