Giter VIP home page Giter VIP logo

rails-style-guide's Introduction

“ロールモデルが重要なのだ。”
-- アレックス・マーフィー巡査 / 映画『ロボコップ』の登場人物

このガイドの目的は、Ruby on Rails 4 開発における コーディングスタイルのベストプラクティスを提供することです。すでに有志によって作成されたRuby coding style guideの補足資料にあたります。

記載内容の一部は Rails 4.0 以上のみを対象としています。

PDF形式やHTML形式のコピーはTransmuterを使って作成できます。

以下の言語の翻訳が利用可能です:

The Rails Style Guide

このガイドは、Rails開発の実務におけるコーディングスタイルのベストプラクティスを目指したものです。開発における理想論は多くありますが、このガイドはあくまで実務での利用に役立つことを目的としています。このガイドの内容は絶対ではありませんが、非常に多くのRails開発者のフィードバックや資料を基にして書かれたものです。ここで改めて、彼らへ多大な感謝を示します。

目次

Configuration

  • アプリケーション起動時の処理をカスタマイズしたい場合は、 config/initializers 配下にその処理を記述したコードを配置しましょう。config/initializers 配下のコードはアプリケーション起動時に実行されます。 [link]

  • gem の初期化に必要なコードは、gem 毎に作成しましょう。また、そのファイルの名前は gem の名前と同じにしましょう。例えば、 carrierwave.rbactive_admin.rbなどです。 [link]

  • Railsには3つの環境(development、test、 production)がありますが、環境毎に適切な設定をしましょう。 ( config/environments/配下にそれぞれの環境に対応した設定ファイルが配置してあります。) [link]

    • もしプリコンパイルを行う場合は、追加するアセット名を明記しましょう。:

      # config/environments/production.rb
      # Precompile additional assets (application.js, application.css,
      #and all non-JS/CSS are already added)
      config.assets.precompile += %w( rails_admin/rails_admin.css rails_admin/rails_admin.js )
  • 設定をすべての環境に適用したい場合は、 config/application.rb に記述しましょう. [link]

  • production環境と同環境の staging 環境を作成しておきましょう。 [link]

Routing

  • もしRESTfulなresourceにアクションを追加する場合(そのようなアクションが本当に必要かはわかりませんが)、 membercollection を利用しましょう。 [link]

    # 悪い例
    get 'subscriptions/:id/unsubscribe'
    resources :subscriptions
    
    # 良い例
    resources :subscriptions do
      get 'unsubscribe', on: :member
    end
    
    # 悪い例
    get 'photos/search'
    resources :photos
    
    # 良い例
    resources :photos do
      get 'search', on: :collection
    end
  • 複数のmember/collectionを定義しなければいけない場合は、ブロック構文を利用しましょう。[link]

    resources :subscriptions do
      member do
        get 'unsubscribe'
        # more routes
      end
    end
    
    resources :photos do
      collection do
        get 'search'
        # more routes
      end
    end
  • ActiveRecordのモデル間の関連を表現するには、入れ子型でルートを定義すると分かりやすいでしょう。[link]

    class Post < ActiveRecord::Base
      has_many :comments
    end
    
    class Comments < ActiveRecord::Base
      belongs_to :post
    end
    
    # routes.rb
    resources :posts do
      resources :comments
    end
  • 関連する アクション・ルートをまとめるには namespaceを利用しましょう。[link]

    namespace :admin do
      # Directs /admin/products/* to Admin::ProductsController
      # (app/controllers/admin/products_controller.rb)
      resources :products
    end
  • Railsに昔あった古いルーティング記法は絶対に利用しないようにしましょう。この記法を利用した場合、すべてのアクションへのすべてのGETリクエストを許可してしまいます。[link]

    # 非常に悪い例
    match ':controller(/:action(/:id(.:format)))'
  • match を利用しないようにしましょう。もし利用する必要がある場合は、アクション毎に :via オプションで[:get, :post, :patch, :put, :delete]を指定しましょう。 [link]

Controllers

  • ビジネスロジックは controller でなく model に書きましょう。controller の役割は、view層にデータを渡すこと、またはview層からデータを受け取ることのいずれかのみです。それ以外のコードは controller に記述しないようにしましょう。[link]

  • (理想論ですが)すべての controller は find と new 以外のメソッドはひとつ程度に留められるようにしましょう。[link]

  • controller と view の間でやりとりするインスタンス変数は2つまでに留めておきましょう。[link]

