6

Tôi đã thành công có thể thực hiện việc bổ sung các mục nghệ sĩ mới mà đã không được bao gồm trong Ryan Bates railscast # 258 http://railscasts.com/episodes/258-token-fieldsRails: Sử dụng jquery tokeninput (railscast # 258) để tạo mục mới

Vì vậy, nói cách khác, người dùng có thể nhập tên nghệ sĩ sẽ tự động hoàn thành bằng cách sử dụng jquery tokinput. Tuy nhiên, tôi muốn các kết quả tự động hoàn thành chỉ hiển thị tên nghệ sĩ được tạo bởi người dùng cá nhân đó.

Điều này có hợp lý không? Một ví dụ tốt hơn và dễ hiểu hơn sẽ là cho một collection.rb, nơi người dùng tạo các bài viết và chỉ định một 'bộ sưu tập' cho bài đăng thuộc về, nhưng họ chỉ có thể thêm bài đăng vào bộ sưu tập mà họ tạo ra.

Đây là dạng bài với artist_tokens như một thuộc tính ảo:

<%= 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 %> 

    </div> 
    <div class="actions"> 
    <%= f.submit "Submit" %> 
    </div> 
<% end %> 

này thấy các nghệ sĩ bởi giá trị nhập vào trường artist_tokens về hình thức bưu điện, và tôi cũng nói thêm tùy chọn "Add {params [: q]} "để thêm mục mới.

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 

Tôi đã thêm mã bổ sung để phân tích cú pháp 'mới' theo id và sau đó tạo một nghệ sĩ mới với chúng. Sau đó, các nghệ sĩ được gán lại.

post.rb 
def artist_tokens=(ids) 
    ids.gsub!(/CREATE_(.+?)_END/) do 
     Artist.create!(:name => $1).id 
    end 
    self.artist_ids = ids.split(",") 
    end 

Mọi thứ đều hoạt động tuyệt vời ngoại trừ khả năng thu hẹp kết quả json chỉ bởi mục nhập của current_user. Tôi sẽ đi đâu để tới đó? Tôi có cần lưu user_id của người tạo mục trong bảng không? Tôi có thể làm cái này như thế nào?

EDIT: hiệp hội cho các mô hình

# app/models/user.rb 

class User < ActiveRecord::Base 
    has_many :posts 
    has_many :artists, :through => :posts 

end 



# app/models/post.rb 

class Post < ActiveRecord::Base 

    belongs_to :user 
    has_many :artisanships 
    has_many :artists, :through => :artisanships 

end 

# all/models/artist.rb 

class Artist < ActiveRecord::Base 

    has_many :artisanships 
    has_many :users, :through => :artisanships 
    has_many :posts, :through => :artisanships 

end 


# app/models/artisanship.rb 

class Artisanships < ActiveRecord::Base 

    belongs_to :post 
    belongs_to :artist 
    has_one :user, :through => :post 

end 

EDIT: 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 

Edit: Đã cố gắng alias_method_chain để thiết lập thuộc tính user_id bài đầu tiên. (Không làm việc để sửa chữa các mục NULL db) referneced từ: Rails 3: alias_method_chain still used?

def attributes_with_user_id_first=(attributes = {}) 
    # Make sure not to accidentally blank out the important_attribute when none is passed in 
    if attributes.include?(:user_id) 
     self.user_id = attributes.delete(:user_id) 
    end 

    self.attributes_without_user_id_first = attributes 
    end 
    alias_method_chain :attributes=, :user_id_first 
+0

'collection.rb' bạn đã đề cập trước đó nhưng bỏ qua nó sau. 'Post' và' Nghệ sĩ' có liên quan như thế nào? chính xác là bạn muốn làm gì? – rubish

+0

Bài đăng và nghệ sĩ có bảng tham gia được gọi là artisanships (sử dụng artist_ids và post_ids). Nếu bạn đã quen thuộc với jquery tokeninput, tôi đã thêm khả năng thêm các mục mới. Tôi muốn tự động hoàn thành chỉ bao gồm các mục do người dùng tạo. –

+0

Collection.rb không tồn tại nó chỉ là một ví dụ để hiểu rõ hơn cách tôi muốn sử dụng jquery tokeninput, bạn có thể nghĩ về các bộ sưu tập thay cho các nghệ sĩ. Người dùng tạo một bài đăng và các loại trong tên bộ sưu tập, nếu đó là một bộ sưu tập mới, họ chọn "add:" tên bộ sưu tập mới "nếu đó là một bộ sưu tập cũ mà họ chỉ chọn. Nếu người dùng tạo bộ sưu tập họ chỉ có thể chọn từ bộ sưu tập của họ –

