Rails:使用jquery tokeninput (railscast #258)创建新条目



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

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

这有意义吗?一个更好、更容易理解的例子是集合。Rb,用户创建帖子并指定帖子所属的"集合",但他们应该只能将帖子添加到他们自己创建的集合中。

这是一个post表单,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 %>

这是通过在post表单的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解析"新"条目,然后用它们创建一个新的艺术家。然后再次分配artist_id。

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

一切都很好,除了能够缩小json结果只有current_user的条目。我该怎么做呢?我需要在表中存储条目创建者的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先设置post的user_id属性。(没有修复NULL数据库条目)参考:Rails 3: alias_method_chain仍然使用?
 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)不能工作,如果我们能看到更多的代码,特别是action创建一个Post,那就太好了

更新:您是否尝试将PostController#create更改为以下内容,尽管我觉得当前的代码应该正常工作,

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

我不是rails专业人士,不理解alias_method_chain,所以不能评论为什么它不起作用。

如果您正在使用一些身份验证解决方案,如设计,清除或authlogic,您可能已经有current_user方法。因此,在Artist模型中添加列user_id:integer,并执行以下操作:

#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

当然,当你创建一个艺术家时,不要忘记设置user_id列

相关内容

  • 没有找到相关文章

最新更新