読者です 読者をやめる 読者になる 読者になる

railsでタスクを作った。-How to build rake task-

Hi:)
最近railsで簡単なタスクを作る任務を課せられたのでメモ用にここに残す。

My boss order me to build task on rails.This is my first time so I blog here as a memo.

タスクの内容は一ヶ月より前のコメントを消すことである。

All I wanna do is to delete comments which are posted more than a month ago.

まず最初にファイルを作成する。

First of all, create a file for it.

rails g task delete_old_comments

lib/task/delete_old_comments.rakeのファイルが生成された。次に進みましょう。

Now you create a file for writing a code for task. Let’s move on.

namespace :apps do
  desc "delete_old_comments"

  task delete_old_comments: :environment do
    BlogComment.delete_all["created_at < ?", 1.month.ago]
  end
end

descenvironmentは必須事項である。

desc and environment are essential for task.

それではターミナルでbin/rake -Tを入力をして自分が作ったタスクが表示されるか確認しよう。

Now, typebin/rake -T in terminal for checking whether your task are included on your application.

このように表示されるはずだ。

You can find like this below.

rake apps:delete_old_following_notifications # delete_old_following_notifications

続けて記述したコードが動いているか、ターミナルで入力して確認しよう。

As a test, type this to see if your codes are executing .

bin/rake apps:delete_old_comments

Good luck!!

rails consoleからレコードを編集&レコードをループで追加

Hi ;) Haven’t seen you for a long while.
Today, I want to share my new knowledge with you as a rehab.

I’m not good at using rails console with terminal screen although my supervisor is telling me to use it.
That is a reason why I cannot go to the next level.
So my first step is to edit a record in db.
I did like this..

$ BlogComment.create(:blog_post_id => 110, :insta_user_id=> 4, :desc=> "test"+count.to_s)

it works!!

So let’s move on how to iterate comments for adding lots of records.
I use until here.

$ count = 100
$ until count == 0
$ BlogComment.create(:blog_post_id => 110, :insta_user_id=> 4, :desc=> "test"+count.to_s)
$ count -= 1
$ end

Now you could add 100 of records on your db!!
Isn’t that great?:)

See you!!

rails内のクラスで実行されているこれって一体何だ!?[和訳]

Hey guys :)
今日も和訳するぜ!
stack overflowでrails初心者に興味深い記事があったので紹介します!
まだ私の知識は浅いのできつい和訳になっているので、できれば和訳を参考に英文を読んでいただければと思います汗

–質問–

I have just started learning ruby on rails and I have encountered code like below:

Ruby on Railsを始めたばかりなんだけど、下記のようなコードに出会った。

class Post < ActiveRecord::Base
 validates_presence_of   :title
 belongs_to :user
end

There are two method calls inside the class body. I have had a hard time finding any ruby documentation that describes how method calls from within a body of a class (but outside of any method) work.

クラス内で2つのメソッドが呼び出しをしている。どうやってメソッドが呼び出しをしているのかRubyのドキュメントを必死に探してもみつからない。

All the books I have, only describe how to define class and instance methods and how to call them from within other methods.

私が持っている本には全てどのようにクラスやインスタンスメソッドを作って、どうやって他のメソッドから呼び出せるのかしか説明されていないんだ。

The questions I have are: How and when are these methods called? How are they defined? Are they mixins defined in some active record module?

私の質問は..いつどのようにこれらのメソッドは呼び出されるのか。どのように定義されているのか。ActiveRecord的なものの中で定義されているのか?

–回答–

The body of a class definition is an execution context for code just like any other.

クラスの定義の主要部分としてはコードを実行することができるということである。

Code there is executed within the context of the class (meaning self is the class object, which is an instance of Class).

クラス内のコードが実行されている。(selfはインスタンスクラスであるクラスオブジェクトという意味)

You can have locals and instance variables (which will belong to the class object itself rather than instances of the class) and you can call any method that class object responds to.

