Как исправить ошибку в теге ** form_with **, не передающем атрибуты ассоциативной модели в params в Rails - PullRequest
0 голосов
/ 16 января 2019

У меня есть 3 модели Пользователь , UserActivity и Активность . Я создал связь между ними, и когда я отправляю значения через форму, я вижу значения в задней части консоли, но получаю ошибки проверки пустых полей.

Я пробовал несколько способов, включая поиск на разных форумах и пробовал разные предложения, но безрезультатно.

Модели

class User < ApplicationRecord

    belongs_to :role #, foreign_key: "id"

    has_many :user_activities, inverse_of: :user
    has_many :activities, through: :user_activities

    accepts_nested_attributes_for :user_activities
end

class UserActivity < ApplicationRecord

    belongs_to :user, inverse_of: :user_activities
    belongs_to :activity, inverse_of: :user_activities, optional: true

    attr_accessor :user_activity_date, :user_activity_start,  :user_activity_end, :user_activity_note, :activity_id, :user_id

    validates_presence_of :user_activity_end, presence: true, null: false, :message => "cannot be empty"
    validates_presence_of :user_activity_start, presence: true, null: false, :message => "cannot be empty"
    validates_presence_of :user_activity_date, presence: true, null: false, :message => "cannot be empty"
    validates_presence_of :user_activity_note, presence: true, length: { minimum: 10 }, null: false, :message => "cannot be empty"

end

class Activity < ApplicationRecord

  has_many :user_activities, inverse_of: :activity
  has_many :users, through: :user_activities

  accepts_nested_attributes_for :user_activities

end

Методы контроллера

class UserActivitiesController < ApplicationController

   # GET /user_activities/new
   def new
        @user_activity = current_user.user_activities.build(activity_id: params[:activity_id])

        @activity = Activity.all
    end
  end

     # POST /user_activities
     # POST /user_activities.json
     def create
        @user_activity = current_user.user_activities.build
        respond_to do |format|
            if @user_activity.save
               format.html { redirect_to @user_activity, notice: 'User activity was successfully created.' }
               format.json { render :show, status: :created, location: @user_activity }
            else
                @activities = Activity.all
                format.html { render :new }
                format.json { render json: @user_activity.errors, status: :unprocessable_entity }
            end
       end
    end

    def user_activity_params
        params.require(:user_activity).permit( :user_activity => [:activity_id, :user_activity_date, :user_activity_start, :user_activity_end, :user_activity_note])
    end
end

Вид

Я удалил некоторые поля только для уменьшения числовой строки кодов

<%= form_with(model: user_activity, local: true) do |frm| %>

  <div class="field">
    <%= frm.label :activity_id %><br />
    <%= collection_select(:user_activity, :activity_id, Activity.all, :id, :activity_name, prompt: true) %>
    <%#= select("user_activity", "activity_id", Activity.all.collect {|a| [ a.activity_name, a.id ] }, {include_blank: 'none'}) %>
  </div>

  <div class="field">
    <%= frm.label(get_user_activity_date) %><br />
    <%= frm.date_field :user_activity_date, autofocus: true%>
   </div>

<% end %>

Результаты на консоли

