- 浏览: 229004 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
jj7jj7jj:
容我来补一刀~1,function(){ ...
执行JS匿名函数的N种方式 -
duwu:
根本就不能用,试了好多天,一次都没发送成功,发了根本就没有任何 ...
邮件发新浪微博 -
ganky:
终于搞定了,我郁闷啊……我是用JAVA写的,在登录成功后使用g ...
基于web飞信接口的飞信应答机器人 -
ganky:
之前也有搞了一下,只实现了登录,因为一直找不到webim_se ...
基于web飞信接口的飞信应答机器人 -
kewin:
现在127行了哦
基于web飞信接口的飞信应答机器人
require 'camping' Camping.goes :Blog module Blog::Models class Post < Base; belongs_to :user; end class Comment < Base; belongs_to :user; end class User < Base; end end module Blog::Controllers class Index < R '/' def get @posts = Post.find :all render :index end end end module Blog::Views def layout html do body do self << yield end end end def index for post in @posts h1 post.title end end end
这代码体现的思想太棒了!异常简洁。
http://camping.rubyforge.org/files/README.html
http://redhanded.hobix.com/bits/campingAMicroframework.html
http://github.com/why/camping/downloads
全部源码才4k。
# == About camping.rb # # Camping comes with two versions of its source code. The code contained in # lib/camping.rb is compressed, stripped of whitespace, using compact algorithms # to keep it tight. The unspoken rule is that camping.rb should be flowed with # no more than 80 characters per line and must not exceed four kilobytes. # # On the other hand, lib/camping-unabridged.rb contains the same code, laid out # nicely with piles of documentation everywhere. This documentation is entirely # generated from lib/camping-unabridged.rb using RDoc and our "flipbook" template # found in the extras directory of any camping distribution. %w[uri stringio rack].map { |l| require l } class Object #:nodoc: def meta_def(m,&b) #:nodoc: (class<<self;self end).send(:define_method,m,&b) end end # TODO: Rack (for production). Overriding r404, r500 and r501. # # Ready for developing with Camping? Just follow along and we'll explain # everything in a few minutes. If there's a specific thing you're wondering # about, here are some guidelines of how Camping and the documentation is organized: # # * All the modules are documentated with a little overview, followed by # all the methods defined there. # * Camping::Controllers explains all you need to know about taking care # of the request and returning a response. # * Camping::Models explains how you interact with the database, or other data sources. # * Camping::Views explains how you can easily generate HTML from plain Ruby. # * Camping::Helpers is a module with useful helpers, both for the controllers and the views. # * Camping::Base is a module which is included in all your controllers. # # # == Starting My First App # # When you're going to start a new app in Camping, you simply open # your favorite text editor and start writing: # # require 'camping' # Camping.goes :Blog # # module Blog # # lots of code # end # # What's important to know, is that <tt>Camping.goes :Blog</tt> copies the # Camping-module into the Blog-module. So whenever you see Camping in this # documentation, you can replace it with Blog and everything should work # as expected. # # By not modifying the Camping-module itself, you can have all your apps # running in the same process and have less moving parts. In fact, we recommend # splitting larger apps into several, smaller ones to make it more manageable. # # == The Camping Server (for development) # # Camping includes a pretty nifty server which is built for development. # It follows these rules: # # * Load all Camping apps in a directory or a file. # * Load new apps that appear in that directory or that file. # * Mount those apps according to their name. (e.g. Blog is mounted at /blog.) # * Run each app's <tt>create</tt> method upon startup. # * Reload the app if its modification time changes. # * Reload the app if it requires any files under the same directory and one of their modification times changes. # * Support the X-Sendfile header. # # Run it like this: # # camping examples/ # Mounts all apps in that directory # camping blog.rb # Mounts Blog at / # # And visit http://localhost:3301/ in your browser. Ready for some development? # # # == MVC # # Camping follows the MVC-pattern, which means you'll separate your app into # three parts: Models, views and controllers. Let's start with the last: # # === Controllers # # module Blog::Controllers # class Index # def get # @posts = Post.all # render :index # end # end # end # # The controllers are the heart of your app: They respond to a request from # the user, process it and return an appropriate response. Have a look at # Camping::Controllers in order to fully understand how controllers work # and how you should use them in Camping. # # === Models # # module Blog::Models # class Post < Base; belongs_to :user; end # class Comment < Base; belongs_to :user; end # class User < Base; end # end # # Most apps needs to handle _data_ in some way: A blog needs a place to save # and retrieve posts and comments; a wiki needs to store the pages somewhere. # A _database_ is (most of the time) a great place to save such data. Camping # uses (just like Rails) ActiveRecord to abstract the boring details down to # beautiful Ruby. Read Camping::Models to learn how to use them in your app. # # === Views # # module Blog::Views # def layout # html do # head { title "My Blog" } # body do # h1 "My Blog" # self << yield # end # end # end # # def index # @posts.each do |post| # h2 post.title # self << post.content # end # end # end # # Since we're on the web, we need to return the language which the web speaks: # HTML. Writing HTML manually can be tedious and boring. Camping uses Markaby # which lets you write HTML in Ruby - simple and elegant. As always, read # Camping::Views to get a overview of how to use views. # # === Helpers # # I know, I know: Helpers don't fit into the MVC-pattern. That doesn't mean # they're useless, though. Whenever you need a snippet in several controllers # or views, you should refactor it out to a helper. Camping includes a # sensible collection of helpers in Camping::Helpers. # # # == Tips & Tricks # # === The <tt>create</tt> method # # It's a rule in Camping which says that the <tt>create</tt> method should be # called when the server starts up. The Camping Server does this, and so # should you in your environment. # # This is a good place to check for database tables and create those tables # to save users of your application from needing to manually set them up. # # def Blog.create # Blog::Models::Base.establish_connection( # :adapter => 'sqlite3', # :database => 'blog.db' # ) # Blog::Models.create_schama # end # # === Service Override # # Occassionally, you may want to intercept controller calls or do some cleanup # afterwards. Many other frameworks have before-, after- and around-filters # to do that. Camping has no facility for doing this. It's not worth the bytes. # # Instead, you can override <tt>service</tt>, which handles all controller calls. # You can do include into specific controllers or right into the main application module. # # module MySession # def service(*a) # # Do stuff before # @session = MyApp::Session.new # # Run regular controller # super(*a) # ensure # # Do stuff after # @session.close # end # end # # module MyApp # include MySession # # module Controllers # class Index # include OtherOverload # end # end # end module Camping C = self S = IO.read(__FILE__) rescue nil P = "<h1>Cam\ping Problem!</h1><h2>%s</h2>" U = Rack::Utils Apps = [] # TODO: @input[:page] != @input['page'] # An object-like Hash. # All Camping query string and cookie variables are loaded as this. # # To access the query string, for instance, use the <tt>@input</tt> variable. # # module Blog::Controllers # class Index < R '/' # def get # if page = @input.page.to_i > 0 # page -= 1 # end # @posts = Post.find :all, :offset => page * 20, :limit => 20 # render :index # end # end # end # # In the above example if you visit <tt>/?page=2</tt>, you'll get the second # page of twenty posts. You can also use <tt>@input[:page]</tt> or <tt>@input['page']</tt> # to get the value for the <tt>page</tt> query variable. # # Use the <tt>@cookies</tt> variable in the same fashion to access cookie variables. class H < Hash # Gets or sets keys in the hash. # # @cookies.my_favorite = :macadamian # @cookies.my_favorite # => :macadamian # def method_missing(m,*a) m.to_s=~/=$/?self[$`]=a[0]:a==[]?self[m.to_s]:super end undef id, type end # TODO: Fair enough. Maybe complete the ActionPack example? # Helpers contains methods available in your controllers and views. You may add # methods of your own to this module, including many helper methods from Rails. # This is analogous to Rails' <tt>ApplicationHelper</tt> module. # # == Using ActionPack Helpers # # If you'd like to include helpers from Rails' modules, you'll need to look up the # helper module in the Rails documentation at http://api.rubyonrails.org/. # # For example, if you look up the <tt>ActionView::Helpers::FormHelper</tt> class, # you'll find that it's loaded from the <tt>action_view/helpers/form_helper.rb</tt> # file. You'll need to have the ActionPack gem installed for this to work. # # require 'action_view/helpers/form_helper.rb' # # # This example is unfinished.. soon.. # module Helpers # From inside your controllers and views, you will often need to figure out # the route used to get to a certain controller +c+. Pass the controller class # and any arguments into the R method, a string containing the route will be # returned to you. # # Assuming you have a specific route in an edit controller: # # class Edit < R '/edit/(\d+)' # # A specific route to the Edit controller can be built with: # # R(Edit, 1) # # Which outputs: <tt>/edit/1</tt>. # # You may also pass in a model object and the ID of the object will be used. # # If a controller has many routes, the route will be selected if it is the # first in the routing list to have the right number of arguments. # # == Using R in the View # # Keep in mind that this route doesn't include the root path. # You will need to use <tt>/</tt> (the slash method above) in your controllers. # Or, go ahead and use the Helpers#URL method to build a complete URL for a route. # # However, in your views, the :href, :src and :action attributes automatically # pass through the slash method, so you are encouraged to use <tt>R</tt> or # <tt>URL</tt> in your views. # # module Blog::Views # def menu # div.menu! do # a 'Home', :href => URL() # a 'Profile', :href => "/profile" # a 'Logout', :href => R(Logout) # a 'Google', :href => 'http://google.com' # end # end # end # # Let's say the above example takes place inside an application mounted at # <tt>http://localhost:3301/frodo</tt> and that a controller named <tt>Logout</tt> # is assigned to route <tt>/logout</tt>. The HTML will come out as: # # <div id="menu"> # <a href="http://localhost:3301/frodo/">Home</a> # <a href="/frodo/profile">Profile</a> # <a href="/frodo/logout">Logout</a> # <a href="http://google.com">Google</a> # </div> # def R(c,*g) p,h=/\(.+?\)/,g.grep(Hash) g-=h raise "bad route" unless u = c.urls.find{|x| break x if x.scan(p).size == g.size && /^#{x}\/?$/ =~ (x=g.inject(x){|x,a| x.sub p,U.escape((a[a.class.primary_key]rescue a))}) } h.any?? u+"?"+U.build_query(h[0]) : u end # Simply builds a complete path from a path +p+ within the app. If your # application is mounted at <tt>/blog</tt>: # # self / "/view/1" #=> "/blog/view/1" # self / "styles.css" #=> "styles.css" # self / R(Edit, 1) #=> "/blog/edit/1" # def /(p); p[0]==?/?@root+p:p end # Builds a URL route to a controller or a path, returning a URI object. # This way you'll get the hostname and the port number, a complete URL. # # You can use this to grab URLs for controllers using the R-style syntax. # So, if your application is mounted at <tt>http://test.ing/blog/</tt> # and you have a View controller which routes as <tt>R '/view/(\d+)'</tt>: # # URL(View, @post.id) #=> #<URL:http://test.ing/blog/view/12> # # Or you can use the direct path: # # self.URL #=> #<URL:http://test.ing/blog/> # self.URL + "view/12" #=> #<URL:http://test.ing/blog/view/12> # URL("/view/12") #=> #<URL:http://test.ing/blog/view/12> # # It's okay to pass URL strings through this method as well: # # URL("http://google.com") #=> #<URL:http://google.com> # # Any string which doesn't begin with a slash will pass through # unscathed. def URL c='/',*a c = R(c, *a) if c.respond_to? :urls c = self/c c = @request.url[/.{8,}?(?=\/)/]+c if c[0]==?/ URI(c) end end # Camping::Base is built into each controller by way of the generic routing # class Camping::R. In some ways, this class is trying to do too much, but # it saves code for all the glue to stay in one place. # # Forgivable, considering that it's only really a handful of methods and accessors. # # == Treating controller methods like Response objects # TODO: I don't think this belongs here. Either Controllers or Camping. # # Camping originally came with a barebones Response object, but it's often much more readable # to just use your controller as the response. # # Go ahead and alter the status, cookies, headers and body instance variables as you # see fit in order to customize the response. # # module Camping::Controllers # class SoftLink # def get # redirect "/" # end # end # end # # Is equivalent to: # # module Camping::Controllers # class SoftLink # def get # @status = 302 # @headers['Location'] = "/" # end # end # end # module Base attr_accessor :input, :cookies, :headers, :body, :status, :root M = proc { |_, o, n| o.merge(n, &M) } # Display a view, calling it by its method name +v+. If a <tt>layout</tt> # method is found in Camping::Views, it will be used to wrap the HTML. # # module Camping::Controllers # class Show # def get # @posts = Post.find :all # render :index # end # end # end # # You can also return directly HTML by just passing a block # def render(v,*a,&b) mab(/^_/!~v.to_s){send(v,*a,&b)} end # You can directly return HTML form your controller for quick debugging # by calling this method and pass some Markaby to it. # # module Camping::Controllers # class Info # def get; mab{ code @headers.inspect } end # end # end # # You can also pass true to use the :layout HTML wrapping method # def mab(l=nil,&b) m=Mab.new({},self) s=m.capture(&b) s=m.capture{layout{s}} if l && m.respond_to?(:layout) s end # A quick means of setting this controller's status, body and headers. # Used internally by Camping, but... by all means... # # r(302, '', 'Location' => self / "/view/12") # # Is equivalent to: # # redirect "/view/12" # # You can also switch the body and the header in order to support Rack: # # r(302, {'Location' => self / "/view/12"}, '') # r(*another_app.call(@env)) # # See also: #r404, #r500 and #r501 def r(s, b, h = {}) b, h = h, b if Hash === b @status = s @headers.merge!(h) @body = b end # Formulate a redirect response: a 302 status with <tt>Location</tt> header # and a blank body. Uses Helpers#URL to build the location from a controller # route or path. # # So, given a root of <tt>http://localhost:3301/articles</tt>: # # redirect "view/12" # redirects to "//localhost:3301/articles/view/12" # redirect View, 12 # redirects to "//localhost:3301/articles/view/12" # # <b>NOTE:</b> This method doesn't magically exit your methods and redirect. # You'll need to <tt>return redirect(...)</tt> if this isn't the last statement # in your code. # # See: Controllers def redirect(*a) r(302,'','Location'=>URL(*a).to_s) end # Called when a controller was not found. It is mainly used internally, but it can # also be useful for you, if you want to filter some parameters. # # See: Controllers def r404(p) P % "#{p} not found" end # If there is a parse error in Camping or in your application's source code, # it will not be caught by Camping. The controller class +k+ and request method +m+ (GET, POST, etc.) where the error # took place are passed in, along with the Exception +e+ which can be mined for useful info. # # You can overide it, but if you have an error in here, it will be uncaught ! # # See: Controllers def r500(k,m,e) raise e end # Called if an undefined method is called on a controller, along with the request method +m+ (GET, POST, etc.) # # See: Controllers def r501(m) P % "#{m.upcase} not implemented" end # Turn a controller into an array. This is designed to be used to pipe # controllers into the <tt>r</tt> method. A great way to forward your # requests! # # class Read < '/(\d+)' # def get(id) # Post.find(id) # rescue # r *Blog.get(:NotFound, @headers.REQUEST_URI) # end # end def to_a r = Rack::Response.new(@body, @status, @headers) @cookies.each do |k, v| v = {:value => v, :path => self / "/"} if String===v r.set_cookie(k, v) end r.to_a end def initialize(env, m) #:nodoc: r = @request = Rack::Request.new(@env = env) @root, p, @cookies, @headers, @status, @method = (env.SCRIPT_NAME||'').sub(/\/$/,''), H[r.params], H[r.cookies], {}, m =~ /r(\d+)/ ? $1.to_i : 200, m @input = p.inject(H[]) do |h, (k, v)| h.merge(k.split(/[\]\[]+/).reverse.inject(v) { |x, i| H[i => x] }, &M) end end # All requests pass through this method before going to the controller. # Some magic in Camping can be performed by overriding this method. # # See: Camping def service(*a) r = catch(:halt){send(@method, *a)} @body ||= r self end end # In order to fully understand controllers and how they are used, you # should know a bit about HTTP - the protocol behind The World Wide Web. # # == Request # # HTTP is built around _requests_. When a user types "http://yoursite.com/" # in his web browser, the browser starts making requests to the server. # It's basically asking the server to do what the user want. When the server # has decided what to do, it sends a _response_ back to the browser which # is then showed to the user. # # We can brutually split a request into three parts: a resource, a method # and the rest. # # === Resource # # A _resource_ in HTTP is simply a name of a _thing_ - it's a noun. Just like # "home", "blog post" and "comment" are nouns in our world, are +/+, # +/post/123+ and +/post/123/comment/456+ resources in HTTP. # # Nouns are well and good, but just like you can't build a sentence with # only nouns, you can't build a request with only a resource. We need verbs! # # === Method # # _Methods_ are the verbs in HTTP. It's not enough to have the name of # what you want, you have to tell _what_ you want to do too. Since # we're speaking with machines, we have to stick to these: # # * GET # * POST # * (PUT) # * (DELTE) # # GET is the default method. When you type an address or click a link in # your browser, it's smart enough to realize that you want to get that # resource. GET also is the simplest of the methods: it should not _do_ # anything, just return the content. # # The three others are focused on actions. POST for create, PUT for # update and DELETE for, uhm, delete. You may have noticed the parenthesis # around PUT and DELETE, and the reason for that is quite sad: # # When the web was still young, some realized that they didn't _need_ # PUT and DELETE; they could just use POST and put the verb in the # resource: POST /posts/delete/1. This doesn't make sense at all, but # it happened and <strong>right now browsers only support GET and POST.</strong> # # === The Rest # # HTTP is also very flexible, so the browser can send all kind of other # metadata (called _headers_). This includes the name of the browser, the # preferred language, the domain of the server and much, much more. # # In POST, PUT and DELETE you can also send some arbitrary data (called # the _body_). This is used for instance when you upload a file. # # Probably the most important part is that the browser can send parameters. # In all the methods you can tack them on to the end after a question mark # (<tt>/search?query=camping</tt>), while POST, PUT and DELETE also allows # to send them, hidden from the user, in the body. # # == Response # # When the browser has sent the request to the server, the server has # to return a response. We can also split the response into three parts: # a status code, headers and a body. # # === Status Code # # The status code tells a bit about the response. For instance: # # * 200 means everything went fine and no problems occured. # * 401 means you have to login. # * 404 means the resource couldn't be found. # * 500 means the server encountered an error. # # This is just a small selection. Wikipedia has a {nice list with _all_ the # codes}[http://en.wikipedia.org/wiki/List_of_HTTP_status_codes]. # # === Headers # # Just like the headers in the request, the headers in the response are # used to send useful metadata back to the browser. Examples of this # are what kind of content this is, the length of the body and if the # browser should give a "File Download" dialogue box. # # === Body # # The body is simply what the user is going to see. # # == Using controllers in Camping # # I guess you're bored with all of this (seemingly useless) theory, but we # believe it's better to understand HTTP now than later. Let's however # start with some coding. # # In Camping, a controller is simply a resource: # # module Blog::Controllers # class Posts < R '/posts' # def get # "Hello from GET" # end # # def post # "Hello from POST" # end # end # end # # Camping will take care if of all the boring stuff, and whenever someone # tries to GET or POST <tt>/posts</tt> it will display this nice message. # # If someone tries to DELETE <tt>/posts</tt>, Camping will return a 501 # response (which means the method wasn't implemented). If someone tries to # access <tt>/postsss</tt>, it will return a 404 response (no such resource). # # === Specialized resources # # Most of the time your resources needs to match more than a single, static # path (like <tt>/posts</tt> above). Luckily, you can use regular expressions # in your routes. Wrap the rules with some parethesis and it will also be # sent as arguments to your method: # # module Blog::Controllers # class Post < R '/post/(\d+)' # def get(id) # case id.to_i # when 1 # "You're looking at the first post (/post/1)!" # when 2 # "You're looking at the second post (/post/2)!" # else # "Meh." # end # end # end # # class Page < R '/user/(\w+)/page/(\w+)', '/u/(\w+)/(\w+)' # def get(user, page_name) # "You're visiting #{user}'s #{page_name}" # end # end # end # # As you can see, you can also give your controllers several routes to match. # # === Magic resources # # Very often, you will name your controllers identical to it's route. If # you leave out the route and just define the controller as a class # (<tt>class Posts</tt>), Camping will automatically build the route using some magic: # # First it will split the controller name up by words. For instance # +VeryNiftyRoute+ will be split up into +Very+, +Nifty+ and +Route+. # # Then it substitutes each part using these rules: # # * Index turns into / # * X turns into ([^/]+) # * N turns into (\\\d+) # * Everything else turns into lowercase # # Finally it puts a slash between the parts. # # It can take some time to grasp, but it's actually very nice since you # avoid repeating the route in the name (or vica versa). Have a look at the # examples below if you're still a little confused. # # module Blog::Controllers # # Matches: / # class Index # end # # # Matches: /post/(\d+) # class PostN # end # # # Matches: /very/nifty/route # class VeryNiftyRoute # end # end # # TODO: @input & @cookies at least. # Controllers is a module for placing classes which handle URLs. This is done # by defining a route to each class using the Controllers::R method. # # module Camping::Controllers # class Edit < R '/edit/(\d+)' # def get; end # def post; end # end # end # # If no route is set, Camping will guess the route from the class name. # The rule is very simple: the route becomes a slash followed by the lowercased # class name. See Controllers::D for the complete rules of dispatch. module Controllers @r = [] class << self # An array containing the various controllers available for dispatch. def r #:nodoc: @r end # Add routes to a controller class by piling them into the R method. # # module Camping::Controllers # class Edit < R '/edit/(\d+)', '/new' # def get(id) # if id # edit # else # new # end # end # end # end # # You will need to use routes in either of these cases: # # * You want to assign multiple routes to a controller. # * You want your controller to receive arguments. # # Most of the time the rules inferred by dispatch method Controllers::D will get you # by just fine. def R *u r=@r Class.new { meta_def(:urls){u} meta_def(:inherited){|x|r<<x} } end # Dispatch routes to controller classes. # For each class, routes are checked for a match based on their order in the routing list # given to Controllers::R. If no routes were given, the dispatcher uses a slash followed # by the name of the controller lowercased. # # Controllers are searched in this order: # # # Classes without routes, since they refer to a very specific URL. # # Classes with routes are searched in order of their creation. # # So, define your catch-all controllers last. def D(p, m) p = '/' if !p || !p[0] r.map { |k| k.urls.map { |x| return (k.instance_method(m) rescue nil) ? [k, m, *$~[1..-1]] : [I, 'r501', m] if p =~ /^#{x}\/?$/ } } [I, 'r404', p] end N = H.new { |_,x| x.downcase }.merge! "N" => '(\d+)', "X" => '([^/]+)', "Index" => '' # The route maker, this is called by Camping internally, you shouldn't need to call it. # # Still, it's worth know what this method does. Since Ruby doesn't keep track of class # creation order, we're keeping an internal list of the controllers which inherit from R(). # This method goes through and adds all the remaining routes to the beginning of the list # and ensures all the controllers have the right mixins. # # Anyway, if you are calling the URI dispatcher from outside of a Camping server, you'll # definitely need to call this at least once to set things up. def M def M #:nodoc: end constants.map { |c| k=const_get(c) k.send :include,C,Base,Helpers,Models @r=[k]+r if r-[k]==r k.meta_def(:urls){["/#{c.scan(/.[^A-Z]*/).map(&N.method(:[]))*'/'}"]}if !k.respond_to?:urls } end end # Internal controller with no route. Used by #D and C.call to show internal messages. I = R() end X = Controllers class << self # When you are running many applications, you may want to create independent # modules for each Camping application. Namespaces for each. Camping::goes # defines a toplevel constant with the whole MVC rack inside. # # require 'camping' # Camping.goes :Blog # # module Blog::Controllers; ... end # module Blog::Models; ... end # module Blog::Views; ... end # def goes(m) Apps << eval(S.gsub(/Camping/,m.to_s), TOPLEVEL_BINDING) end # Ruby web servers use this method to enter the Camping realm. The e # argument is the environment variables hash as per the Rack specification. # And array with [statuc, headers, body] is expected at the output. def call(e) X.M e = H[e] p = e.PATH_INFO = U.unescape(e.PATH_INFO) k,m,*a=X.D p,(e.REQUEST_METHOD||'get').downcase k.new(e,m).service(*a).to_a rescue r500(:I, k, m, $!, :env => e).to_a end # The Camping scriptable dispatcher. Any unhandled method call to the app module will # be sent to a controller class, specified as an argument. # # Blog.get(:Index) # #=> #<Blog::Controllers::Index ... > # # The controller object contains all the @cookies, @body, @headers, etc. formulated by # the response. # # You can also feed environment variables and query variables as a hash, the final # argument. # # Blog.post(:Login, :input => {'username' => 'admin', 'password' => 'camping'}) # #=> #<Blog::Controllers::Login @user=... > # # Blog.get(:Info, :env => {'HTTP_HOST' => 'wagon'}) # #=> #<Blog::Controllers::Info @headers={'HTTP_HOST'=>'wagon'} ...> # def method_missing(m, c, *a) X.M h = Hash === a[-1] ? a.pop : {} e = H[Rack::MockRequest.env_for('',h[:env]||{})] k = X.const_get(c).new(e,m.to_s) k.send("input=", h[:input]) if h[:input] k.service(*a) end end # Views is an empty module for storing methods which create HTML. The HTML # is described using the Markaby language. # # == Defining and calling templates # # Templates are simply Ruby methods with Markaby inside: # # module Blog::Views # def index # p "Welcome to my blog" # end # # def show # h1 @post.title # self << @post.content # end # end # # In your controllers you just call <tt>render :template_name</tt> which will # invoke the template. The views and controllers will share instance # variables (as you can see above). # # == Using the layout method # # If your Views module has a <tt>layout</tt> method defined, it will be # called with a block which will insert content from your view: # # module Blog::Views # def layout # html do # head { title "My Blog "} # body { self << yield } # end # end # end module Views; include X, Helpers end # TODO: Migrations # Models is an empty Ruby module for housing model classes derived # from ActiveRecord::Base. As a shortcut, you may derive from Base # which is an alias for ActiveRecord::Base. # # module Camping::Models # class Post < Base; belongs_to :user end # class User < Base; has_many :posts end # end # # == Where Models are Used # # Models are used in your controller classes. However, if your model class # name conflicts with a controller class name, you will need to refer to it # using the Models module. # # module Camping::Controllers # class Post < R '/post/(\d+)' # def get(post_id) # @post = Models::Post.find post_id # render :index # end # end # end # # Models cannot be referred to in Views at this time. module Models autoload :Base,'camping/ar' def Y;self;end end autoload :Mab, 'camping/mab' C end
发表评论
-
更新了那个"最小的ruby飞信客户端"
2012-06-13 23:39 1135曾经的那个“最小的ruby飞信客户端” http://www. ... -
基于web飞信接口的飞信应答机器人
2010-11-25 23:08 4490fetion-robot是基于web飞信接口的飞信机器人(一小 ... -
邮件发新浪微博
2010-11-25 22:46 3771绑定邮件后,发邮件即可收发新浪微博。请先访问 http://s ... -
获取gmail新邮件---ruby版
2010-07-29 22:55 1745#! /usr/bin/ruby #author new ... -
if $0 == _FILE_
2009-11-18 09:56 950if __name__ == "__main__&q ... -
配置irb支持tab自动补全
2009-10-20 14:34 1715编辑~/.irbrc,输入下面内容即可使irb支持tab自动补 ... -
ruby-sms
2009-08-19 19:55 1170出处:http://raa.ruby-lang.org/pro ... -
A simple full-text search engine in 200 lines of Ruby
2009-08-18 23:25 897http://eigenclass.org/hiki/simp ... -
最小的ruby飞鸽客户端--仅可以发消息
2009-08-18 21:51 1050飞鸽(IPMSG)在企业局域网内应用还是非常广泛的,我本来想用 ... -
最小的ruby飞信客户端
2009-08-09 14:38 2355最小的飞信的ruby客户端,功能很简单,目前只能给自己和飞信好 ... -
ruby非阻塞式socket编程--写飞信客户端的经验总结
2009-08-07 23:27 2866最近在使用ruby编写飞信客户端时,遇到TCPSocket的阻 ... -
飞信 HTTPS入口
2009-07-27 14:02 1593require 'net/http' require ' ...
相关推荐
Camping分析PPT学习教案.pptx
In conclusion, the excessive use of electronic devices is taking a toll on our cognitive abilities due to the continuous pressure exerted on the prefrontal cortex. To alleviate this strain, it is ...
1. (B) I go camping once a month. 我一个月去野营一次。 2. (A) How often do you go skating? 你多久去滑冰一次? 3. (A) What are you going to do tomorrow? 你明天将要做什么? 4. (B) I play the violin ...
Camping Adventure Game 露营冒险游戏Unity2d儿童家庭模拟游戏项目源码C# 支持Unity版本2018.3.3f1及以上 准备好来一场真正的公路旅行周末冒险了吗?适合家庭的夏令营游戏就在这里,您可以通过许多激动人心的活动...
- This is a book. 变为 This isn’t a book. (isn’t = is not) - Sally can hear a ship. 变为 Sally can’t hear a ship. (can’t = can not) 2. 当句子中含有实义动词时,需借助助动词do或does,再加上not和...
去野营 一个新的Flutter项目。 入门 该项目是Flutter应用程序的起点。 如果这是您的第一个Flutter项目,那么有一些资源可以帮助您入门: 要获得Flutter入门方面的帮助,请查看我们的,其中提供了教程,示例,有关...
该项目是“新营地”系统的设计源码,基于Java核心技术构建,包含788个文件,涵盖376个Java源文件、110个Vue组件、91个JavaScript脚本、87个SVG矢量图形、45个XML配置文件、16个SQL数据库脚本、13个Vue模板文件、10个...
”句型来询问公园内是否有特定的自然元素,如“Is there a forest in the park?”(公园里有森林吗?)和“Is there a lake in the park?”(公园里有湖吗?)。对话中,张鹏提议去划船,进一步巩固了“go boating”...
- Who is going to see a play the day after tomorrow? (对主语提问,用who代替My father and mother) 3. 适当形式填空: - We are going to have a picnic this afternoon. (一般将来时,be going to + 动词...
4. 名词性从句的主语:"Desertification, the name for __________ happens when farm land is turned into desert, is a growing world problem."中,"what happens when farm land is turned into desert"是名词性...
1. **写作中的讨论结构**:在写作中,我们经常需要表达是否做某事,例如"I think we’d better have a discussion about whether we’ll go camping this weekend or not." 这句话展示了如何用"whether...or not...
- 另外两个翻译题目涉及到等同表达,比如"我认为野营和骑车一样好玩",英文可以表达为"I think camping is as fun as cycling.";“滑雪没有潜水危急”则译为"Skiing is less dangerous than diving." 3. 句型转换...
- 在be动词(am, is, are)后面加上not,如:I’m not going to have a picnic this afternoon. - 情态动词will后面加not,缩写成won’t,如:I won’t have a picnic this afternoon. 四、一般疑问句: - be动词...
黄石露营yellowstone-camping是黄石国家公园的露营地预订取消查找器。 这个简单的Python应用程序将不断检查API,并在您的Android或iOS设备上通过推送通知提供预订后立即通知您。 不要着急在预定的露营地中找到露营地...
第10页至第12页,引入了"Pair work",这是一种小组合作的学习活动,学生两人一组,一人提问,一人回答,模拟实际情境进行对话,如"A: Where is my _____? B: Is it _____ your desk / chair?"这样的互动练习能提高...
She will go camping in the jungle、C. She will spend 3 weeks in South Africa。问题11询问女士需要带什么,选项为A. A map、B. A tent、C. Some clothes。问题12关于谁准备餐食,选项为A. The man、B. The ...
”可以表达为"What a beautiful girl she is!" 或 "How beautiful she is!"。 2. 使用“so+形容词/副词 + that 从句”表达“如此……以至于……”,如“I was so tired that I went to sleep early.”。这个结构可以...
1. Andy is hungry. → Is Andy hungry? 2. Frank comes from England. → Does Frank come from England? 3. I can speak English. → Can you speak English? 4. We will go camping tomorrow morning. → Will ...
- "The hardest thing to learn is to be a good loser." 强调心态的重要性,"good loser"是指输得起的人。 - "My class went camping last summer." 描述过去活动,"went camping"是去露营。 5. **报纸与杂志** ...
标题“open-camping-data”指的是一个与露营相关的数据集,该数据集是以JSON格式存储的,这使得数据可以通过编程方式轻松地进行读取、处理和分析。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,...