インスタンスクラスよりもクラスオブジェクトに付随している)ローカル、インスタンス変数を持つことが出来、クラスオブジェクトが対応するメソッドを呼び出すことが出来る。

The code is run once the class definition block is finished.

コードはクラスで定義されたブロックを通過すると実行される。

In this case, ActiveRecord::Base defines the class methods validates_presence_of and belongs_to.

今回のケースだと、ActiveRecord::Baseがvalidates_presence_ofとbelongs_toのクラスメソッドを定義しているのだ。

ActiveRecord内で定義したものを実行した結果は以下である(例として)。

[11] pry(main)> ActiveRecord::Base.belongs_to(:blog_post)
=> {"blog_post"=>
  #<ActiveRecord::Reflection::BelongsToReflection:0x007fa3ee03c958
   @active_record=ActiveRecord::Base,
   @association_scope_cache={},
   @automatic_inverse_of=nil,
   @constructable=true,
   @foreign_type="blog_post_type",
   @klass=nil,
   @name=:blog_post,
   @options={},
   @plural_name="blog_posts",
   @scope=nil,
   @scope_lock=#<Mutex:0x007fa3ee03c570>,
   @type=nil>}

追記)contextを上手く訳するのが難しかったので省略しましたw

see you!!:)  

リンク

Ruby Method calls declared in class body - Stack Overflow

railsのform_forをstylingする[和訳]

hey guys :)
form_forをhtml内でstylingできるんだね!
stack overflowからの豆知識を共有してみる。

–質問–

Is there a way to add styling to rails form_for and make it display inline?

railsform_forで stylingしてdisplayをinlineに出来たりするの?

–回答–

There might be a cleaner way to do this, but it works. (I tried with another nested hash, no dice)
単純かもしれないが、こうすれば出来るよ。(他のネストされたハッシュでも試してみたけど、無意味だった)

 <% form_for(@model, :html => { :style => 'background-color:red;' }) do |f| %>

inlineについては触れられてないじゃん!汗
まぁ、記事内のコメントに「なぜinlineにしたいんだい?」って的確なツッコミがあるのは頷けるw

see you !!:)

リンク

html - rails form_for styling - Stack Overflow

ユーザー情報と記事の紐付けしたあと保存ができない!涙「解決への道のり」Ruby on Rails

Hey guys!!
ユーザー情報と記事の紐付け後につまった!!
今思えばなぜあんなことをしてしまっていたのか。。

ログイン機能が搭載されているgem Deviseを取り入れて、ArticleのDBにuser_idを追加したことを前提に話をすすめる。
ちなみにrails5を使用しています。

それぞれのmodelにhas_manybelongs_to で紐付けした。

models/user.rb

class User < ApplicationRecord 

  has_many :articles
  
  validates :name, presence: true
  validates :email, presence: true, uniqueness: true
  devise :database_authenticatable, :registerable,
              :recoverable, :rememberable, :trackable, :validatable,
              :omniauthable
end

models/article.rb

class Article < ApplicationRecord 

  belongs_to :user

  validates :title, presence: true
  validates :content, presence: true, length: { maximum: 140 } 
  validates :user_id, presence: true
end

これは特に問題なさそうだ。

そして今回の問題がcontrollerのcreateアクションの部分だ。

class ArticlesController < ApplicationController
  
  def create
    @article = Article.new
    @article.title = params[:article][:title]
    @article.content = params[:article][:content]
    @article.save
    redirect_to root_path
  end

試しに記事を投稿してみよう…

..!?

更新したようにみえたけど、DBに保存されていない…

saveをした時にデータがちゃんとあるか確認するために @article.saveの直後にraise @article.inspectを記述して記事を更新。
もちろんRuntime Errorがブラウザ上表示されるがその中身をみるとuser_idとidがnilだ。

rails consoleで確認。

$ @article = Article.new
$ @article.title = "title-test"
$ @article.content = "content-test"
$ @article.save

=> false  

なるほど。 idが足りないからなのか? 検証してみよう。

$ @article = Article.new
$ @article.title = "title-test"
$ @article.content = "content-test"
$ @article.id = 1
$ @article.save

