2016-06-18 9 views
1

これはこれまでに多くのことで尋ねられてきましたが、かなり適用されるものは見つかりませんでした。私がしようとしているのは、SettingsControllerの編集フォームを編集ビューのUsersControllerにレンダリングすることです。私はRoRの新人ですので、私が間違っていることさえ分かりません。ビューの1つのコントローラのform_forを部分的に保存できません。レール4

This質問に最も近いようだが、私はUsersコントローラで@setting = Setting.newを初期化するとき、私は、移行中に新しいユーザーに対して設定デフォルトなしSettingsフォームを取得します。しかし、@setting = Setting.editまたはSetting.updateを初期化すると、定義されていないメソッドまたは引数の数が正しくないというエラーが発生します。私は、データベースをチェックすると

undefined method for find_by_id in the SettingsController: app/controllers/settings_controller.rb:43:in `correct_user'.

、ユーザーが作成されたとき、レコードが正しく作成されている設定が、設定レコードが更新されません。Setting.newフォームが保存されている

は、それがこのエラーがスローされますフォームが保存されます。

setting.rb:

class Setting < ActiveRecord::Base 
    belongs_to :user 
    validates :user_id, presence: true 
end 

user.rb:

class User < ActiveRecord::Base 
    has_many :posts, dependent: :destroy 
    has_one :setting, dependent: :destroy 
    after_create :create_setting 
end 

がUserController:

class UsersController < ApplicationController 
before_action :logged_in_user, only: [:edit, :update, :index, :destroy] 
before_action :correct_user, only: [:edit, :update] 
before_action :admin_user, only: :destroy 

def new 
    @user = User.new 
end 

def edit 
    @user = User.find(params[:id]) 
    @setting = Setting.update 
end 

def update 
    @user = User.find(params[:id]) 
    @setting = Setting.update 
    if @user.update_attributes(user_params) 
    flash[:success] = "Profile updated!" 
    redirect_to @user 
    else 
    render 'edit' 
    end 
end 

def settings 
    @title = "Settings" 
    @setting = Setting.find_by_user_id(params[:user_id]) 
end 

private 

def user_params 
    params.require(:user).permit(:name, :email, :password, 
           :password_confirmation) 
end 

# Confirms the correct user. 
def correct_user 
    @user = User.find(params[:id]) 
    redirect_to(root_url) unless current_user?(@user) 
end 
end 

SettingsController:

class SettingsController < ApplicationController 
before_action :logged_in_user, only: [:create, :edit, :update, :show, :index] 
before_action :correct_user, only: [:create, :edit, :update, :show, :index] 

def index 
    @settings = Setting 
end 

def show 
    @setting = User.find(params[:id]).setting 
end 

def new 
    @setting = Setting.new 
end 

def edit 
    @setting = Setting.find(params[:id]) 
end 

def create 
    @setting = current_user.settings.build(setting_params) 
    @setting.save 
end 

def update 
    @setting = Setting.find(params[:id]) 
    if @setting.update_attributes(post_params) 
    flash[:success] = "Settings updated!" 
    redirect_to request.referrer 
    else 
    render 'edit' 
    end 
end 

private 

def setting_params 
    params.require(:setting).permit(:reading_theme) 
end 

def correct_user 
    @setting = current_user.setting.find_by_id(params[:id]) ##the line which throws an error when the form is saved 
    redirect_to root_url if @setting.nil? 
end 
end 

部分形式:

<%= form_for(@setting) do |f| %> 
    <%= render 'shared/error_messages', object: f.object %> 
    <div class="field"> 
     <%= radio_button_tag(:reading_theme, "flatly") %> 
     <%= label_tag(:reading_theme_flatly, "Light (Default)") %> 
    </div> 
    <div class="field"> 
     <%= radio_button_tag(:reading_theme, "darkly") %> 
     <%= label_tag(:reading_theme_darkly, "Dark") %> 
    </div> 
    <%= f.submit yield(:button_text), class: "btn btn-primary" %> 
<% end %> 

routes.rbを:

resources :users do 
    member do 
    get :following, :followers 
    end 
end 
resources :settings, only: [:new, :create, :edit, :update] 
... 

ETA:設定の移行:私のフォームができるように、私は適切なデフォルト値を取得するにはどうすればよい

class CreateSettings < ActiveRecord::Migration 
    def change 
    create_table :settings do |t| 
     t.string :reading_theme, default: => "flatly" 
     t.references :user, index: true, foreign_key: true 

     t.timestamps null: false 
    end 
    end 
end 

正しく保存されましたか?

+0

をcurrent_user.setting =

ちょうど@settingあなたの移行を含めてください特に既定値が挙げられます。これにより、プロジェクトの状況に応じた適切な回答が得られます。 –

+0

@MichaelGaskill、ちょうどそれを追加しました –

+0

私は 'new'アクションで私の答えに追加しました。 –

答えて

1

マイグレーション中のフィールドに含めるデフォルトは、Rubyのモデルクラス(設定)に対して「不明」です。 Ruby(またはむしろRails ActiveRecord)は、モデルオブジェクトの作成時にテーブル定義からデフォルト値を読み込みません。これはあなたがここで見ているような二重の性格の問題につながる可能性があります。

あなたがしなければならないことは、必要に応じて関連するデフォルトをRubyコードに追加することです。たとえば、[設定]コントローラで、あなたはこれらの変更を行うことができます。これはあなたではありませんユーザーとデフォルトに表示されるデフォルト値を区別することができます

def new 
    @setting = Setting.new 
    # Set any defaults that will be visible to the user on the form 
    @setting.reading_theme = "flatly" 
    # The form will allow the user to choose their own values, based on the defaults 
end 

def create 
    @setting = current_user.settings.build(setting_params) 
    # Set any defaults that will NOT be visible to the user 
    @setting.save 
end 

を。

モデルオブジェクトの作成時にデフォルトを設定するオプションもありますが、状況によってはこれがより複雑になる可能性があり、実際の使用ではあまり一般的ではないようです。このための答えはHow to initialize an ActiveRecord with values in Rails?です。これは、あなたのニーズに適しています。

+0

ありがとう!したがって、この回答と@DennisCastro'sの間で、フォームはレンダリングされ、保存時にエラーをスローすることはなくなりましたが、データベースに保存されません。私はdef newとdef createをどこに変更する必要があるのか​​を正しく理解していないと思います。私はUsersControllerで仮定しましたか?なぜなら、私がSettingsControllerでそれらを変更した場合、引き続きnil引数エラーが発生するためです。ただし、それらをUsersControllerに追加すると空のフォームが作成され、何も保存されません。私は何かシンプルなものを見逃しているように感じる。 –

+0

@JimHogan私は自分の答えを更新して、設定コントローラに変更を加えるべきだと言った。 DennisCastroの答えは、 'new'アクションや' create'アクションのいずれにも適用されないように注意してください。これは、 'edit'アクションや' show'アクションのために特に使用されるアプローチです。あなたの "nil argument error"によって証明されているように、完全な解決策を得るために解決する必要のあるあなたのコードには別の問題があるかもしれませんし、あなたの質問を関連するエラーの詳細(アクションログ全体、スタックトレースを含む)を把握することができます。 –

0

@setting = current_user.setting.find_by_id([:ID]のparams)has_oneの関係でfind_by_id使用できるわけではありません

関連する問題