6

Mam powodzeniem w stanie realizować dodawanie nowych wpisów artysty, który nie został uwzględniony w Ryan Bates railscast # 258 http://railscasts.com/episodes/258-token-fieldsszyn: Korzystanie tokeninput jquery (railscast # 258), aby utworzyć nowe wpisy

Więc innymi słowy, użytkownik może wprowadzić nazwę wykonawcy, która będzie autouzupełniania za pomocą jqery tokinput. Jednak chciałbym, aby wyniki autouzupełniania wyświetlały tylko nazwy wykonawców, które zostały utworzone przez tego użytkownika.

Czy to ma sens? Lepszym i bardziej zrozumiałym przykładem będzie plik collection.rb, w którym użytkownicy utworzą posty i określą "kolekcję", do której będzie należał post, ale będą mogli dodawać posty tylko do kolekcji, które sami utworzyli.

Jest to forma post z artist_tokens jako atrybut wirtualnym:

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

Znajduje artystę o wartości wprowadzonej w polu artist_tokens na formularzu pocztowym, a ja również dodać opcję „Dodaj {params [: q]} ", aby dodać nowe wpisy.

Dodałem dodatkowy kod, aby przeanalizować "nowe" wpisy według id, a następnie utworzę z nimi nowego artystę. Następnie artist_ids są przypisane ponownie.

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

Wszystko działa świetnie, z wyjątkiem możliwości zawężenia wyników json tylko o wpisy użytkownika current_user. Jak miałbym to zrobić? Czy muszę przechowywać identyfikator użytkownika twórcy wpisów w tabeli? Jak mogę to zrobić?

EDIT: stowarzyszenia dla modeli

# 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: Próba alias_method_chain ustawić pierwszy USER_ID atrybut wpisu. (Nie działa naprawić wpisy NULL dB) referneced od: 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

Co to jest 'collection.rb', o którym wspomniałeś wcześniej, ale opuściłeś go całkowicie później. W jaki sposób powiązane są "Post" i "Artist"? Co dokładnie chcesz robić? – rubish

+0

Post i artysta mają połączoną tabelę o nazwie rzemieślnicze (za pomocą artist_ids i post_ids). Jeśli znasz przypadek tokenu jquery, dodałem możliwość dodawania nowych wpisów. Chciałbym, aby automatyczne uzupełnianie zawierało tylko wpisy utworzone przez użytkownika. –

+0

Collection.rb nie istnieje, to tylko przykład, aby lepiej zrozumieć, w jaki sposób chciałbym użyć tokenu jquery, można myśleć o kolekcjach zamiast artystów. Użytkownik tworzy wpis i typy w nazwie kolekcji, jeśli jest to nowa kolekcja, wybierz "dodaj:" nowa nazwa kolekcji ", jeśli jest to stara kolekcja, którą właśnie wybiera. Jeśli użytkownik tworzy kolekcję, może wybrać tylko z własnej kolekcji kolekcje, czy masz więcej sensu? –

Odpowiedz

3

Jeśli nie chcesz zmodyfikować coś w modelach, można zrobić to tak:

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 

zauważyć, że istnieje wiele sprzężeń tu dzieje, więc nie jest zalecane.

Aby debugować dlaczego Artist.create!(:name => $1, :user_id => self.user_id) nie będzie działać, to byłoby wspaniale, jeśli możemy zobaczyć trochę więcej kodu, szczególnie action stworzyć Post

UPDATE: Czy spróbować zmienić PostController#create do następujących, chociaż czuję kod curent powinien działać jak to jest,

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

nie jestem pro szyny i nie rozumieją alias_method_chain więc nie mogę wypowiedzieć się na temat, dlaczego to nie działa.

+0

Myślę, że jesteś na dobrej drodze. Próbowałem debugować problem: user_id => self.user_id i myślałem, że wynika to z kolejności ustawiania atrybutów postu. Próbowałem użyć alias_method_chain na: attributes = metoda, aby ustawić atrybut user_id na pierwszym miejscu, więc gdy self.user_id został wywołany, nie był NULL. To nie działa. Zaktualizuję powyższy kod za pomocą mojego post_controller.rb i kodu, który próbowałem użyć alias_method_chain. –

+0

Ciągle wydaje mi się, że nie działa, czytam gdzie indziej, ponieważ to dlatego, że post jest tylko obiektem rubinowym, dopóki nie zostanie zapisany i stanie się obiektem ActiveRecord, więc dopóki nie zostanie zapisany, nie ma identyfikatora. Myślę, że muszę użyć accepts_nested_attributes_, ale nie wiem jak. Jakieś pomysły? Jeszcze raz dziękuję –

+0

To nie prawda. Jest to obiekt 'ActiveRecord', niezwiązany z żadnym wierszem w bazie danych. Czy umieścisz dodatkowy wiersz 'puts @ post.inspect' po linii' @post = current_user.posts.build' i opublikuje dane wyjściowe z konsoli. – rubish

2

jeśli używasz jakieś rozwiązanie uwierzytelniania takiego opracowania, odprawa lub Authlogic, zapewne masz już metodę current_user. Dlatego dodać user_id kolumny: integer do modelu artysty i wykonaj następujące czynności:

#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 

I oczywiście nie zapomnij ustawić kolumnę USER_ID podczas tworzenia artysty.

+0

Cześć, dziękuję za pomoc.Myślę, że jesteś w połowie drogi do odpowiedzi na moje pytanie! próbowałem bezskutecznie wypełnić kolumnę user_id dla modelu artysty. Czy mógłbyś wyjaśnić, jak dodać ID użytkownika podczas tworzenia artysty? Próbowałem dostosować metodę artist_tokens z Artist.create! (: name => $ 1,: user_id = > self.user_id) .id ale db utrzymujący pozycje NULL –

+0

W jaki sposób przypisujesz user_id do nowego posta w kontrolerze? Jeśli zrobisz coś takiego jak current_user.build_post (params [: post]) w PostsController # create, then user_id powinno być przypisane ned i twoja próba powinna zakończyć się sukcesem. Jeśli nie, zrestartuj serwer. Jeśli to nie pomoże, dodaj kod kontrolera do swojego pytania. –

+0

Dodałem kod kontrolera powyżej, ale potrzebuję pomocy przy dodawaniu user_id do modelu artysty, a nie do modelu postu. Identyfikator użytkownika jest przypisany do modelu posta, ale nie mogę uzyskać identyfikatora użytkownika przypisanego do modelu wykonawcy, ciągle otrzymuję puste wpisy. –

Powiązane problemy