=> false  

ふむふむ。user_idで検証してみよう。

$ @article = Article.new
$ @article.title = "title-test"
$ @article.content = "content-test"
$ @article.user_id = 1
$ @article.save

=> true

お!user_idがあればsaveできるんだな!! user_idをcurrent_userヘルパーメソッド(Deviseにデフォで搭載)とイコールにすれば保存ができそう。

class ArticlesController < ApplicationController

 before_action :authenticate_user!    #追加(これを記述しないとcurrent_userが使えない!!)
  
  def create
    @article = Article.new
    @article.user_id = current_user  #追加
    @article.title = params[:article][:title]
    @article.content = params[:article][:content]
    @article.save
    redirect_to root_path
  end

よし、これで上手くいくはずだ。記事を投稿してみよう。

…えーーー、なんで保存されてないんだーーー涙涙

stack overflowで"rails can’t save data"みたいな感じで検索し、でてきた記事がこれ

ruby - Troubleshooting: Rails can't save to database in production? - Stack Overflow

save!っていうメソッドを使ってみたらどうだろうか?とのこと。
何か手がかりが掴めそうだ

よし、やってみっか!

class ArticlesController < ApplicationController

 before_action :authenticate_user!   
  
  def create
    @article = Article.new
    @article.user_id = current_user  
    @article.title = params[:article][:title]
    @article.content = params[:article][:content]
    @article.save!   #変更
    redirect_to root_path
  end

おやおや?

Validation failed: User must exist, User can’t be blank ってブラウザで言われた。

ははーん、答えがみえてきたぞ。
念のために"Validation failed: User must exist, User can’t be blank"をコピペでググったらstack overflowに行き着いた。

ruby on rails - Validation failed: User can't be blank - Stack Overflow

はい、やっぱり上記の記事と答えが一緒でした!

class ArticlesController < ApplicationController

 before_action :authenticate_user!   
  
  def create
    @article = Article.new
    @article.user = current_user   #変更  
    @article.title = params[:article][:title]
    @article.content = params[:article][:content]
    @article.save
    redirect_to root_path
  end

これでやっと記事が保存できた!!

今回の反省点は二つあった。
一つ目はuser_idがnilだったので保存ができなかったという考えに取り憑かれてuser_idに絞って考えてしまっていたこと。
もう少し視野を広げていたら、そもそもuserがないって早く気付いていたかもしれなかったですね。汗汗

そして二つ目はstack overflowの記事でポイントが低いものはあてにならないと思いスルーしていたことである。
上記で取り上げた2つの記事は両方共ポイントが少なかったが解決に導いてくれた。
ポイントが多い記事がないかついつい探してしまいがちだが、初心者の私にとってはポイントが低い記事も知識の宝庫であることに気付かされた。
これからはポイント数をあまり気にせずに、stack overflowを活用していきたいと思います。。

see you!!

redirect_toになんでインスタンス変数??

Hey guys!!:)
今日もstackoverflowの記事を訳すよー。今回は2013年に投稿した古い記事だけど、初心者の勉強の為には良記事だなと思ってピックアップした。

–質問–

I am confused about passing an instance variable to a redirect_to method. How is this possible? I thought redirect_to would be relevant for redirecting to another webpage or a url.

redirect_toメソッドにインスタンス変数を受け渡していることについて混乱している。なんでこんなことが出来るの?私はredirect_toは他のウェブページやURLを表示させることと関係するのだと思ってたよ。

In the examples given on the guide it says the following:
あるガイドが下記のような例でこんなこと説明していたんだ;

2.2.2 Rendering an Action’s View

If you want to render the view that corresponds to a different action within the same template, you can use render with the name of the view:
もし同じテンプレートで違うアクションを実行させたかったら、renderにviewの名前を渡して使えるよ。  
  
def update
  @book = Book.find(params[:id])
  if @book.update_attributes(params[:book])
    redirect_to(@book)
  else
    render "edit"
  end
end

