Zend FrameworkからRailsへのプロジェクトの書き換え

約5か月前、私はzendフレームワークに縛られてレールに移動しました。 それから彼は彼のプロジェクトwww.okinfo.ruを書き直し始めました。 これですでに終了し、sloccountはプロジェクトの行数が15000から4000に減少したことを示しました。私の友人のphp開発者はサクセスストーリーを求め、その結果、この記事が誕生しました。 その中で、それがどのようだったかを説明するとともに、ルビーへの私の移行について少し話をします。


背景


www.starlook.ruの主な開発者として約2年間働いた後、私はあなたがそれが先に進む時であると理解するようになりました。 アプリケーションアーキテクチャが落ち着き、スケーリングが定められ、コードが一般的に微調整され、一般に、開発プロセス全体が明確にデバッグされました。 実際、私たちは機能を増やし続け、すでに書かれたものをサポートしました。 この時点で、楽しみのために、ジャンゴとレールを詳しく調べ始めました。 私は言語としてpythonが好きだったという事実にもかかわらず、djangoは感動しませんでした。 そして、レールとルビーでは状況は完全に異なっていました。 これは一目で愛と呼ぶことができます。 文字通り1か月の勉強の後、ルビー開発者の欠員の提案とともに私のサークルに手紙が届きましたが、これは偶然でしたが、 何らかの理由で送信者はルビーを知っていると思った。 一般的に、私はこれが運命だと決め、多くのインタビューを行った後、彼らは私を新しい場所のハックに連れて行ってくれました。

なんで?


レールを理解した後、ZFでプロジェクトを書き続けることは非常に困難でした。手でやりすぎて、ほぼすべてのタスク(タグ、ツリー、デプロイ、移行など)について独自の決定を書かなければなりませんでした。 このプロジェクトには余暇があまりないことを考えて、1石で2羽の鳥を殺して、それを書き直すことにしました。 第一に、開発とサポートを簡素化し、第二に、関連するテクノロジーに関する知識を強化することです。

環境設定


rvm.beginrescueend.com -Rubyのいくつかのバージョンのインストールとgemsetのサポート。
en.wikipedia.org/wiki/RubyGems-Gems

sudo apt-get install rubygems
gem install rails
rails s


, . .


.

