genki-merb_component 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'merb-core'
5
5
  require 'merb-core/tasks/merb'
6
6
 
7
7
  GEM_NAME = "merb_component"
8
- GEM_VERSION = "0.1.1"
8
+ GEM_VERSION = "0.1.2"
9
9
  AUTHOR = "Genki Takiuchi"
10
10
  EMAIL = "genki@s21g.com"
11
11
  HOMEPAGE = "http://blog.s21g.com/genki"
@@ -49,3 +49,10 @@ task :gemspec do
49
49
  file.puts spec.to_ruby
50
50
  end
51
51
  end
52
+
53
+ desc "Run specs"
54
+ task :spec do
55
+ sh "spec --color spec"
56
+ end
57
+
58
+ task :default => :spec
@@ -1,15 +1,17 @@
1
1
  # make sure we're running inside Merb
2
2
  if defined?(Merb::Plugins)
3
3
 
4
- # Merb gives you a Merb::Plugins.config hash...feel free to put your stuff in your piece of it
4
+ # Merb gives you a Merb::Plugins.config hash...feel free to put your stuff in
5
+ # your piece of it
5
6
  Merb::Plugins.config[:merb_component] = {
6
- :chickens => false
7
7
  }
8
8
 
9
9
  Merb::BootLoader.before_app_loads do
10
10
  # require code that must be loaded before the application
11
11
  require 'merb_component/controller_ext'
12
12
  require 'merb_component/model_ext'
13
+ require 'merb_component/resource_ext'
14
+ require 'merb_component/helper_ext'
13
15
  end
14
16
 
15
17
  Merb::BootLoader.after_app_loads do
@@ -1,9 +1,65 @@
1
1
  class Merb::Controller
2
+ METHOD_TO_ACTION = {
3
+ :post => :create,
4
+ :put => :update,
5
+ :delete => :destroy
6
+ }.freeze
7
+
8
+ class << self
9
+ private
10
+ def aggregates(*args)
11
+ @aggregations ||= Mash.new
12
+ options = extract_options_from_args!(args) || {}
13
+ args.each do |arg|
14
+ define_method(arg){} unless method_defined?(arg)
15
+ model = Object.full_const_get(arg.to_s.singular.camel_case)
16
+ key = "#{controller_name.singular}_id"
17
+ var = "@#{arg.to_s.singular}"
18
+
19
+ add_filter(_before_filters, proc{|c|
20
+ # setup request
21
+ id = params.delete(key)
22
+ req = request.dup
23
+ req.reset_params!
24
+ req.instance_variable_set(:@params, params.merge(
25
+ :controller => arg, :action => METHOD_TO_ACTION[req.method]))
26
+
27
+ # call action of subsidiary controller with scope
28
+ cc = Object.full_const_get(params[:action].camel_case).new(req)
29
+ model.send :with_scope, key => id do
30
+ cc._abstract_dispatch(req.params[:action])
31
+ result = cc.instance_variable_get(var)
32
+ c.instance_variable_set(var, result)
33
+ end
34
+
35
+ # prepare for performing actoin of principal controller
36
+ params[:id] = id
37
+ params[:action] = c.action_name = :show
38
+ }, :only => arg)
39
+ end
40
+ end
41
+ end
42
+
43
+ def _abstract_dispatch(*args)
44
+ _dispatch = Merb::AbstractController.instance_method(:_dispatch)
45
+ _dispatch.bind(self).call(*args)
46
+ end
47
+
2
48
  private
3
49
  def component(controller, action, params = {})
4
50
  req = request.dup
5
51
  req.reset_params!
6
52
  req.instance_variable_set :@params, params
7
- controller.new(req)._dispatch(action).render :layout => false
53
+ controller.new(req)._abstract_dispatch(action)
54
+ end
55
+
56
+ def resource(first, *args)
57
+ model = case first
58
+ when Symbol, String
59
+ Object.full_const_get(first.to_s.singular.camel_case)
60
+ else first.class
61
+ end
62
+ return super unless model.relation
63
+ super(model.relation, first, *args)
8
64
  end
9
65
  end
