πŸ“œ ⬆️ ⬇️

Rewrite project from Zend Framework to Rails

About five months ago, I tied up with the zend framework and moved onto rails. Then he began to rewrite his project www.okinfo.ru . Now it is already finished and sloccount showed that the number of lines in the project decreased from 15,000 to 4,000. My familiar php developers asked for a success story and eventually this article was born. In it, I will describe how it was, as well as talk a little about my transition to ruby.


Prehistory


Having worked as the main developer of www.starlook.ru for about two years, I reached a point where you understand that it is time to move on. The architecture of the application is well-established, scaling is inherent, the code as a whole is fine and in general the whole development process was clear and debugged. In fact, we continued to increase the functionality and maintain already written. At this time for interest, I began to look closely at django and rails. Despite the fact that the python as a language I liked, but that django was not impressed. And with the rails and cut the situation was completely different. It can be called love at first sight. And literally after a month of study, a letter came to My Circle offering a vacancy for a ruby ​​developer, although it was an accident, since sending for some reason thought that I know ruby. In general, I decided that this was fate, and after passing a bunch of interviews, they still took me to chop for a new place.

What for?


After getting acquainted with the rails, it was very difficult to continue writing a project on ZF, too much had to be done by hand and practically for each task (tags, trees, deploy, migrations, etc.) to write our own solutions. Given that there is not much free time on the project, it was decided to rewrite it, killing two birds with one stone. Firstly, to simplify your development and support, and secondly, to tighten the knowledge of the relevant technologies.
')

Setting up the environment


rvm.beginrescueend.com - installation of several versions of ruby ​​and gemset support.
ru.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/112966/


All Articles