Models

  • ActiveRecord を継承しないモデルも導入しましょう。 [link]

  • モデルの名前は、意味が通じてなおかつ短いものにしましょう。その際には省略語は利用しないようにしましょう。 [link]

  • ActiveRecordのような振る舞い(validationなど)が必要なモデルには、ActiveAttr のような gem を使いましょう. [link]

    class Message
      include ActiveAttr::Model
    
      attribute :name
      attribute :email
      attribute :content
      attribute :priority
    
      attr_accessible :name, :email, :content
    
      validates :name, presence: true
      validates :email, format: { with: /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i }
      validates :content, length: { maximum: 500 }
    end

    詳細な例はRailsCast on the subjectに譲ります。

ActiveRecord

  • データベースの操作を自由に出来ない等、特別な理由がない限り、ActiveRecord の初期値(テーブル名、主キー等)を変更しないようにしましょう。 [link]

    # 悪い例
    class Transaction < ActiveRecord::Base
      self.table_name = 'order'
      ...
    end
  • has_manyvalidatesなどはクラス定義の最初の方に記述しましょう。(satour注:本文と例が一致していません@原文) [link]

    class User < ActiveRecord::Base
      # 一番上にデフォルト・スコープを記述する。
      default_scope { where(active: true) }
    
      # 定数を記述する。
      COLORS = %w(red green blue)
    
      # attr関連のマクロを記述する。
      attr_accessor :formatted_date_of_birth
    
      attr_accessible :login, :first_name, :last_name, :email, :password
    
      # アソシエーションに関するマクロを記述する。
      belongs_to :country
    
      has_many :authentications, dependent: :destroy
    
      # ヴァリデーションに関するマクロを記述する。
      validates :email, presence: true
      validates :username, presence: true
      validates :username, uniqueness: { case_sensitive: false }
      validates :username, format: { with: /\A[A-Za-z][A-Za-z0-9._-]{2,19}\z/ }
      validates :password, format: { with: /\A\S{8,128}\z/, allow_nil: true}
    
      # コールバックを記述する。
      before_save :cook
      before_save :update_username_lower
    
      # 上記以外のマクロがある場合、コールバックの下に続けて記述する。
    
      ...
    end
  • なるべくhas_and_belongs_to_manyよりhas_many :throughを利用しましょう。has_many :through を使うと model を join する際に属性やヴァリデーションを利用することが出来ます。 [link]

    # あまり良くない例
    class User < ActiveRecord::Base
      has_and_belongs_to_many :groups
    end
    
    class Group < ActiveRecord::Base
      has_and_belongs_to_many :users
    end
    
    # 良い例
    class User < ActiveRecord::Base
      has_many :memberships
      has_many :groups, through: :memberships
    end
    
    class Membership < ActiveRecord::Base
      belongs_to :user
      belongs_to :group
    end
    
    class Group < ActiveRecord::Base
      has_many :memberships
      has_many :users, through: :memberships
    end
  • なるべくread_attribute(:attribute)よりself[:attribute]を利用しましょう。 [link]

    # 悪い例
    def amount
      read_attribute(:amount) * 100
    end
    
    # 良い例
    def amount
      self[:amount] * 100
    end
  • なるべくwrite_attribute(:attribute, value)よりself[:attribute] = valueを利用しましょう。 [link]

    # 悪い例
    def amount
      write_attribute(:amount, 100)
    end
    
    # 良い例
    def amount
      self[:amount] = 100
    end
  • "sexy" validations を利用しましょう。 [link]

    # 悪い例
    validates_presence_of :email
    
    # 良い例
    validates :email, presence: true
  • 独自のヴァリデーションが2回以上呼び出される場合、もしくは独自のヴァリデーションが正規表現を含む場合は、ファイルとして切り出しましょう。 [link]

    # 悪い例
    class Person
      validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i }
    end
    
    # 良い例
    class EmailValidator < ActiveModel::EachValidator
      def validate_each(record, attribute, value)
        record.errors[attribute] << (options[:message] || 'is not a valid email') unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
      end
    end
    
    class Person
      validates :email, email: true
    end
  • 独自のヴァリデーション・ファイルはapp/validatorsを作成し、その配下に配置しましょう。 [link]

  • 独自のヴァリデーションを使って複数のアプリケーションをメンテナンスしている場合、もしくはそのヴァリデーションが汎用的な内容である場合、gem 化することを検討しましょう。 [link]

  • 名前付きスコープを取り入れましょう。 [link]

    class User < ActiveRecord::Base
      scope :active, -> { where(active: true) }
      scope :inactive, -> { where(active: false) }
    
      scope :with_orders, -> { joins(:orders).select('distinct(users.id)') }
    end
  • 名前付きスコープがラムダ式で定義されており、かつ引数が複雑になってきた際には、スコープ名と同名のActiveRecord::Relationオブジェクトを返すクラスメソッドを作成することが望ましいです。そうすることで記述を簡潔にすることができます。 [link]

    class User < ActiveRecord::Base
      def self.with_orders
        joins(:orders).select('distinct(users.id)')
      end
    end
  • update_attributeupdate_attributesと異なり、モデルのヴァリデーション実行をスキップするので、利用する際は気をつけましょう。 [link]

  • ユーザー・フレンドリーな URL を用意しましょう。下記に例を示します。 [link]

    • ここでは、to_param を上書きします。このメソッドはRailsによるURL作成に使用されます。デフォルトの実装ではレコードのidString型で返します。

      class Person
        def to_param
          "#{id} #{name}".parameterize
        end
      end
    • to_paramの返り値をURL-friendlyな値にするために, 文字列をparameterize します。parameterizeではオブジェクトをActiveRecordのfindメソッドで検索できるようにする為、idを文字列の一番先頭に置きます。

    • friendly_idという gem を利用しましょう。idのかわりに model の他の属性を使って、読みやすいURLを生成することが出来ます。

      class Person
        extend FriendlyId
        friendly_id :name, use: :slugged
      end

    より詳細な内容は gem documentation に譲ります。

  • ActiveRecordのオブジェクトに対して繰り返し処理を行う場合は、find_eachを利用しましょう。(allなどで)DBから取得したレコードセットを直接繰り返し処理させる場合、すべてのオブジェクトを即時にインスタンス化することが求められ、大量にメモリを消費します。find_eachはインスタンス化を逐次処理にできるため、メモリ量の消費を抑制することが出来ます。 [link]

    # 悪い例
    Person.all.each do |person|
      person.do_awesome_stuff
    end
    
    Person.where('age > 21').each do |person|
      person.party_all_night!
    end
    
    # 良い例
    Person.find_each do |person|
      person.do_awesome_stuff
    end
    
    Person.where('age > 21').find_each do |person|
      person.party_all_night!
    end
  • Rails creates callbacks for dependent associations により、 before_destroyにはprepend: trueオプションを付けましょう。(satour注:リンク先の内容がタイトルから連想される内容と異なる。またリンク先のissueはcloseされている。)

    # 悪い例 (super_admin? が true でもrolesが自動的にdeleteされる。)
    has_many :roles, dependent: :destroy
    
    before_destroy :ensure_deletable
    
    def ensure_deletable
      fail "Cannot delete super admin." if super_admin?
    end
    
    # 良い例
    has_many :roles, dependent: :destroy
    
    before_destroy :ensure_deletable, prepend: true
    
    def ensure_deletable
      fail "Cannot delete super admin." if super_admin?
    end

