Rails:使用jquery tokeninput(railscast#258)创建新条目 [英] Rails : Using jquery tokeninput (railscast #258) to create new entries

查看:79
本文介绍了Rails:使用jquery tokeninput(railscast#258)创建新条目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经成功实现了Ryan Bates railscast#258 http://railscasts.com/episodes/258-token-fields

I have successfully been able to implement the addition of new artist entries which was not included in Ryan Bates railscast #258 http://railscasts.com/episodes/258-token-fields

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

So in other words, a user can enter an artist name which will autocomplete using jquery tokinput. However, I'd like the autocomplete results to only display the artist names which were created by that individual user.

这有意义吗?一个更好的和更易理解的示例是collection.rb,用户在其中创建帖子并为该帖子所属的类别指定收藏集",但他们只能将帖子添加到自己创建的收藏集中.

Does this make sense? An better and more understandable example would be for a collection.rb, where users create posts and specify a 'collection' for the post to belong to, but they should only be able to add posts to the collections which they created themselves.

这是具有artist_tokens作为虚拟属性的帖子形式:

This is the post form with artist_tokens as a virtual attribute:

<%= 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字段中输入的值来查找艺术家,我还添加了选项添加{params [:q]}"来添加新条目.

This finds the artist by the value entered into the artist_tokens field on the post form, and I also added the option "Add {params[:q]}" to add new entries.

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.

I added the additional code to parse the 'new' entries by id and then create a new artist with them. Then the artist_ids are assigned again.

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?我该怎么办?

Everything works great except the ability to narrow the json results by only the current_user's entries. How would I go about doing this? Do I need to store the user_id of the entries creator in the table? How can I do this?

模型关联

# 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

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 db条目) 引用自:规则3:alias_method_chain仍在使用吗?

Attempted alias_method_chain to set post's user_id attribute first. (didn't work to fix the NULL db entries) referneced from: 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

推荐答案

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

If you don't want to modify anything in your models, then you can do it like this:

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

请注意,这里有很多联接,因此不推荐.

Notice that there are a lot of joins going on here, so not recommended.

要调试为什么Artist.create!(:name => $1, :user_id => self.user_id)不起作用,最好能看到更多代码,尤其是action来创建Post

To debug why Artist.create!(:name => $1, :user_id => self.user_id) would not work, it would be great if we can see some more code, particularly the action to create a Post

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

UPDATE: Did you try changing PostController#create to following, although I feel curent code should work as it is,

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

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

I am not a rails pro and don't understand the alias_method_chain so can't comment on why it didn't work.

这篇关于Rails:使用jquery tokeninput(railscast#258)创建新条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