2016-03-18 58 views
0

我希望用戶能夠選擇他們說的語言。我已經建立了關聯,表格屬性和表格的一部分。當我選擇一種語言,提交表單我去鐵軌控制檯,做一個u.languages,但我得到一個空數組回:=> []將Has_many關聯映射到不同的模型

這裏有日誌,當我提交表單:

Started POST "/update_user_via_user" for 127.0.0.1 at 2016-03-18 13:26:03 +0200 
    ActiveRecord::SchemaMigration Load (0.4ms) SELECT "schema_migrations".* FROM "schema_migrations" 
Processing by UsersController#update_user_via_user as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"CB1Qca0VrBcap9qO6VpKfoi2dG8GNG+tGGNDgCnFEv4E=", "user"=>{ "fullname"=>"John Doe", "languages"=>["", "1", "2"]}, "commit"=>"Save"} 
    User Load (28.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = 3 ORDER BY "users"."id" ASC LIMIT 1 
Unpermitted parameters: languages 
    (0.1ms) begin transaction 
    (0.1ms) commit transaction 
Redirected to http://127.0.0.1:3000/setup_profile 
Completed 302 Found in 163ms (ActiveRecord: 29.5ms) 

現在如果仔細觀察這些人,你會看到「未經許可的參數:語言」。

在我users_controller我有以下內容:

def user_params 
    params.require(:user).permit(:languages, :fullname) 
    end 

和自定義操作:

def update_user_via_user 
    if current_user.update(user_params) 
     flash.notice = "Your profile was sent for moderation. We will moderate it asap!" 
    else 
     flash.alert = "Something went wrong! Please try again." 
    end 
    redirect_to root_path 
    end 

其他一些參考:(我在最後的問題)

schema.rb:

語言表:

create_table "languages", force: true do |t| 
    t.string "name" 
    t.datetime "created_at" 
    t.datetime "updated_at" 
    t.integer "user_id" 
    end 

用戶表:

t.string "languages" 

language.rb模型:

class Language < ActiveRecord::Base 
    belongs_to :user 
end 

和user.rb模型:

class User < ActiveRecord::Base 
    has_many :languages 
end 

的視圖:

<%= f.label :languages %> 
    <%= f.select :languages, Language.all.map{ |l| [l.name, "#{l.id}"] }, {}, { :multiple => true } %> 

我不知道爲什麼「語言」是不允許的,也如果我的代碼的概念是正確的

+2

試試這個:'params.require(:user).permit(:fullname,languages:[])' – Deep

+1

我不確定你正在使用的概念。 'language'屬於'user',你允許用戶選擇語言意味着你需要創建新的語言記錄,而不是讓他們選擇你的情況。否則你需要一個模型來存儲它,比如'user_languages'。它應該在'has_many through'的'HABTM'上,並且爲了避免重複使用你應該保留模型的語言。 – Deep

+0

@Deep嘗試了第一個。它給了我一個語法錯誤 –

回答

2
class Language < ActiveRecord::Base 
    belongs_to :user 
end 

這將設置用戶和語言之間的一個兩個many關係這是不是你想要的。你想要的是一個多對多的關係:

  • 用戶可以說多種語言
  • 語言有許多發言者(用戶)

所以要跟蹤這一點,我們需要第三個表:

database diagram

language_users就是所謂的連接表。你可以根據自己的意願命名錶格 - 稱之爲a + _ + bs只是一個慣例。

我們還需要設置我們的模型以使用連接表

class User < ActiveRecord::Base 
    has_many :language_users 
    has_many :languages, through: :language_users 
end 

class Language < ActiveRecord::Base 
    has_many :language_users 
    has_many :users, through: :language_users 
end 

# this is a join model that links User & Language 
class LanguageUser < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :language 
end 

要創建一個表單元素,用戶可以選擇的語言,你可以使用:

<%= f.collection_select(:languages_ids, Language.all, :id, :name, multiple: true) %> 

或者:

<%= f.collection_check_boxes(:languages_ids, Language.all, :id, :name) %> 

languages_ids是一個特殊的訪問器的ActiveRecord創建has_many協會,讓您可以通過傳遞一個ID數組來設置多個關聯。

+0

還有一種方法可以用'has_and_belongs_to_many'做到這一點,但是這不能在連接表上添加任何額外的數據 - 所以它在你的情況下不是很有用。 – max

+0

在附註上 - 您不應該通過POST請求更新記錄。您應該使用PATCH請求。 – max

0

我在想Deep的答案是正確的,基於this exchange

我啓動了我的控制檯,這樣做:

irb(main):001:0> x = ActionController::Parameters.new(user: {fullname: "John Doe", languages: ['','1','2']}) 
    => {"user"=>{"fullname"=>"John Doe", "languages"=>["", "1", "2"]}} 

    irb(main):002:0> y = x.require(:user).permit(:fullname, :languages => []) 
    => {"fullname"=>"John Doe", "languages"=>["", "1", "2"]} 

    irb(main):003:0> y[:languages] 
    => ["", "1", "2"] 

所以,HM。

你現在得到的錯誤信息是什麼?與原創相同?

相關問題