Если вы знакомы с Railscasts, я следовал за полем токена # 258, чтобы изначально настроить его, где Райан руководит книгами авторов has_many через авторские права, я использую сообщения художников has_many через ремесленные мастерства. (и сообщения принадлежат пользователям) http://asciicasts.com/episodes/258-token-fields
Итак, другими словами:
У меня есть сообщения, создаваемые пользователем с полями title и artist, форма post содержит виртуальный атрибут для поля Artist под названием artist_tokens, с этим виртуальным атрибутом связан метод setter Artist_tokens = (ids).
Это метод, который вызывает у меня проблемы с пониманием. Метод делает 2 вещи. Он берет идентификаторы, введенные в форму сообщения и вызывает Artist.create! используя идентификаторы как: имя. Затем он вызывает .id на любом оставленном объекте Artist. Это итоговый идентификатор artist_id, который используется для создания ассоциации ремесленников.
1) Что происходит, когда я вызываю Artist.create (: name => $ 1) внутри модели поста?
2) Затем этот запрос переходит к методу create внутри контроллера Artist?
Я понимаю, что обычный запрос post отправляется в метод postscontroller # create и затем записывается в базу данных, а затем перенаправляется на любой путь в методе создания, например post_path, поэтому он попадает в postscontroller # show и затем вид. Правильно?
3) Какова последовательность запросов от контроллера к модели, чтобы посмотреть, что я делаю, когда я вызываю Artist.create! из метода artist_tokens = (ID) внутри модели поста?
# app/models/user.rb
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
has_many :artists, :through => :posts
attr_accessible :email, :password, :password_confirmation,
:remember_me, :name, :avatar, :username, :bio
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
mount_uploader :avatar, AvatarUploader
end
# app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
has_many :artisanships
has_many :artists, :through => :artisanships
attr_accessible :title, artist_tokens
attr_reader :artist_tokens
def artist_tokens=(ids)
ids.gsub!(/CREATE_(.+?)_END/) do
Artist.create!(:name => $1).id
end
self.artist_ids = ids.split(",")
end
end
# all/models/artist.rb
class Artist < ActiveRecord::Base
has_many :artisanships
has_many :users, :through => :posts
has_many :posts, :through => :artisanships
attr_accessible :name
end
# app/models/artisanship.rb
class Artisanships < ActiveRecord::Base
belongs_to :post
belongs_to :artist
has_one :user, :through => :post
attr_accessible :post_id, :artist_id
end
# app/views/shared/_post_form.html.erb
<%= form_for @post, :validate => true, :html => {:multipart => true} do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div class="field">
<%= f.label :title, 'Title:' %><br />
<%= f.text_field :title %><br />
<%= f.label :artist_tokens, "Artists" %><br />
<%= f.text_field :artist_tokens, "data-pre" =>
@post.artists.map(&:attributes).to_json %> # html 5 data attribute for prepopulate
</div>
<div class="actions">
<%= f.submit "Submit" %>
</div>
<% end %>
# app/controllers/pages_controller.rb
class PagesController < ApplicationController
def home
@title = "Home"
@featured_posts = Post.featured.limit(10)
if user_signed_in?
@user = current_user
@post = current_user.posts.build
@feed_items = current_user.feed.paginate(:per_page => "10", :page => params[:page])
else
#render :layout => 'special_layout'
end
end
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_filter :authenticate_user!, :only => [:create, :edit, :update, :destroy]
before_filter :authorized_user, :only => [:destroy, :edit, :update]
def create
@user = current_user
@post = current_user.posts.build(params[:post])
if @post.save
flash[:success] = "Post created!"
redirect_to root_path
else
@feed_items = current_user.feed.paginate(:per_page => "10", :page => params[:page])
render 'pages/home'
end
end
def index
@posts = Post.paginate(:page => params[:page])
end
def show
@post = Post.find(params[:id])
end
def edit
@post = Post.find(params[:id])
end
def update
@post = Post.find(params[:id])
respond_to do |format|
if @post.update_attributes(params[:post])
format.html { redirect_to(post_path(@post), :notice => 'Post was successfully updated.') }
else
format.html { render :action => "edit" }
end
end
end
def destroy
@post.destroy
redirect_to root_path
end
def likers
@title = "Likers"
@post = Post.find(params[:id])
@likers = @post.likers.paginate(:page => params[:page])
render 'show_likers'
end
def search
if params[:q]
query = params[:q]
@search = Post.search do
keywords query
end
@posts = @search.results
end
end
private
def authorized_user
@post = Post.find(params[:id])
redirect_to root_path unless current_user?(@post.user)
end
end
# app/controller/artists_controller.rb
class ArtistsController < ApplicationController
def index
@artists = Artist.where("name like ?", "%#{params[:q]}%")
results = @artists.map(&:attributes)
results << {:name => "Add: #{params[:q]}", :id => "CREATE_#{params[:q]}_END"}
respond_to do |format|
format.html
format.json { render :json => results }
end
end
def show
@artist = Artist.find(params[:id])
end
def new
@artist = Artist.new
end
def create
@artist = Artist.build(params[:artist])
if @artist.save
redirect_to @artist, :notice => "Successfully created artist."
else
render :action => 'new'
end
end
def edit
@artist = Artist.find(params[:id])
end
def update
@artist = Artist.find(params[:id])
if @artist.update_attributes(params[:artist])
redirect_to @artist, :notice => "Successfully updated artist."
else
render :action => 'edit'
end
end
def destroy
@artist = Artist.find(params[:id])
@artist.destroy
redirect_to authors_url, :notice => "Successfully destroyed artist."
end
end