Started POST "/user_activities" for 127.0.0.1 at 2019-01-16 04:10:28 +0100
Processing by UserActivitiesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"o81mDoZ87/hodGpWaHkH/CDs87Hr2nH+s518GCp8q3GZC650UrRh0hYTCu41ax3vjUhgRC3JkP03ZHbVIYYQJQ==", "user_activity"=>{"activity_id"=>"", "user_activity_date"=>"", "user_activity_start"=>"", "user_activity_end"=>"", "user_activity_note"=>"a test message I place here""}, "commit"=>"Create User activity"}

Я ожидал, что отправленные данные формы будут переданы в user_activity_params в контроллере, но тогда это не произойдет, поскольку он продолжает возвращать сообщение об ошибке всех полей в форме было пустым.

Сообщение об ошибке в FireFox

4 errors prohibited this user_activity from being saved:
   User activity end cannot be empty
   User activity start cannot be empty
   User activity date cannot be empty
   User activity note cannot be empty

И из-за этого я не могу сохранить данные в таблицу user_activities в базе данных.

Обновление журнала сервера

Started POST "/user_activities" for 127.0.0.1 at 2019-01-16 21:15:48 +0100
Processing by UserActivitiesController#create as HTML
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"7v79xk6TW0IHNjkno+iXwzIYqqBjBMxCSodddPHUmKI/N4C9W6nkFz7qApXaQMEFJL6Qumn6BfsX/gxueMjp2w==", "user_activity"=>{"activity_id"=>"1", "user_activity_date"=>"2019-01-15", "user_activity_start"=>"20:14", "user_activity_end"=>"21:15", "user_activity_note"=>"testing to see if values can be retrieved"}, "commit"=>"Create User activity"}
    Activity ID -> 1
    Date -> 2019-01-15
    Start Time -> 20:14
    End Time -> 21:15
    Activity Note -> testing to see if values can be retrieved

        User Load (0.9ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
        ↳ app/controllers/user_activities_controller.rb:46
    (0.5ms)  BEGIN
        ↳ app/controllers/user_activities_controller.rb:46
        UserActivity Create (3.0ms)  INSERT INTO `user_activities` (`created_at`, `updated_at`, `user_id`) VALUES ('2019-01-16 20:15:49', '2019-01-16 20:15:49', 1)
        ↳ app/controllers/user_activities_controller.rb:46
        (0.5ms)  ROLLBACK
        ↳ app/controllers/user_activities_controller.rb:46
Completed 500 Internal Server Error in 125ms (ActiveRecord: 12.4ms)

ActiveRecord::NotNullViolation (Mysql2::Error: Field 'user_activity_date' doesn't have a default value: INSERT INTO `user_activities` (`created_at`, `updated_at`, `user_id`) VALUES ('2019-01-16 20:15:49', '2019-01-16 20:15:49', 1)):

app/controllers/user_activities_controller.rb:46:in `create'

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Я исправил ошибки, которые я получил, только после того, как опробовал большинство рекомендаций без решений. Я начал с изучения ассоциаций моделей и отключения одного из методов, таких как inverse_of, accepts_nested_attribute_for и attr_accessor, один за другим.

До

class UserActivity < ApplicationRecord

    # ----ASSOCIATION OF MODELS----

    # a UserActivity belongs to a User
    # and UserActivity belongs to an Activity
    belongs_to :user, inverse_of: :user_activities
    belongs_to :activity, optional: true, inverse_of: :user_activities 

    attr_accessor :user_activity_date, :user_activity_start,  :user_activity_end, :user_activity_note, :activity_id, :user_id

    accepts_nested_attributes_for :activity, :user

    # ----MODEL VALIDATIONS----
    validates_presence_of :user_activity_end, presence: true, null: false, :message => "cannot be empty"
    validates_presence_of :user_activity_start, presence: true, null: false, :message => "cannot be empty"
    validates_presence_of :user_activity_date, presence: true, null: false, :message => "cannot be empty"
    validates_presence_of :user_activity_note, presence: true, length: { minimum: 10 }, null: false, :message => "cannot be empty"

    validates :user, presence: true
    validates :activity, presence: true
end

После

class UserActivity < ApplicationRecord

    # ----ASSOCIATION OF MODELS----

    # a UserActivity belongs to a User
    # and UserActivity belongs to an Activity
    belongs_to :user, inverse_of: :user_activities
    belongs_to :activity, optional: true, inverse_of: :user_activities 

    accepts_nested_attributes_for :activity, :user

    # ----MODEL VALIDATIONS----
    validates_presence_of :user_activity_end, presence: true, null: false, :message => "cannot be empty"
    validates_presence_of :user_activity_start, presence: true, null: false, :message => "cannot be empty"
    validates_presence_of :user_activity_date, presence: true, null: false, :message => "cannot be empty"
    validates_presence_of :user_activity_note, presence: true, length: { minimum: 10 }, null: false, :message => "cannot be empty"

    validates :user, presence: true
    validates :activity, presence: true
end

Результаты консоли

Started POST "/user_activities" for 127.0.0.1 at 2019-01-18 02:11:27 +0100
Processing by UserActivitiesController#create as HTML
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"Z6DP3METaYH2oczN11Mpewy4K4E1Gj+24twDM4NHI0y2abKn1CnW1M9993+u+3+9Gh4Rmz/k9g+/pVIpCltSNQ==", "user_activity"=>{"activity_id"=>"2", "user_activity_date"=>"2018-12-18", "user_activity_start"=>"09:56", "user_activity_end"=>"11:00", "user_activity_note"=>"still testing for errors in the app"}, "commit"=>"Create User activity"}
   The activity ID which is received is -> 2
   Date -> 2018-12-18
   Start Time -> 09:56
   End Time -> 11:00
   Activity Note -> still testing for errors in the app
       User Load (0.7ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
       ↳ app/controllers/user_activities_controller.rb:54
       (0.4ms)  BEGIN
       ↳ app/controllers/user_activities_controller.rb:57
       UserActivity Create (0.7ms)  INSERT INTO `user_activities` (`user_activity_date`, `user_activity_start`, `user_activity_end`, `user_activity_note`, `created_at`, `updated_at`, `user_id`, `activity_id`) VALUES ('2018-12-18 00:00:00', '09:56:00', '11:00:00', 'still testing for errors in the app', '2019-01-18 01:11:28', '2019-01-18 01:11:28', 1, 2)
       ↳ app/controllers/user_activities_controller.rb:57
       (0.4ms)  COMMIT
       ↳ app/controllers/user_activities_controller.rb:57
Redirected to http://localhost:3000/user_activities/7
Completed 302 Found in 111ms (ActiveRecord: 4.3ms)

У меня была accepts_nested_attribute_for в модели UserActivity , и используемые переменные были точно такими же, как и у уже установленных атрибутов, поэтому они конфликтовали .

Сразу после того, как я отключил это, я смог сохранить в базу данных, и теперь все работает хорошо.

Я благодарю вас за вашу поддержку, поскольку они дали мне представление о том, куда направить мою технику поиска ошибок.

0 голосов
/ 16 января 2019

Проблема в вашем методе strong_parameters. API не самый интуитивный. Метод #require возвращает только значение требуемого ключа. Поэтому, когда вы переходите к #permit определенным атрибутам, вы не можете сказать ему снова искать ключ :user_activity.

Вы можете попробовать поиграть с консоли рельсов, чтобы посмотреть, что произойдет. Сначала давайте смоделируем набор параметров:

>> params = ActionController::Parameters.new("user_activity"=>{"user_activity_note"=>"a test message I place here"})
#> <ActionController::Parameters {"user_activity"=>{"user_activity_note"=>"a test message I place here"}} permitted: false>

require возвращает объект ActionController :: Parameters только со значением требуемого ключа:

>> params.require(:user_activity)
#> <ActionController::Parameters {"user_activity_note"=>"a test message I place here"} permitted: false>

Если мы повторим клавишу :user_activity в нашем действии permit, мы получим пустой объект params, потому что все, что было в нем, определено как недопустимое. Это не происходит молча; если вы проверите свои журналы, вы увидите, что все ваши атрибуты не были разрешены.

>> params.require(:user_activity).permit(:user_activity => [:user_activity_note])
Unpermitted parameters: :user_activity_note
#> <ActionController::Parameters {} permitted: true>

Но если мы просто перечислим нужные нам атрибуты, мы получим ожидаемый результат:

>> params.require(:user_activity).permit(:user_activity_note)
#> <ActionController::Parameters {"user_activity_note"=>"a test message I place here"} permitted: true>

Измените user_activity_params метод на:

def user_activity_params
  params.require(:user_activity).permit(:activity_id, :user_activity_date, :user_activity_start, :user_activity_end, :user_activity_note)
end

и оно должно работать на вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...