The render “edit” makes complete sense, its going to render that new form again.

render editは確かに理に適っていて、新しいフォームを再度表示させる。

But what in the world is going on with redirect_to(@book)?

でもredirect_to(@book)って一体何なんだ?

What exactly is that going to render and how is a book object going to be redirected to?

具体的にrenderは何をして、bookオブジェクトはどのようにしてリダイレクトしているんだ?

BTW, the book model has columns, Name, author, pages etc…

追記すると、bookモデルはカラム、名前、作者、ページ等がある。

–回答–

redirect_to(options = {}, response_status = {}) Redirects the browser to the target specified in options.   
  
redirect_to(options = {}, response_status = {})ブラウザをオプションで指定した所にリダイレクトする。
  
Record - The URL will be generated by calling url_for with the options, which will reference a named URL for that record.  
  
レコード - URLはオプションでurl_forを呼びだすことによって生成される。そのレコードより名付けられたURLを参照する。

So when one does redirect_to(@book) @book is a specific record with an id .

なのでredirect_to(@book)を実行した時、@bookはidのもつ特定のレコードだ。

Thus, the associated records (in this case @book) show method is used as a template.

したがって、関連のレコード(このケースでは@book)があるshowメソッドはテンプレートに使われる。

In addition to above, if you look at the routes.rb file which defines these paths you will notice

上記に加えてもしroutes.rbファイルをみてみたら、下記のようなパスが定義されていて何か気づくだろう。

resources :books

Now this route is essentially translated as (you can see by running rake routes)

このルートは下記のように読み込まれる(rake routesを実行すればみれるよ)。

    books GET    /books(.:format)                   books#index
          POST   /books(.:format)                   books#create
 new_book GET    /books/new(.:format)               books#new
edit_book GET    /books/:id/edit(.:format)          books#edit
     book GET    /books/:id(.:format)               books#show
          PUT    /books/:id(.:format)               books#update
          DELETE /books/:id(.:format)               books#destroy  

Notice the book GET /books/:id books#show - which gets matched when you do redirect_to(@book)

book GET/books/:id books#showで何か気づくかな?これはredirect_to(@book)と結びついているんだ。

終わり  

どうだったかな?たしかにインスタンス変数を引数にしているのには違和感があった。
この記事を読んで少し霧が晴れたような気がしたかな!

see you!!

リンク

ruby - Confusion about passing instance variables to redirect_to method. As seen in Rails Guides - Stack Overflow

deviseのカラム追加-Ruby on Rails-

Hey, guys:)
最近Deviseっていうgemを使ってログイン機能を開発中のアプリに追加させた。めっちゃ便利でやれることも盛り沢山!

しかし!!

なぜユーザーの名前を登録できるカラムがないのだ!!デフォルトで搭載されているはずじゃ…

もやもやしながらもnameを追加させたのでここで共有してみる。

バージョンはRails 5 向けです。

まずは皆さんお馴染みのmigrationから

$ bin/rails g migration AddNameToUsers name:string

それでもちろんrakeだね

$ rake db:migrate

はい、追加出来たね!

しかし!これだけでは終われない!!

新規ユーザー登録画面でユーザー名を登録できるようにする。

ファイル:app/views/devise/registrations/new.html.erb

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= devise_error_messages! %>

  <div class = "field">
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true %>
  </div>   #この4行だけ追加、それ以外はデフォルトで書かれてるので以下省略

  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true %>
                          :
                          :

この時、デフォのコードを真似してf.name_field :nameみたいな調子乗った記述をしないように!(実体験。自らドブにハマりました..)

次のコードを追加するの忘れずに!!

ファイル;app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?  
  
  protected

  def configure_permitted_parameters
    added_attrs = [:name, :email, :password, :password_confirmation, :remember_me]
    devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
    devise_parameter_sanitizer.permit :account_update, keys: added_attrs
  end
end

以上!!

Railsのバージョンが違うと最後のapplication_controller.rbに書く記述が変わってくるので注意してください。

See ya!!