ActiveRecord Queries

  • SQLインジェクション攻撃を防ぐため、 クエリの文字列の中で式を展開するのはやめましょう。 [link]

    # bad - paramがエスケープされず、SQLインジェクションの可能性が残る。
    Client.where("orders_count = #{params[:orders]}")
    
    # good - paramがエスケープされる
    Client.where('orders_count = ?', params[:orders])
  • クエリのなかで2つ以上のプレースホルダを使う場合は、 名前付きプレースホルダを利用しましょう。 [link]

    # okish
    Client.where(
      'created_at >= ? AND created_at <= ?',
      params[:start_date], params[:end_date]
    )
    
    # good
    Client.where(
      'created_at >= :start_date AND created_at <= :end_date',
      start_date: params[:start_date], end_date: params[:end_date]
    )
  • idを指定してひとつのレコードを取得する場合は、whereよりfindを使いましょう。 [link]

    # bad
    User.where(id: id).take
    
    # good
    User.find(id)
  • 複数の属性を指定してひとつのレコードを取得する場合は、whereよりfind_byを使いましょう。

[link]

# bad
User.where(first_name: 'Bruce', last_name: 'Wayne').first

# good
User.find_by(first_name: 'Bruce', last_name: 'Wayne'))
  • 大量のレコードを処理しなければいけない場合は、find_eachを使いましょう。 [link]

    # bad - すべてのレコードを一度に読み込む
    # users テーブルに数千行のレコードがあった場合、