@@ -0,0 +1,4 @@
1
+ module Merb
2
+ module GlobalHelpers
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module DataMapper::Resource
2
+ module ClassMethods
3
+ def build(attrs = {})
4
+ all.build(attrs)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ class Admin < Application
2
+ aggregates :comments
3
+
4
+ def index
5
+ @comments = Comment.all
6
+ render
7
+ end
8
+ end
@@ -0,0 +1,2 @@
1
+ class Application < Merb::Controller
2
+ end
@@ -0,0 +1,25 @@
1
+ class Comments < Application
2
+ def index
3
+ @comments = Comment.all
4
+ display @comments
5
+ end
6
+
7
+ def new
8
+ @comment = Comment.build
9
+ display @comment
10
+ end
11
+
12
+ def create(comment)
13
+ @comment = Comment.all.create(comment)
14
+ end
15
+
16
+ def update(id, comment)
17
+ @comment = Comment.get(id)
18
+ @comment.update_attributes(comment)
19
+ end
20
+
21
+ def destroy(id)
22
+ @comment = Comment.get(id)
23
+ @comment.destroy
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ class Posts < Application
2
+ aggregates :comments
3
+
4
+ def index
5
+ @posts = Post.all
6
+ display @posts
7
+ end
8
+
9
+ def show(id)
10
+ @post = Post.get(id)
11
+ display @post
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ class Comment
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :body, Text
6
+
7
+ belongs_to :post
8
+ end
@@ -0,0 +1,7 @@
1
+ class Post
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+
6
+ has n, :comments
7
+ end
@@ -0,0 +1,7 @@
1
+ <h2>Comments</h2>
2
+
3
+ <ul>
4
+ <% @comments.each do |comment| %>
5
+ <li><%= comment.body %></li>
6
+ <% end %>
7
+ </ul>
@@ -0,0 +1,3 @@
1
+ <%= form_for @comment, :action => resource(:comments) do %>
2
+ <%= submit "submit" %>
3
+ <% end =%>
@@ -0,0 +1,7 @@
1
+ <h1>Posts</h1>
2
+
3
+ <ul>
4
+ <% @posts.each do |post| %>
5
+ <li><%= post.id %></li>
6
+ <% end %>
7
+ </ul>
@@ -0,0 +1,6 @@
1
+ <h1><%= @post.id %></h1>
2
+
3
+ <% Comment.related_with(@post) do %>
4
+ <%= component Comments, :index %>
5
+ <%= component Comments, :new %>
6
+ <% end %>
@@ -0,0 +1,14 @@
1
+ Merb::Router.prepare do
2
+ resources :posts do |posts|
3
+ posts.match("/:action").to(:controller => :posts)
4
+ posts.match("/:action/:id").to(:controller => :posts)
5
+ posts.resources :comments#, :controller => :posts
6
+ end
7
+ resource :admin do |admin|
8
+ admin.match("/:action").to(:controller => :admin)
9
+ admin.match("/:action/:id").to(:controller => :admin)
10
+ admin.resources :comments#, :controller => :admin
11
+ end
12
+
13
+ default_routes
14
+ end
@@ -1,7 +1,11 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
2
 
3
3
  describe "merb_component" do
4
- it "should do nothing" do
5
- true.should == true
4
+ it "should extend controller" do
5
+ Posts.private_instance_methods.should be_include("component")
6
+ end
7
+
8
+ it "should extend model" do
9
+ Post.public_methods.should be_include("related_with")
6
10
  end
7
11
  end
