Skip to main content
 首页 » 编程设计

sql之rails : Using jquery tokeninput (railscast #258) to create new entries

2024年02月06日25sxdcgaq8080

我已经成功地添加了 Ryan Bates Railscast #258 http://railscasts.com/episodes/258-token-fields 中未包含的新艺术家条目。

换句话说,用户可以输入艺术家姓名,该姓名将使用 jquery tokinput 自动完成。但是,我希望自动完成结果仅显示由该单个用户创建的艺术家姓名。

这有道理吗?一个更好、更容易理解的例子是 collection.rb,用户在其中创建帖子并指定帖子所属的“集合”,但他们应该只能将帖子添加到他们自己创建的集合中。

这是以artist_tokens作为虚拟属性的帖子表单:

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

这会通过在帖子表单上的artist_tokens字段中输入的值来查找艺术家,并且我还添加了选项“Add {params[:q]}”来添加新条目。

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 

我添加了额外的代码来通过 id 解析"new"条目,然后用它们创建一个新的艺术家。然后再次分配artist_ids。

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

除了能够仅通过 current_user 的条目缩小 json 结果范围之外,一切都运行良好。我该怎么做呢?我需要在表中存储条目创建者的 user_id 吗?我怎样才能做到这一点?

编辑:模型关联

# 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 

编辑: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 

编辑:首先尝试使用alias_method_chain设置帖子的user_id属性。 (无法修复 NULL 数据库条目) 引用自: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 

请您参考如下方法:

如果您不想修改模型中的任何内容,那么您可以这样做:

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 

请注意,此处正在进行大量联接,因此不推荐。

要调试为什么 Artist.create!(:name => $1, :user_id => self.user_id) 不起作用,如果我们能看到更多代码,尤其是用于创建帖子操作

更新:您是否尝试将 PostController#create 更改为以下内容,尽管我认为当前代码应该按原样工作,

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

我不是 Rails 专业人士,也不了解 alias_method_chain 因此无法评论它为什么不起作用。