. tail -f log/development.log (http://habrastorage.org/storage/29abc841/af70206c/2794fbe5/5d1f434f.png). , , , , ..

rails c


irb . . .

image

netbeans vim.

REST


habrahabr.ru/blogs/webdev/38730
guides.rubyonrails.org/routing.html

, . REST .

: pastebin.com/x0bA3siH

:

namespace :admin do
  resources :brands do
    resources :systems
  end
end


rake routes : pastebin.com/mPSvzkAJ

. :

admin_brand_systems_path(@brand) #    
admin_brand_systems_url(@brand) #    


. Zend_Controller_Router_Route_Hostname.

, . rails3 , :

#       ZF
match "/company/:id" => redirect("/companies/%{id}")


ZF Zend_Rest_Controller Zend_Rest_Route, , :

$restRoute = new Zend_Rest_Route($front, array(), array(
    'api',
    'backlog' => array('task'),
));
$router->addRoute('rest', $restRoute);


, .


guides.rubyonrails.org/action_controller_overview.html

: pastebin.com/TYhYAWEQ
: pastebin.com/seJzhYMq

. ZF, , .

( ) — ApplicationController ( ). . .

(ThinkingSphinx)


. www.okinfo.ru.

, , DSL.

define_index do
    indexes title
    indexes body
    indexes sub_categories(:title)

    has created_at
    has taggings(:tag_id), :as => :tag_ids, :facet => true
    has companies_sub_categories :sub_category_id
    has addresses :city_id
    has :calculator_page # :without => {:calculator_page => 0}
    has :site
    has :reviews_count
  end


sphinx, . :

rake ts:rebuild


:

Company.search ‘’


sphinx, . thinking-sphinx , . , .

ActiveRecord


guides.rubyonrails.org/association_basics.html
guides.rubyonrails.org/active_record_querying.html

class Company < ActiveRecord::Base
  acts_as_taggable

  devise :database_authenticatable, :registerable,
    :recoverable, :rememberable, :validatable, :trackable

  belongs_to :image
  has_many :weekly_newsletters, :class_name => 'Notice', :conditions => { :notice_type => 'weekly_newsletter' }
  has_many :addresses
  has_many :sub_categories, :through => :companies_sub_categories

  validates :site, 
    :uniqueness => true,
    :format => { :with => URI::regexp(%w(http https)) },
    :allow_blank => true
  validates :title, :presence => true, :uniqueness => true
  validates :twitter_page, :format => { :with => URI::regexp(%w(http https)) },
    :allow_blank => true

  scope :by_rating, order('ratings_sum DESC')
  scope :with_logo, where('image_id IS NOT NULL').includes(:image)


. . , orm .

State Machine


github.com/pluginaweek/state_machine

/ .. .

# ActiveRecord model
 state_machine :state, :initial => :moderate do
    state :off, :human_name => ''
    state :moderate, :human_name => ' '
    state :published, :human_name => '' do
      validates :uri, :presence => true
    end

    event :publish, :human_name => '' do
      transition :off => :published
      transition :moderate => :published
    end

    event :off, :human_name => '' do
      transition :published => :off
    end
  end


(Rake, cron)


ru.wikipedia.org/wiki/Rake


rake. , , pastebin.com/MavWT7JA. , . rake ruby. php — pake.

#     
namespace :app do
  namespace :notice do
    desc 'Weekly newsletter'
    task :weekly_for_company => :environment do
      Company.state.find_each do |company| # find_each  batch
        	last_notice = company.weekly_newsletters.last
	        next if last_notice && (Time.now - last_notice.created_at < 1.week)
        notice = company.weekly_newsletters.create
        notice.save
        CompanyMailer.weekly_newsletter(company).deliver
        sleep(1)
      end
    end
  end
end


:

rake app:notice:weekly_for_company


php, . .

Deploy (capistrano)


github.com/capistrano/capistrano/wiki
habrahabr.ru/blogs/webdev/110021

. ( ):

cap deploy:migrations


, , , , , . .

(Bundler)


gembundler.com

bundler. . , , ( ) . . : pastebin.com/50pe40Sb.

— Ancestry (use Materialized path)
— breadcrumbs_on_rails
— graticule
— acts-as-taggable-on
— paperclip
— foreigner
— rspec, factory_girl_rails, rcov
— capistrano, capistrano-ext, capistrano_colors

(Devise)


github.com/plataformatec/devise
: Omniauthable, Confirmable, Recoverable, Registerable, Rememberable, Trackable, Timeoutable, Validatable, Lockable, Encryptable, Database Authenticatable, Token Authenticatable.

. . .

(Simple_Form)


github.com/plataformatec/simple_form

ZF, Django, . . Zend_Form ( zend_form ).

<%= simple_form_for(resource, :url => company_registration_path) do |f| %>
    <%= f.input :email %>
    <%= f.input :password %>
    <%= f.input :password_confirmation %>
    <%= f.association :forma, :label_method => :title %>
    <%= f.input :title %>
    <%= f.association :sub_categories, :label_method => :title %>

    <%= f.simple_fields_for :address do |address| %>
      <%= address.association :city, :as => :select, :collection => cities(@company.address),
        :input_html => { :id => "city_id" } %>
      <%= address.input :street %>
      <%= address.input :house, :required => false %>
    <% end %>
    <%= f.submit '' %>
<% end %>


.

(Rspec, FactoryGirl, Rcov)


habrahabr.ru/blogs/testing/52929
github.com/thoughtbot/factory_girl

: pastebin.com/3tEctqmT
: pastebin.com/VmawXxbc

FactoryGirl , , , . ( ). assert’.

php. , .


guides.rubyonrails.org/action_mailer_basics.html
rusrails.ru/action-mailer-basics

rails . rails g mailer MailerName. . . : CompanyMailer.after_registration(@company).deliver

. Rails environment , ZF, : , , env. dev ( ) .

( ):

describe ColumnistMailer do
  describe "after_registration" do
    let(:mail) { ColumnistMailer.after_registration }

    it "renders the headers" do
      mail.subject.should eq("After registration")
      mail.to.should eq(["to@example.org"])
      mail.from.should eq(["from@example.com"])
    end

    it "renders the body" do
      mail.body.encoded.should match("Hi")
    end
  end
end



github.com ( ) — .
newrelic.com — .
hoptoadapp.com/pages/home — . , php. ( ), — , , . , . , , . . , must have. js.

github.com/jdpace/errbit (Errbit is an open source, self-hosted error catcher. It is Hoptoad API compliant so you can just point the Hoptoad notifier at your Errbit server if you are already using Hoptoad).
php github.com/rich/php-hoptoad-notifier


. . , .

, , . , .

Source: https://habr.com/ru/post/J112966/


All Articles