@@ -0,0 +1,76 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Posts do
4
+ before do
5
+ @req = Merb::Request.new(
6
+ Merb::Const::REQUEST_PATH => "/posts",
7
+ Merb::Const::REQUEST_METHOD => "GET",
8
+ Merb::Const::QUERY_STRING => "")
9
+ @c = Posts.new(@req)
10
+ end
11
+
12
+ it "should be a controller" do
13
+ @c.should be_kind_of(Merb::Controller)
14
+ end
15
+ end
16
+
17
+ describe "Posts controller" do
18
+ before :all do
19
+ @post = Post.create
20
+ @comment = @post.comments.create
21
+ end
22
+
23
+ it "should be tested on at least one post" do
24
+ Post.count.should > 0
25
+ Comment.count.should > 0
26
+ end
27
+
28
+ it "should show html" do
29
+ res = request(resource(@post))
30
+ res.should be_successful
31
+ res.should have_xpath("//h1")
32
+ res.should have_xpath("//h2")
33
+ res.should have_xpath("//ul/li")
34
+ res.should have_xpath("//form[@method='post']")
35
+ res.should have_xpath("//form[@action='/posts/#{@post.id}/comments']")
36
+ end
37
+
38
+ it "should show html after post a comment" do
39
+ count = @post.comments.count
40
+ res = request(resource(@post, :comments),
41
+ :method => 'POST', :params => {:comment => {:body => "foo"}})
42
+ res.should be_successful
43
+ res.should have_xpath("//h1")
44
+ res.should have_xpath("//h2")
45
+ res.should have_xpath("//ul/li[1]")
46
+ res.should have_xpath("//ul/li[2]")
47
+ res.should have_xpath("//form[@method='post']")
48
+ res.should contain("foo")
49
+ Comment.all(:post_id => @post.id).count.should == count + 1
50
+ end
51
+
52
+ it "should show html after update a comment" do
53
+ comment = @post.comments.last
54
+ comment.should be_kind_of(Comment)
55
+ res = request(resource(@post, comment),
56
+ :method => 'PUT', :params => {:comment => {:body => "bar"}})
57
+ res.should be_successful
58
+ res.should have_xpath("//h1")
59
+ res.should have_xpath("//h2")
60
+ res.should have_xpath("//ul/li[1]")
61
+ res.should have_xpath("//ul/li[2]")
62
+ res.should have_xpath("//form[@method='post']")
63
+ res.should contain("bar")
64
+ end
65
+
66
+ it "should show html after update a comment" do
67
+ count = @post.comments.count
68
+ comment = @post.comments.last
69
+ comment.should be_kind_of(Comment)
70
+ res = request(resource(@post, comment), :method => 'DELETE')
71
+ res.should be_successful
72
+ res.should have_xpath("//h1")
73
+ res.should have_xpath("//h2")
74
+ @post.comments.count.should == count - 1
75
+ end
76
+ end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,35 @@
1
- $:.push File.join(File.dirname(__FILE__), '..', 'lib')
1
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'rubygems'
4
+ require 'merb-core'
5
+ require 'merb-core/plugins'
6
+ require 'merb_component'
7
+ require "spec" # Satisfies Autotest and anyone else not using the Rake tasks
8
+
9
+ dependency "dm-core"
10
+ dependency "dm-aggregates"
11
+ dependency "merb-action-args"
12
+ dependency "merb-helpers"
13
+
14
+ use_orm :datamapper
15
+ use_test :rspec
16
+ use_template_engine :erb
17
+
18
+ # this loads all plugins required in your init file so don't add them
19
+ # here again, Merb will do it for you
20
+ Merb.disable(:initfile)
21
+ Merb.start_environment(
22
+ :testing => true,
23
+ :adapter => 'runner',
24
+ :environment => ENV['MERB_ENV'] || 'test',
25
+ :merb_root => File.dirname(__FILE__) / 'fixture',
26
+ :log_file => File.dirname(__FILE__) / '..' / "merb_test.log"
27
+ )
28
+ DataMapper.setup(:default, "sqlite3::memory:")
29
+
30
+ Spec::Runner.configure do |config|
31
+ config.include(Merb::Test::ViewHelper)
32
+ config.include(Merb::Test::RouteHelper)
33
+ config.include(Merb::Test::ControllerHelper)
34
+ config.before(:all){DataMapper.auto_migrate!}
35
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: genki-merb_component
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Genki Takiuchi
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-05 00:00:00 -08:00
12
+ date: 2009-01-25 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -38,10 +38,33 @@ files:
38
38
  - TODO
39
39
  - lib/merb_component
40
40
  - lib/merb_component/controller_ext.rb
41
+ - lib/merb_component/helper_ext.rb
41
42
  - lib/merb_component/merbtasks.rb
42
43
  - lib/merb_component/model_ext.rb
44
+ - lib/merb_component/resource_ext.rb
43
45
  - lib/merb_component.rb
46
+ - spec/fixture
47
+ - spec/fixture/app
48
+ - spec/fixture/app/controllers
49
+ - spec/fixture/app/controllers/admin.rb
50
+ - spec/fixture/app/controllers/application.rb
51
+ - spec/fixture/app/controllers/comments.rb
52
+ - spec/fixture/app/controllers/posts.rb
53
+ - spec/fixture/app/models
54
+ - spec/fixture/app/models/comment.rb
55
+ - spec/fixture/app/models/post.rb
56
+ - spec/fixture/app/views
57
+ - spec/fixture/app/views/comments
58
+ - spec/fixture/app/views/comments/index.html.erb
59
+ - spec/fixture/app/views/comments/new.html.erb
60
+ - spec/fixture/app/views/posts
61
+ - spec/fixture/app/views/posts/index.html.erb
62
+ - spec/fixture/app/views/posts/show.html.erb
63
+ - spec/fixture/config
64
+ - spec/fixture/config/router.rb
65
+ - spec/fixture/tmp
44
66
  - spec/merb_component_spec.rb
67
+ - spec/posts_spec.rb
45
68
  - spec/spec_helper.rb
46
69
  has_rdoc: true
47
70
  homepage: http://blog.s21g.com/genki