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

查看:15
本文介绍了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 %>

这会通过在 post 表单上的 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 解析新"条目,然后用它们创建一个新艺术家.然后再次分配艺术家 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 数据库条目)引用自:Rails 3:a​​lias_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) 不起作用,如果我们能看到更多代码,那就太好了,特别是创建 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天全站免登陆