この書き方では非常に非効率になる。 User.all.each do |user| NewsMailer.weekly(user).deliver_now end

good - バッチのなかでレコードが読み込まれる

User.find_each do |user| NewsMailer.weekly(user).deliver_now end


* <a name="where-not"></a>
SQLのようにクエリを記述する場合、`where.not`を使った方がよいケースがあります。
<sup>[[link](#where-not)]</sup>

```Ruby
# bad
User.where("id != ?", id)

# good
User.where.not(id: id)

Migrations

  • schema.rb (または structure.sql) は必ずバージョン管理しましょう。 [link]

  • 最新のスキーマで空のデータベースを作る際には、rake db:migrateでなくrake db:schema:loadを利用しましょう。 [link]

  • フィールドの初期値の設定処理は、アプリケーションの中に記述せず、migration ファイルに記述しましょう。 [link]

    # 悪い例 - アプリケーションでデフォルト値を設定している。
    def amount
      self[:amount] or 0
    end

    多くのRails開発者が、初期値の設定をRailsのアプリケーション層だけで行っています。しかし、そのやり方はデータの不整合やアプリケーションのバグを引き起こす可能性が高いです。また、重要なアプリケーションは、データベースを他のアプリケーションと共有している場合が多く、単体のRailsアプリケーションでデータ保全性を担保するのは不可能です。

  • 外部キー制約を設定しましょう。Railは4.2から外部キー制約をサポートしています。 [link]

  • スキーマを変更する(テーブルの追加、フィールドの追加など)migrationを書くときは、updownでなくchangeを利用しましょう。 [link]

    # 古い書き方(古いバージョンのRailsではこのような書き方しか出来ませんでした。)
    class AddNameToPeople < ActiveRecord::Migration
      def up
        add_column :people, :name, :string
      end
    
      def down
        remove_column :people, :name
      end
    end
    
    # こちらの方が好ましい
    class AddNameToPeople < ActiveRecord::Migration
      def change
        add_column :people, :name, :string
      end
    end
  • migration でモデルを利用してはいけません。モデルの内容は更新されていくものであり、migration でモデルを引用していた場合、migrationの実行時に不具合を起こす可能性が高いです。 [link]

Views

  • viewから直接、モデル層を呼び出さないようにしましょう。 [link]

  • Viewでの表示のための複雑なフォーマット処理をviewのファイルに記述してはいけません。ヘルパーメソッドに書き出しましょう。 [link]

  • 同じコードを複数箇所に書くのは非効率です。複数のviewで同じコードを書く場合は、部分テンプレートやレイアウトにまとめましょう。 [link]

Internationalization

  • 国際化(国や土地によって文字列を翻訳する)したい文字列は、すべてconfig/locales配下のlocaleファイル(辞書ファイル)で定義しましょう。 [link]

  • 国際化する場合、ActiveRecordのmodelのラベルには必ず対訳が必要です。各辞書ファイルでactiverecord スコープを使って対訳を定義しましょう。 [link]

    en:
      activerecord:
        models:
          user: Member
        attributes:
          user:
            name: 'Full name'
    

    この場合、User.model_name.human は "Member" を返し、User.human_attribute_name("name") は "Full name" を返します。これらの対訳はviewでのラベル表示で使用されます。

  • ActiveRecord の model の対訳と view で使用するテキストは別々の辞書ファイルに定義しましょう。model の対訳はmodelディレクトリを作成しその配下に辞書ファイルを作成しましょう。また view での用いる対訳はviewsディレクトリを作成し、その配下に辞書ファイルを作成しましょう. [link]

    • 辞書ファイルを格納したディレクトリが分散する場合、 application.rb で辞書ファイルを格納しているディレクトリを指定する必要があります。

      # config/application.rb
      config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
  • データフォーマットや通貨表記など、どのlocaleでも共通して利用したい文字列は、locales 直下にファイルを作成しそこに定義しましょう。 [link]

  • 挙動が同じなら、利用するメソッドは名称が短い方が望ましいです。I18n.translateではなくI18n.tを使いましょう。また、I18n.localizeでなく、I18n.lを使いましょう。 [link]

  • View では、"lazy lookup" を利用しましょう。 [link]

    en:
      users:
        show:
          title: 'User details page'
    

    辞書ファイルでこのように訳語が定義されている場合、app/views/users/show.html.hamlでは下記の呼び出し方でusers.show.titleを呼び出すことができます。このような呼び出し方を "lazy lookup" と呼びます。

    = t '.title'
  • 訳語の呼び出しに用いるキーは、ドットを使った記法を利用しましょう。その方が:scopeオプションを利用するより読みやすく、また辞書ファイルでの訳語の定義の階層がわかりやすいです。 [link]

    # 悪い例
    I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages]
    
    # 良い例
    I18n.t 'activerecord.errors.messages.record_invalid'
  • より詳細な内容は Rails Guides に譲ります。 [link]

Assets

assets pipeline を使いましょう。

  • 独自のstylesheetファイル・javascriptファイル・画像ファイルは、app/assets配下に配置しましょう。 [link]

  • 開発中のアプリケーションに必ずしもフィットしていない独自ライブラリは、lib/assets配下に配置しましょう。 [link]

  • jQuerybootstrapのようなサードパーティーのコードは、vendor/assets配下に配置しましょう。 [link]

  • 可能であれば、gem 化されたアセットを利用しましょう。 (例: jquery-rails, jquery-ui-rails, bootstrap-sass, zurb-foundation). [link]

Mailers

  • mailer の名には SomethingMailerといったようにMailerを語尾につけ、その Mailer とどの view を結びついているか分かるようにしましょう [link]

  • html と plain-text 両方での view templateを用意するようにしましょう。. [link]

  • delelopment 環境では、メールの送信に失敗したらエラーが発生するように設定しておきましょう。デフォルトでは、develepment環境でのメール送信失敗はエラーとならないように設定されています。 [link]

    # config/environments/development.rb
    
    config.action_mailer.raise_delivery_errors = true
  • development 環境ではローカルのSMTPサーバーは、Mailcatcher のように利用しましょう。 [link]

    # config/environments/development.rb
    
    config.action_mailer.smtp_settings = {
      address: 'localhost',
      port: 1025,
      # more settings
    }
  • host名を設定しましょう。 [link]

    # config/environments/development.rb
    config.action_mailer.default_url_options = { host: "#{local_ip}:3000" }
    
    # config/environments/production.rb
    config.action_mailer.default_url_options = { host: 'your_site.com' }
    
    # in your mailer class
    default_url_options[:host] = 'your_site.com'
  • view で email へのリンクを記載する際には、_pathでなく_urlを利用しましょう。_url が生成するURLはホスト名を含みますが、_pathメソッドのそれは含まない為です。 [link]

    # 悪い例
    詳細は下記のリンクをご参照ください。
    = link_to 'こちら', course_path(@course)
    
    # 良い例
    詳細は下記のリンクをご参照ください。
    = link_to 'こちら', course_url(@course)
  • fromtoは下記のような記法で記述するようにしましょう。 [link]

    # in your mailer class
    default from: 'Your Name <info@your_site.com>'
  • email 送信のテストでは、email 送信メソッドのプロトコルを:testに設定しましょう。 [link]

    # config/environments/test.rb
    
    config.action_mailer.delivery_method = :test
  • 開発時と本番運用時には、email 送信メソッドのプロトコルは:smtpに設定しましょう。 [link]

    # config/environments/development.rb, config/environments/production.rb
    
    config.action_mailer.delivery_method = :smtp
  • 外部の css ファイルを読み込めないメールクライアントがある為、html メールを送信する場合は、すべての style を template に直接記述するようにしましょう。styleをtemplateに直接記述した場合、template のコードの保守が非常に難しいものになりますが、 premailer-railsroadie といった gem を使用することで、style や htmlタグを適切に編集することができます。 [link]

  • ページ描画と email の送信を同時に行うのはやめましょう。email が複数送信されると、ページのロードが遅延してリクエストがタイムアウトになる可能性があります。sidekiq のような gem を利用し、email をバックグラウンドのプロセスで送信することでこの問題を回避できます。 [link]

Time

  • application.rb でtimezoneを適切に設定しましょう。 [link]

    config.time_zone = 'Eastern European Time'
    # optional - :utc か :local しか指定できません(デフォルトは:utcです)
    config.active_record.default_timezone = :local
  • Time.parseは使わないようにしましょう。 [link]

    # bad
    Time.parse('2015-03-02 19:05:37') # => システムのtimezoneを反映した時刻が返されます。
    
    # good
    Time.zone.parse('2015-03-02 19:05:37') # => Mon, 02 Mar 2015 19:05:37 EET +02:00
  • Time.nowは使わないようにしましょう。 [link]

    # bad
    Time.now # => システム日付を返します。その際、timezoneの設定は無視されます。
    
    # good
    Time.zone.now # => Fri, 12 Mar 2014 22:04:47 EET +02:00
    Time.current # 上記と同じ処理で、より短い記法です。

Bundler

  • 開発およびテストでしか利用しない gem は、Gemfileにて利用する環境(developmenttest)を指定しましょう。 [link]

  • 有名で利用者の多い gem を利用しましょう。もし、無名の gem を利用しなければならない場合は、利用前にソースコードをよく確認しましょう。 [link]

  • gem にはOS固有のものがあります。もし、そのようなgemを利用しており、かつプロジェクトに参加している開発者が複数のOSを利用している場合、頻繁に Gemfile.lock が書き変わってしまいます。そのような状況を避けるため、Gemfileでは OS X 特有のgem を darwin とグルーピングしましょう。同様に Linux 特有の gem はlinux とグルーピングしましょう。 [link]

    # Gemfile
    group :darwin do
      gem 'rb-fsevent'
      gem 'growl'
    end
    
    group :linux do
      gem 'rb-inotify'
    end

    適切な環境に適切なgemをrequireさせるために、下記のコードをconfig/application.rbに追記しましょう。

    platform = RUBY_PLATFORM.match(/(linux|darwin)/)[0].to_sym
    Bundler.require(platform)
  • Gemfile.lockはかならずバージョン管理しましょう。これはあなた方のプロジェクトの開発者全員がbundle installを実行する際に、同じバージョンの gem をインストールできるよう保証するためのものです。 [link]

Flawed Gems

問題をはらんでいる、もしくは陳腐化した gem の一覧です。これらの gem は利用しないことをお勧めします。

  • rmagick

    • この gem は莫大なメモリ量を消費してしまいます。代わりに minimagick を使いましょう。
  • autotest

    • guardwatchrの方が新しく優れているため、これらを利用しましょう。
  • rcov

    • コードカバレッジツールです。Ruby 1.9 以降に対応していないため、代わりにSimpleCovを使いましょう。
  • therubyracer

    • 莫大にメモリ量を消費するため、本番環境での利用は適当ではありません。 node.js を用いた方法をお勧めします。

この一覧は随時更新していきます。もし有名で問題のある gem をご存知であれば、ご一報頂けると幸いです。

Managing processes

  • プロジェクトが外部の複数のプロセスに依存している場合、foreman を利用しましょう。 [link]

参考文献

この文書の他にもRailsのコーディングスタイルについて、優れた文献があります。時間があるときに目を通されてみることをお勧めします:

貢献

このガイドに書いてあることはすべて編集可能です。 Railsのコードスタイルに興味のある全ての人と共に取り組むことが私の望みです。 究極的には、全てのRubyコミュニティにとって有益なガイドを作ることができればと思っています。 遠慮せずチケットを立てたりプルリクエストを送ったりしてください。 また、このプロジェクト(とRubocop)への金銭的な貢献は、gittip経由で行うことができます。

Support via Gittip

貢献するには

簡単です! contribution guidelines をご覧ください!

ライセンス

Creative Commons Licenseこの著作物は、 Creative Commons Attribution 3.0 Unported Licenseに従います。

このガイドを広めてください

このガイドは有志のコミュニティによって作成されるものです。そもそも存在が世に知られないと、このガイド自体が意味のないものになってしまいます。このページをご覧になった方には、ぜひこのガイドについてTwitterでつぶやいたり、友達や同僚にシェアして、このガイドの存在を広めていただけるようお願いします。 全てのコメント・提案・意見がこのガイドをより良いものにしていきます。

親愛をこめて
Bozhidar

rails-style-guide's People

Contributors

bbatsov avatar satour avatar et avatar velobuff avatar markevich avatar pointlessone avatar abotalov avatar drewda avatar semanticart avatar luqipan avatar toao avatar kalkov avatar darkside73 avatar willnet avatar adamt avatar akshaymohite avatar arbox avatar ognevsky avatar andyw8 avatar astyagun avatar arturt avatar chakaitos avatar dideler avatar zudochkin avatar dzhlobo avatar edzhelyov avatar gabrielfagundez avatar thebaggage avatar julio avatar kathgironpe avatar

Watchers

James Cloos avatar Tsukasa Arima avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.