Vagrant+ChefでMySQL+Ryby2環境構築
1. 前提
・ VirtualBoxのインストール
https://www.virtualbox.org/wiki/Downloads
・Vagrantのインストール
http://www.vagrantup.com/downloads.html
・Vagrantのインストール確認
$ vagrant -v Vagrant 1.4.3
・RubyバージョンとGem確認
$ ruby -v ruby 2.0.0p247 (2013-06-27 revision 41674) [universal.x86_64-darwin13] $ gem list | grep chef chef (11.8.2) $ gem list | grep knife knife-solo (0.4.1) $ gem list | grep berks berkshelf (2.0.13)
2. セットアップ
$ knife solo init sandbox-chef-cookbooks
$ cd sandbox-chef-cookbooks
$ berks init
3. site-cookbooksの作成
・iptablesの設定をするcookbookeを作成する
$ knife cookbook create site_simple_iptables -o site-cookbooks/
・設定
$ vim site-cookbooks/site_simple_iptables/recipes/default.rb -- default.rb # Reject packets other than those explicitly allowed simple_iptables_policy "INPUT" do policy "DROP" end # The following rules define a "system" chain; chains # are used as a convenient way of grouping rules together, # for logical organization. # Allow all traffic on the loopback device simple_iptables_rule "system" do rule "--in-interface lo" jump "ACCEPT" end # Allow any established connections to continue, even # if they would be in violation of other rules. simple_iptables_rule "system" do rule "-m conntrack --ctstate ESTABLISHED,RELATED" jump "ACCEPT" end # Allow SSH simple_iptables_rule "system" do rule "--proto tcp --dport 22" jump "ACCEPT" end # Allow HTTP, HTTPS simple_iptables_rule "http" do rule [ "--proto tcp --dport 80", "--proto tcp --dport 443" ] jump "ACCEPT" end # Allow MySQL simple_iptables_rule "mysql" do rule "--proto tcp --dport 3306" jump "ACCEPT" end # Allow Rails simple_iptables_rule "mysql" do rule "--proto tcp --dport 3000" jump "ACCEPT" end
4. Berksfile
・サードパーティのcookbook(iptable + Ruby + MySQL)を使う設定を追加する
$ vim Berksfile site :opscode cookbook 'simple_iptables', git:"git://github.com/dcrosta/cookbook-simple-iptables.git" cookbook 'site_simple_iptables', path: './site-cookbooks/site_simple_iptables' cookbook 'ruby_build' cookbook 'rbenv', github: "fnichol/chef-rbenv" cookbook 'mysql'
・iptable設定のcookboosとサードパーティのcookbookをインストール
$ berks install --path cookbooks
5. Vagrantfile
chef.json = { :mysql => { :server_root_password => 'rootpass', :server_debian_password => 'debpass', :server_repl_password => 'replpass' }, :rbenv => { :user_installs => [{ :user => "vagrant", :rubies => ["2.0.0-p353"], :global => "2.0.0-p353", :gems => { "2.0.0-p353" => [ {:name => "bundler"} ] } }] } }
・vagrantの起動
$ vagrant up
OmniAuth + DeviceでTwitter, Facebook連携
1. 前提
・deviceでユーザー登録機能が実装されている
Rails 4.0.0.beta1でdevise - t-taira blog
・Twitter Developersに登録している
Twitter Developers
・Facebook Developersに登録している
Home - Facebook Developers
2. 設定関連
・GemFile
# twitter gem 'twitter' gem 'omniauth-twitter' # facebook gem 'fb_graph' gem 'omniauth-facebook' gem 'activerecord-session_store'
・config/routes
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do delete '/users/disconnect/:provider', :to => 'users#disconnect_omniauth_provider', :as => 'disconnect_omniauth_provider' end resources :users
・config/initializers/devise.rb
# ココ追加 config.omniauth :twitter, 'CONSUMER_KEY', 'CONSUMER_SECRET', :display => 'popup' config.omniauth :facebook, 'APP_ID', 'APP_SECRET', :scope => 'manage_pages', :display => 'popup' DeviseController.class_eval do before_action :resource_params #, only: [:show, :edit, :update, :destroy] def resource_params unless params[resource_name].blank? params.require(resource_name).permit( # ココ追加 :twitter_id, :twitter_token, :twitter_secret, :facebook_id, :facebook_token, :facebook_secret, ・・・ ) end end end
3. Model
・app/models/user
class User < ActiveRecord::Base devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :omniauthable, :omniauth_providers => [:facebook, :twitter] # ココ追加 # 連携済みかどうか def connected?(provider) return eval("self.#{provider}_id.nil?") end # 以下、コールバックで呼ばれるメソッド追加 def self.find_for_facebook_oauth(access_token, signed_in_resource = nil) data = access_token.extra.raw_info User.where(:facebook_id => data.id).first end def self.find_for_twitter_oauth(access_token, signed_in_resource = nil) data = access_token User.where(:twitter_id => data.uid).first end def connect_with provider, authdata logger.info("AUTH: #{authdata.inspect}") case provider when :twitter self.twitter_id = authdata['uid'] self.twitter_token = authdata['credentials']['token'] self.twitter_secret = authdata['credentials']['secret'] when :facebook self.facebook_id = authdata['uid'] self.facebook_token = authdata['credentials']['token'] end save end end
4. Controller
・app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def facebook authorize :facebook do session["devise.facebook_data"] = request.env["omniauth.auth"] end end def twitter authorize :twitter do # http://stackoverflow.com/questions/7117200/devise-for-twitter-cookie-overflow-error session["devise.twitter_data"] = request.env["omniauth.auth"].except('extra') end end private def authorize provider @user = User.send "find_for_#{provider}_oauth", request.env["omniauth.auth"], current_user provider_name = provider.to_s.titleize # if current_user exists: # if @user is nil, connecting the account # if @user is not nil and not equal to current_user, show an error # else, see below: if current_user if @user.nil? current_user.connect_with provider, request.env['omniauth.auth'] flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => provider_name elsif @user != current_user # TODO: I18n flash[:error] = "That #{provider_name} account is already linked to a different user." else flash[:notice] = "Your account is already linked with the #{provider_name} account." end redirect_to edit_user_registration_path else if @user flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => provider.to_s.titleize sign_in_and_redirect @user, :event => :authentication else yield if block_given? redirect_to new_user_registration_url end end end end
・app/controllers/users_controller.rb
class UsersController < ApplicationController # 連携を解除するメソッド def disconnect_omniauth_provider provider = params[:provider] if Devise.omniauth_providers.include? provider.to_sym current_user.update_attributes( { "#{provider}_id" => nil, "#{provider}_token" => nil, "#{provider}_secret" => nil, } ) current_user.save flash[:success] = "Your account has been disconnected from #{provider.titleize}." end redirect_to edit_user_registration_path end ・・・ end
5. View
・app/views/layouts/application.html.erb
<div class="well sidebar-nav"> <p class="nav-header">SNS連携</p> <ul class="nav nav-tabs nav-stacked"> <% Devise.omniauth_providers.each do |provider| %> <% if current_user.connected?(provider) %> <li> <%= link_to image_tag("authbuttons/#{provider.to_s}_32.png") + " 認証する", user_omniauth_authorize_path(provider) %> </li> <% else %> <li> <%= link_to image_tag("authbuttons/#{provider.to_s}_32.png") + " 解除する", disconnect_omniauth_provider_path(provider), :method => :delete %> </li> <% end %> <% end %> </ul> </div>
6. 連携
Twitter.configure do |config| config.consumer_key = CONSUMER_KEY config.consumer_secret = CONSUMER_SECRET # oauth_token, oauth_token_secretは連携時に取得した値を利用 config.oauth_token = current_user.twitter_token config.oauth_token_secret = current_user.twitter_secret end twitter_client = Twitter::Client.new # ココはRailsアプリで登録したコンテンツにする twitter_client.update("hogehoge")
# facebook_tokenは連携時に取得した値を利用 me = FbGraph::User.me(current_user.facebook_token) # me.accounts[0]で最新のファンページを取得しているが... # 本当はファンページが複数ある場合は、指定したい page_access_token = me.accounts[0].access_token me = FbGraph::User.me(page_access_token) me.feed!( # # ココはRailsアプリで登録したコンテンツにする :message => 'hellow world!', :link => 'https://www.google.co.jp/')
Source: OmniAuth: Overview · plataformatec/devise Wiki · GitHub
Railsで「もっと見る」の実装
2. Model
・ app/models/item.rb
class Item < ActiveRecord::Base paginates_per 50 default_scope :order => 'created_at DESC' end
3. View
・ app/views/items/_items.html.erb
<% @items.each do |item| %> <div><%= item.name %></div> <% end %>
・ app/views/items/index.html.erb
<div id="items"> <%= render 'items' %> </div> <%= link_to_next_page @items, 'more', remote: true, id: 'more_link' %>
・ app/views/items/index.js.erb
$('#items').append("<%= escape_javascript(render 'items', object: @items) %>") $("#more_link").replaceWith("<%= escape_javascript( link_to_next_page(@items, 'more', remote: true, id: 'more_link') ) %>");
4. Controller
・ app/controller/items_controller.rb
class ItemsController < ApplicationController def index @items = Item.page params[:page] end end
Source: Rails 3 - "More" ajax pagination with Kaminari - Stack Overflow
2013 PHPのはまりどころ・オブ・ザ・イヤー
Rails 4.0.0.beta1でcapistrano
とりあえず、gemが対応されるまでこれで凌ごうかと。
1. Gemfile
gem 'capistrano', group: :development
2. cap deployでエラー... orz
cp: cannot stat `/var/www/sandbox/shared/assets/manifest.yml': No such file or directory
3. 原因
Rails 4 support · Issue #362 · capistrano/capistrano · GitHub
Rails 4 store manifest in JSON file like manifest-effbd5715fcc7c1600baa48c1bc283ee.json, not in manifest.yml. So right now we can’t deploy Rails 4 application.
4. config/deploy.rb に以下を追加
namespace :deploy do namespace :assets do task :precompile, :roles => assets_role, :except => { :no_release => true } do run <<-CMD.compact cd -- #{latest_release.shellescape} && #{rake} RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} assets:precompile CMD end end end
Source: Rails 4 support · Issue #362 · capistrano/capistrano · GitHub
Rails 4.0.0.beta1でdevise
とりあえず、gemが対応されるまでこれで凌ごうかと。
1. Gemfile
gem 'devise', github: 'plataformatec/devise', branch: 'rails4'
2. エラー... orz
`attr_accessible': `attr_accessible` is extracted out of Rails into a gem. Please use new recommended protection model for params(strong_parameters) or add `protected_attributes` to your Gemfile to use old one. (RuntimeError) from /home/leapfrog/projects/kathloc/app/models/user.rb:8:in `<class:User>'
3. config/initializers/devise.rb に以下を追加
DeviseController.class_eval do before_action :resource_params #, only: [:show, :edit, :update, :destroy] def resource_params unless params[resource_name].blank? params.require(resource_name).permit(:email, :password, :password_confirmation, :remember_me, :reset_password_token, :current_password) end end end
Nginx Error - 413 Request Entity Too Large
- この辺はデフォルトで有効になっていたので、そのまま
sendfile on;
keepalive_timeout 65;
- 以下追加
# vim /etc/nginx/conf.d/virtual.conf client_max_body_size 20M;