genki-merb_component 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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