рдХреНрд░реИрдореНрдк рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдХреА рд░реВрдкрд░реЗрдЦрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдкреНрд░рддреАрдХ рдирд╛рдЗрдХ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ 37signals рдореЗрдВ рдПрдХ рдбреЗрд╡рд▓рдкрд░ рдФрд░ рд░реЗрд▓ рдХреЛрд░-рдЯреАрдо рдХрд╛ рд╕рджрд╕реНрдп рд╣реИред рдпрд╣ рдлреНрд░реЗрдорд╡рд░реНрдХ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рдХреЗ рдмреАрдЪ рджреНрд╡рд┐рджрд┐рд╢ рд╕рдВрдЪрд╛рд░ рдХреЗ рдЖрдпреЛрдЬрди рдХреЗ рд▓рд┐рдП рд╣реИ рдФрд░ рдЗрд╕рдореЗрдВ WebSockets рдФрд░ рд╕рд░реНрд╡рд░-рд╕реЗрдВрдЯреЗрдб рдЗрд╡реЗрдВрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд╕рдорд░реНрдерди рд╣реИред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдЗрд╕ рдЙрдкрдХрд░рдг рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдореБрдЦреНрдп рдмрд╛рддреЛрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдЗрд╕рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЛ рд╕рдордЭрдиреЗ рдФрд░ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рд╢рд╛рдпрдж рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдореБрдЦреНрдп рджреЛрд╖ рд▓реЗрдЦреЛрдВ рдФрд░ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рдПрдХ рдЫреЛрдЯреА рд╕рдВрдЦреНрдпрд╛ рд╣реИ,
рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рдХреЗрд╡рд▓ рджрд╕реНрддрд╛рд╡реЗрдЬ рдХрд╛ рдПрдХ рдЫреЛрдЯрд╛ рдкреГрд╖реНрда рд╣реИ рдФрд░
рдЬреАрдердм рдкрд░ рд╡рд╛рд╕реНрддрд╡рд┐рдХ
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛрдб рд╣реИ ред рд╡рд╣рд╛рдВ рд╕реЗ, рдореВрд▓ рд░реВрдк рд╕реЗ, рдиреАрдЪреЗ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╕рдм рдХреБрдЫ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░
рдХреНрд░реИрдореНрдк EventMachine, ActiveSupport, рдФрд░ Thor рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ рдФрд░ рдПрдХ Thin рдпрд╛ Rainbows рд╕рд░реНрд╡рд░ рдкрд░ рдЪрд▓рддрд╛ рд╣реИред
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - рдХреНрд░реИрдореНрдк :: рдЬреЗрдирд░реЗрдЯрд░ :: Application.start рдХреЛ рдмрд╛рдЗрдирд░реА рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреНрд▓рд╛рд╕ рдХреЗ рд╕рднреА рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рддрд░реАрдХреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рдирдХреЗ рдирд╛рдо: create_root, create_config, create_stodels рдЦреБрдж рдХреЗ рд▓рд┐рдП рдмреЛрд▓рддреЗ рд╣реИрдВред
рдЕрдЧрд▓рд╛, рдЬрдм рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, EventMachine рдЪрдХреНрд░ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рд╕рднреА рдШрдЯрдирд╛рдУрдВ рдХреЛ рдкрдХрдбрд╝рддрд╛ рд╣реИ, рдЙрдирд╕реЗ рдЬреБрдбрд╝реА рдХреЙрд▓рдмреИрдХ рд▓реЙрдиреНрдЪ рдХрд░рддрд╛ рд╣реИред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдХреНрд░реИрдореНрдк рдХреЗрд╡рд▓ рд░реЗрдирдмреЛ рдпрд╛ рдерд┐рди (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ) рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдИрдПрдо рдкрд░ рдмрдиреЗ рд╣реЛрддреЗ рд╣реИрдВред
рдХреНрд░реИрдореНрдк рджрд░реНрд╢рди рдХреА рдХреБрдВрдЬреА рдПрдХреНрд╢рди (рдХреНрд▓рд╛рд╕ рдПрдХреНрд╢рди рдФрд░ рдПрдмреНрд╕рдЯреНрд░реИрдХреНрдЯ) рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рд╣реИред рдХрд╛рд░реНрд░рд╡рд╛рдИ рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рдФрд░ рд░реЗрд▓ рдХреЗ рдмреАрдЪ рдПрдХ рдХреНрд░реЙрд╕ рд╣реИ (рдпрджрд┐ рдпрд╣ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдФрд░ рддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдкрд░реЗрдЦрд╛рдУрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рдирд╛ рдЙрдЪрд┐рдд рд╣реИ)ред рдкреНрд░рддреНрдпреЗрдХ рдХреНрд░рд┐рдпрд╛ рдПрдХ рдЕрдиреБрд░реЛрдз рдпрд╛, рдЕрдзрд┐рдХ рд╕рд╣реА рдврдВрдЧ рд╕реЗ, рдПрдХ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрд┐рдВрджреБ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реЗрдм рд╕реЙрдХреЗрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ рдХрдиреЗрдХреНрд╢рди рдХреЛ рдПрдХ рдЕрдиреБрд░реЛрдз рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдПрдХ рдирд┐рдпрдорд┐рдд рдЕрдиреБрд░реЛрдз рд╕рд╢рд░реНрдд рд░реВрдк рд╕реЗ 4 рдЪрд░рдгреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рд╣реИ:
- рдЕрдиреБрд░реЛрдз рдХрд╛ рдкреНрд░рд╛рд░рдВрдн - рдкрд╣рд▓реЗ_рд╕реНрдЯрд╛рд░реНрдЯ рдХреЙрд▓рдмреИрдХ рдХрд╣рд▓рд╛рддреЗ рд╣реИрдВред
рдЗрд╕ рд╕реНрддрд░ рдкрд░, рд╣реЗрдбрд░ рдЕрднреА рддрдХ рдирд╣реАрдВ рднреЗрдЬреЗ рдЧрдП рд╣реИрдВ, рдЖрдк рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдХрд╣реАрдВ рднреА рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЕрдиреБрд░реЛрдз рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд░рд▓реЗрдЦрди рдХрд╛ рдХрд╣рдирд╛ рд╣реИ рдХрд┐ рдЕрдиреБрд░реЛрдз рдпрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рдЕрдиреБрдорддрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ_рд╕реНрдЯрд╛рд░реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЧрдИ рд╣реИред рдХрдИ рддрд░реАрдХреЛрдВ рдХреЛ рдкрд╣рд▓реЗ_рд╕реНрдЯрд╛рд░реНрдЯ рдкрд░ рд▓рдЯрдХрд╛ рджрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рдиреНрд╣реЗрдВ рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдХреНрд░рдорд╢рдГ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдЬрд╛рд░реА рд░рдЦрдиреЗ рдпрд╛ рдмрд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдЬ рдпрд╛ рдкрдбрд╝рд╛рд╡ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред - рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдкреНрд░рд╛рд░рдВрдн - response_with рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИред
рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╢реАрд░реНрд╖рдХреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЖрдорддреМрд░ рдкрд░ рдХреЛрдб 200 рдХреЗ рд╕рд╛рде рдорд╛рдирдХ рд╢реАрд░реНрд╖рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
def build_headers status, headers = respond_to?(:respond_with, true) ? respond_with.dup : [200, {'Content-Type' => 'text/html'}] headers['Connection'] ||= 'keep-alive' [status, headers] end
- рдЕрдиреБрд░реЛрдз рд╢реБрд░реВ рд╣реБрдЖ - on_start рдЪрд▓ рд░рд╣рд╛ рд╣реИред
рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдВ рдЙрддреНрддрд░ рдХрд╛ рдЧрдарди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрдк on_start рдкрд░ рдХрдИ рдХреЙрд▓рдмреИрдХ рднреА рд▓рдЯрдХрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рдиреНрд╣реЗрдВ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд░реЗрдВрдбрд░ рд╡рд┐рдзрд┐ рдХреЛ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░ рдХреЙрд▓ рдХрд░ рд╕рдХрддрд╛ рд╣реИред - рдЕрдиреБрд░реЛрдз рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИ - on_finish рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рдмрдирдиреЗ рдХреЗ рдмрд╛рдж рдЗрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдХреБрдЫ рдХреЛ рд╕рд╛рдл рдХрд░рдиреЗ, рдЦреБрд▓реЗ рдХрдиреЗрдХреНрд╢рди рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдЖрджрд┐ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИред
рдЗрд╕ рдврд╛рдВрдЪреЗ рдХреА рдЦреВрдиреА рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ WebSockets рд╣реИрдВред рд╡реЗ рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рд╕рдорд░реНрдерд┐рдд рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдПрдХ рдЕрд▓рдЧ рд╕рд░реНрд╡рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рд╡реЗрдм рд╕реЙрдХреЗрдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдЖрдкрдХреЗ рдПрдХреНрд╢рди рдореЗрдВ on_data рд╣реИрдВрдбрд▓рд░ рд╡рд┐рдзрд┐ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рдЕрдиреНрдп рд╕рднреА рдореБрджреНрджреЛрдВ рдХреЛ рд╕рд░реНрд╡рд░ рджреНрд╡рд╛рд░рд╛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬреЛ get_data EM рд╡рд┐рдзрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдХрдиреЗрдХреНрд╢рди рд╕реЗ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ:
рдкрддрд▓рд╛
callback = @request.env[Thin::Request::WEBSOCKET_RECEIVE_CALLBACK] callback.call(data) if callback
рдЗрдВрджреНрд░рдзрдиреБрд╖
callback = @env[WEBSOCKET_RECEIVE_CALLBACK] callback.call(data) if callback
рд╣рдо рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдХреЗ рд╕рд╛рде рдЦрддреНрдо рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝реЗрдВрдЧреЗред
рдХреЗ рдЙрдкрдпреЛрдЧ
рдХреНрд░реИрдореНрдк рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдлрд╛рдЗрдмрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд░реВрдмреА рд╢рд╛рдЦрд╛рдУрдВ 1.9 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЬрд╛рддреА рд╣реИ, рдЬреЛ рдХрд┐ рдЕрдЧрд░ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЖрд░рд╡реАрдПрдо рдпрд╛ рд░реЗрдВрдмрд╡ рдЬреИрд╕реЗ рдЙрдкрдХрд░рдг рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ 1.8.7 рдкрд░ рдмреИрдареЗ рд╣реЛрдиреЗ рдкрд░ рднреА рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред
рдХреНрд░реИрдореНрдк рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рд╕реЗ рдХреЛрдИ рдХрдард┐рдирд╛рдИ рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП:
gem install cramp
рдЕрдЧрд▓рд╛, рднрд╛рдЧреЛ
cramp new project_name
рдФрд░ рдЙрдкрд░реЛрдХреНрдд рдереЛрд░ рдЖрдкрдХреЗ рдЖрд╡реЗрджрди рдХрд╛ рдХрдВрдХрд╛рд▓ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред
рдлрд┐рд░, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рд╣реЛрдиреЗ рдХреЗ рдирд╛рддреЗ, рд╣рдо рдмрдВрдбрд▓ рдЗрдВрд╕реНрдЯреЙрд▓ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рд╕рднреА рдЖрд╢реНрд░рд┐рддреЛрдВ рдХреЛ рдХрд╕ рджреЗрдЧрд╛ред
рд╣рдордиреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдХрд╛рд░реНрд░рд╡рд╛рдИ - рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рдХреНрд░рд┐рдпрд╛рдПрдВ / home_action.rb рдмрдирд╛рдИ рд╣реИ:
class HomeAction < Cramp::Action def start render "Hello World!" finish end end
рдЬреИрд╕рд╛ рдХрд┐ рдЗрд╕ рдХреЛрдб рд╕реЗ рд╕рдордЭрдирд╛ рдЖрд╕рд╛рди рд╣реИ, рд╕реНрдЯрд╛рд░реНрдЯ рд╣реИрдВрдбрд▓рд░ "рд╣реИрд▓реЛ рд╡рд░реНрд▓реНрдб!" рд▓рд╛рдЗрди рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрдиреБрд░реЛрдз рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рд╣рдо рд╕рд░реНрд╡рд░ рдХреЛ рд╢реБрд░реВ рдХрд░рдХреЗ рдЗрд╕ рдзрд╛рд░рдгрд╛ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
bundle exec thin start
рдФрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛрдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ, рдерд┐рди рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ config.ru рдлрд╛рдЗрд▓ рдХреЛ рд╕реНрд╡рдпрдВ рдЙрдард╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдирд┐рд╖реНрдард╛ рдХреЗ рд▓рд┐рдП, рдЖрдк рдЗрд╕ рд░реВрдк рдореЗрдВ рдЗрд╕ рдХрдорд╛рдВрдб рдХреЛ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ:
bundle exec thin --max-persistent-conns 1024 --timeout 0 -R config.ru start
рдпрд╛
bundle exec thin --max-persistent-conns 1024 --timeout 0 -V -R config.ru start
рдХреНрд░рд┐рдпрд╛ рдореЛрдб рдореЗрдВ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдПред
рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рд╣рдореЗрдВ рд╕реАрдзреЗ рд╕реНрдерд┐рд░ рдкрд╛рда рдФрд░ HTML рдорд╛рд░реНрдХрдЕрдк рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╕реНрдерд┐рдд рд╡рд┐рдЪрд╛рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди / рд╡рд┐рдЪрд╛рд░ рдлрд╝реЛрд▓реНрдбрд░ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕рдореЗрдВ рдирд┐рдореНрди рд╕рд░рд▓ рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде index.erb рдлрд╝рд╛рдЗрд▓:
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>Hello World!</title> <link rel="stylesheet" type="text/css" href="stylesheets/styles.css" /> </head> <body> <h1>Hello World!</h1> </body> </html>
рдФрд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ / рд╕реНрдЯрд╛рдЗрд▓рд╢реАрдЯ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ, рдХреЗрд╡рд▓ рдПрдХ рдкрдВрдХреНрддрд┐ рдХреЗ рд╕рд╛рде style.css рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ:
h1{color:red}
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдПрд░реНрдм рдЗрдВрдЬрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЖрдк Haml, рд╕реНрд▓рд┐рдо рдпрд╛ рдЬреЛ рдХреБрдЫ рднреА рдЖрдкрдХреЗ рджрд┐рд▓ рдХреА рдЗрдЪреНрдЫрд╛ рд╣реИ, рдкрд╣рд▓реЗ рдЬреЗрдордлрд╛рдЗрд▓ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рд╕рд╣рд┐рдд рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
Erb рдлрд╝рд╛рдЗрд▓ рд╕реЗ рд╕рд╛рдордЧреНрд░реА рд░реЗрдВрдбрд░ рдХрд░рдиреЗ рдХреА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП, рдкрд╣рд▓реЗ рд╣рдо рдЗрдВрдЬрди рдХреЛ рд╕реНрд╡рдпрдВ рдХрдиреЗрдХреНрдЯ рдХрд░реЗрдВрдЧреЗ:
require 'erb'
рдЖрдк рдЗрд╕ рд▓рд╛рдЗрди рдХреЛ рд╕реНрд╡рдпрдВ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдкреВрд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ Erb рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди.rb рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдирд╛ рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред
рдЕрдЧрд▓рд╛, home_action.rb рдмрджрд▓реЗрдВ:
class HomeAction < Cramp::Action def start page = ERB.new(File.read(ExampleProject::Application.root('app/views/index.erb'))) render page.result(binding) finish end end
рдпрд╣рд╛рдБ ExampleProject рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╛ рдирд╛рдо рд╣реИред рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реА рд╕реАрдПрд╕рдПрд╕ рдХрд╣рд╛рдВ рд╣реИ? рд╕реАрдПрд╕рдПрд╕ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдЙрдкрд▓рдмреНрдз рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ config.ru рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдпреБрдХреНрдд рдлрд╝реЛрд▓реНрдбрд░ рд╕реЗ рд╕реНрдерд┐рд░ рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╡рд┐рддрд░рдг рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
use Rack::Static, :urls => ["/javascripts", "/stylesheets"], :root => CrampArticle::Application.root(:public)
рдЦреИрд░, рд╢реАрд░реНрд╖рдХ рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рд▓рд╛рд▓ рд╣реЛ рдЧрдпрд╛ред
рдЕрдм рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдирдпрд╛ рдПрдХреНрд╢рди WsAction рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬреЛ рд╡реЗрдм рд╕реЙрдХреЗрдЯреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд╕рд╛рде рд╕рдВрд╡рд╛рдж рдХрд░реЗрдЧрд╛ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдЗрдП рдЬрд╛рдиреЗрдВ рдХрд┐ рд╡реЗрдм рд╕реЙрдХреЗрдЯ рдХрд┐рд╕ рд╕рд░реНрд╡рд░ рдкрд░ рдХрд╛рдо рдХрд░реЗрдЧрд╛:
Cramp::Websocket.backend = :thin
рдлрд┐рд░ рд╕реЗ, рд░реЗрдирдмреЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдерд┐рди рдХреЗ рдмрдЬрд╛рдп рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдореИрдВ рдерд┐рди рдХреЛ рдХреЗрд╡рд▓ рдЗрд╕рд▓рд┐рдП рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЧрд┐рддреВрдм рдкрд░ рд╕реНрдерд┐рдд рд╣реИ рдФрд░ рдЗрд╕ рдкрд░ рдЕрдзрд┐рдХ рдбреЙрдХ рд╣реИрдВред
рдЕрдЧрд▓рд╛, рдРрдк / рдПрдХреНрд╢рди рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ, ws_action.rb рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдВ рдФрд░ рдЗрд╕рдореЗрдВ рдирд┐рдореНрди рдХреЛрдб рдЬреЛрдбрд╝реЗрдВ:
class WsAction < Cramp::Action self.transport = :websocket on_data :process_data def process_data(data) render "Hello" if /^hello/i =~ data end end
рдпрд╣ рд▓рд╛рдЗрди рд╕реЗрд▓реНрдл рдЯреНрд░рд╛рдиреНрд╕рдкреЛрд░реНрдЯ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред = websocket to the text рдлрд┐рд░ рд╣рдо рдПрдХ рд╕рдВрджреЗрд╢ рд╣реИрдВрдбрд▓рд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рд╕рдВрджреЗрд╢ рднреЗрдЬрддреЗ рд╣реИрдВ рдпрджрд┐ рдПрдХ рд╕рдВрджреЗрд╢ "рд╣реИрд▓реЛ" рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реБрдЖ рд╣реИред
рдЗрд╕ рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдкрд╣рд▓реЗ рдЖрдкрдХреЛ WsAction рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╛рд░реНрдЧ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ (рдлрд╝рд╛рдЗрд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ / path.rb):
get('socket/').to(WsAction)
рдФрд░ рджреВрд╕рд░реА рдмрд╛рдд, рд╣рдо рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛрдб рдХреЛ index.erb рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ:
<script type="text/javascript"> var ws = new WebSocket("ws://localhost:3000/socket/"); ws.onopen = function() { ws.send("Hello!"); }; ws.onmessage = function(e) { alert(e.data); }; ws.onclose = function() { alert("closed"); }; </script>
рдлрд╝рд╛рдпрд░рдлрд╝реЙрдХреНрд╕ рдХреЗ рд▓рд┐рдП, WebSocket рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг MozWebSocket рджреНрд╡рд╛рд░рд╛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдП рдЧрдП рд╣реИрдВред рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛрдб рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ рдФрд░ рдХреЗрд╡рд▓ рдкреНрд░рджрд░реНрд╢рди (рд╕рд░реНрд╡рд░ рдХреЗ рд░реВрдк рдореЗрдВ) рдХреЗ рд▓рд┐рдП рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдлреНрд▓реИрд╢ рдкрд░ рд╡реЗрдм рд╕реЙрдХреЗрдЯ рдХреНрд▓рд╛рд╕ рдпрд╛ рдкреГрд╖реНрдарднреВрдорд┐ рдХреЗ рд▓рд┐рдП рд╢рд░реНрдд рдЗрд╕рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдирд╣реАрдВ рдХрд░рддреА рд╣реИ, рдЗрд╕реЗ рд╕реНрд╡рдпрдВ рдХрд░реЗрдВред
рдпрд╣ рд╕рдм рд╣реИ, рдпрджрд┐ рдЖрдк рдХреНрд░реИрдореНрдк рдХрд╛ рдЕрдзрд┐рдХ рдЧрд╣рд░рд╛рдИ рд╕реЗ рдЕрдзреНрдпрдпрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдХреБрдЫ рдФрд░ рд╡рд┐рд╖рдп рд╣реИрдВ рдЬреЛ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рдереЗ: рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рдИрд╡реЗрдВрдЯреНрд╕, рдлрд╛рдпрд░рдмреНрд░реЛ, ActiveRecord рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ред рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЖрдк рдмрдЧ рд░рд┐рдкреЛрд░реНрдЯ рдХреЗ рд╕рд╛рде рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЬреАрдердм рдкрд░ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдЦреАрдВрдЪ рд╕рдХрддреЗ рд╣реИрдВред
рд╕рдВрдмрдВрдзрд┐рдд рд▓рд┐рдВрдХ
рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛрдб
github.com/lifo/crampрдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реНрдерд▓ (рдкреНрд░рд▓реЗрдЦрди, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ)
cramp.inEventMachine рдХреНрдпрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВ
github.com/eventmachine/eventmachine/wikiрдРрдВрдарди рдХреЗ рд╕рд╛рде рд╡реЗрдмрд╕реНрдХреИрдЯ
vinsol.com/blog/2011/05/09/websockets-with-crampрдХреНрд░реИрдореНрдк рдФрд░ рд╡реЗрдмрд╕реНрдХреЗрдЯреНрд╕ рдкрд░ рдПрдХ рдФрд░ рдЫреЛрдЯрд╛ рд▓реЗрдЦ
boldr.net/html5-websockets-cramp