Trả lời

3

Nếu bạn không muốn sửa đổi gì trong mô hình của bạn, sau đó bạn có thể làm điều đó như thế này:

def index 
    @artists = current_user.posts.join("artisianships").join("artists"). 
       where("artisianships.post_id = posts.id"). 
       where("artists.name like ?", "#{params[:q]}"). 
       select("artists.name as name, artists.id as id") 
    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 

Chú ý rằng có rất nhiều tham gia xảy ra ở đây, vì vậy không được khuyến khích.

Để gỡ lỗi tại sao Artist.create!(:name => $1, :user_id => self.user_id) sẽ không hoạt động, nó sẽ là tuyệt vời nếu chúng ta có thể thấy một số mã khác, đặc biệt là action để tạo ra một CẬP NHẬT Post

: Bạn đã thử thay đổi PostController#create đến sau, mặc dù tôi cảm thấy đang curent nên làm việc như nó có,

@post = current_user.posts.build 
if @post.update_attributes(params[:post]) 
    # do something 
else 
    # do something else 
end 

tôi không phải là một đường ray chuyên nghiệp và không hiểu alias_method_chain vì vậy không thể bình luận về lý do tại sao nó không làm việc.

+0

Tôi nghĩ bạn đang đi đúng hướng ở đây. Tôi đã thử gỡ lỗi các vấn đề: user_id => self.user_id và nghĩ rằng đó là do thứ tự mà các thuộc tính bài đã được thiết lập. Tôi đã thử sử dụng alias_method_chain trên phương thức: attributes = để thiết lập thuộc tính user_id trên bài viết đầu tiên vì vậy khi self.user_id được gọi là nó không phải là NULL. Điều này dường như không hoạt động. Tôi sẽ cập nhật mã ở trên với posts_controller.rb của tôi và mã tôi đã thử sử dụng alias_method_chain. –

+0

Tôi vẫn không thể làm cho nó hoạt động được, tôi đọc ở đâu đó vì bài viết chỉ là một đối tượng ruby ​​cho đến khi nó được lưu và trở thành đối tượng ActiveRecord, cho đến khi nó được lưu, nó không có id. Tôi nghĩ rằng tôi cần phải sử dụng accept_nested_attributes_for nhưng nhầm lẫn như thế nào. Ý tưởng nào? Cảm ơn một lần nữa –

+0

Điều đó không đúng. Nó là một đối tượng 'ActiveRecord', không gắn liền với bất kỳ hàng nào trong cơ sở dữ liệu. Bạn có thể đặt thêm một dòng 'puts @ post.inspect' sau dòng' @post = current_user.posts.build' và đăng đầu ra từ bảng điều khiển không. – rubish

2

nếu bạn đang sử dụng một số giải pháp xác thực như devise, giải phóng mặt bằng hoặc authlogic, có thể bạn đã có phương pháp CURRENT_USER. Vì vậy thêm một cột user_id: integer với mô hình Artist và làm như sau:

#User model 
has_many :artists 

#Artist model 
belongs_to :user 

#Artists controller 
def index 
    @artists = current_user.artists.where("name like ?", "%#{params[:q]}%") #this answers your question! 
    ... blah blah 
end 

Và tất nhiên đừng quên để thiết lập các cột user_id khi bạn tạo một nghệ sĩ.

+0

Xin chào, cảm ơn vì sự giúp đỡ. Tôi nghĩ bạn sắp sửa trả lời câu hỏi của tôi! Tôi' đã cố gắng không thành công để điền cột user_id cho mô hình nghệ sĩ. Bạn có thể giải thích cách tôi thêm user_id khi tạo nghệ sĩ không? Tôi đã thử điều chỉnh phương thức artist_tokens bằng Artist.create! (: name => $ 1,: user_id = > self.user_id) .id nhưng db giữ hiển thị các mục NULL –

+0

Làm thế nào để bạn gán user_id cho một bài viết mới trong bộ điều khiển? Nếu bạn làm một cái gì đó như current_user.build_post (params [: post]) trong PostsController # create, thì user_id nên được assig ned và nỗ lực của bạn sẽ thành công. Nếu không, hãy khởi động lại máy chủ của bạn. Nếu nó không hiệu quả, hãy thêm mã điều khiển vào câu hỏi của bạn. –

+0

Tôi đã thêm mã điều khiển ở trên nhưng tôi cần trợ giúp thêm user_id vào mô hình nghệ sĩ chứ không phải mô hình bài đăng. User_id được gán cho mô hình bài đăng nhưng tôi không thể gán user_id để gán cho mô hình nghệ sĩ, tôi tiếp tục nhận các mục nhập rỗng. –