2013-05-14 2 views
2

ТРЕТЬЕ ОБНОВЛЕНИЕ: Хорошо, теперь я очень близок, я думаю. Теперь я создаю данные, и параметры устанавливаются в БД. Я изменил бизнес-контроллер сильные PARAMS быть:Rails 4 RC1 полиморфная ассоциация не в состоянии создать

def business_params 
     params.require(:business).permit(:name, :description, :address_attributes=>[:line1, :line2, :city, :state, :zip]) 

Когда я изменить существующий бизнес я получаю два адреса, созданные для какой-то причине. Один из них пуст, а один - с параметрами. Итак, я думаю, что я очень близок, если у кого есть последний толчок :).

Адрес модели

class Address < ActiveRecord::Base 
belongs_to :addressable, polymorphic: true 
end 

Бизнес-модель:

class Business < ActiveRecord::Base 

    #each business belongs to user, through user_id 
     belongs_to :owner 
     has_one :address, as: :addressable 
     accepts_nested_attributes_for :address 

     # each business has many customers and has many services 
     has_many :customers 
     has_many :services 

    validates :owner_id, presence:true 
    validates_presence_of :name 
    #validates_length_of :state, is: 2 

end 

бизнес-контроллер: вид

class BusinessesController < ApplicationController 
    before_action :get_owner 
    before_action :set_business, only: [:show, :edit, :update, :destroy] 
    #helper_method :sort_column, :sort_direction 


    def index 
    @businesses = @owner.businesses 
    end 

    def show 
    #@customer = @business.customers.order(sort_column + " " + sort_direction) 
    end 

    def new 
    @owner = Owner.find(params[:owner_id]) 
    @business = @owner.businesses.build 
    @address = @business.build_address(params[:address]) 

    end 

    def edit 
    @address = @business.build_address(params[:address]) 
    end 

    def create 
    @business = @owner.businesses.new(business_params) 
    @address = @business.create_address(params[:address]) 

    respond_to do |format| 
     if @business.save 
     format.html { redirect_to owner_businesses_url(@owner), notice: 'Business was successfully created.' } 
     format.json { render action: 'show', status: :created, location: @business } 
     else 
     format.html { render action: 'new' } 
     format.json { render json: @business.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    def update 
    @address = @business.create_address(params[:address]) 
    respond_to do |format| 
     if @business.update(business_params) 
     format.html { redirect_to owner_businesses_url(@owner), notice: 'Business was successfully updated.' } 
     format.json { head :no_content } 
     else 
     format.html { render action: 'edit' } 
     format.json { render json: @business.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    def destroy 
    @business.destroy 
    respond_to do |format| 
     format.html { redirect_to owner_businesses_url(@owner) } 
     format.json { head :no_content } 
    end 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
    def set_business 
     @business = @owner.businesses.find(params[:id]) 
    end 

    # Never trust parameters from the scary internet, only allow the white list through. 
    def business_params 
     params.require(:business).permit(:name, :description, :address_attributes=>[:line1, :line2, :city, :state, :zip]) 
    end 

    def get_owner 
     @owner = Owner.find(params[:owner_id]) 
    end 

    #def sort_column 
    # Customer.column_names.include?(params[:sort]) ? params[:sort] : "first_name"  
    #end 

    #def sort_direction 
    # %w[asc desc].include?(params[:direction]) ? params[:direction] : "asc" 
    #end 
    end 

форма:

 <%= form_for([@owner, @business]) do |f| %> 
     <% if @business.errors.any? %> 
     <div id="error_explanation"> 
      <h2><%= pluralize(@business.errors.count, "error") %> prohibited this business from being saved:</h2> 

     <ul> 
     <% @business.errors.full_messages.each do |msg| %> 
     <li><%= msg %></li> 
     <% end %> 
     </ul> 
    </div> 
    <% end %> 

    <div class="field"> 
    <%= f.label :name %><br /> 
    <%= f.text_field :name %> 
    </div> 
    <div class="field"> 
    <%= f.label :description %><br /> 
    <%= f.text_area :description %> 
    </div> 

    <%= f.fields_for :address do |address| %> 
    <%= p address.object %> 
    <div class="field"> 
    <%= address.label :line1 %><br> 
    <%= address.text_field :line1 %> 
    </div> 
    <div class="field"> 
    <%= address.label :line2 %><br> 
    <%= address.text_field :line2 %> 
    </div> 
    <div class="field"> 
    <%= address.label :city %><br> 
    <%= address.text_field :city %> 
    </div> 
    <div class="field"> 
    <%= address.label :state %><br> 
    <%= address.text_field :state %> 
    </div> 
    <div class="field"> 
    <%= address.label :zip %><br> 
    <%= address.number_field :zip %> 
    </div> 

    <% end %> 

    <div class="actions"> 
    <%= f.submit %> 
    </div> 
<% end %> 

Теперь у меня создаются два адреса. Один пустой, один с установленными параметрами. Почти готово :).

ответ

1

В контроллере вы должны строить отношения между моделями, так что вместо:

@business = @owner.businesses.new(business_params) 

Попробуйте

@business = @owner.businesses.build(business_params) 
+0

Спасибо Dodge.Здесь ошибка, но конкретные строки, которые вы указываете, уже работают. Что не работает, это адресная часть. @ business.build_address (params [: address]) Я думаю, это необходимо. Теперь у меня появилось сообщение параметров unpermitted, которое отличается от предыдущего. Метод @ business.address.create предназначен для отношений has_many. – Art

+0

Итак, я сделал больше изменений и близко. Теперь я получаю unpermitted параметры для всех полей адреса. Я сделал «address_attributes => {} как часть бизнес-ресурсов, используя сильные параметры, как это делает Rails 4.0. С этим я вижу, что хеш передан и введен, но он отклоняется из-за отсутствия возможности использовать эти атрибуты. В контроллере адресов I переместил address_params из частного метода, но я думаю, что он никогда не попадал туда, поэтому я должен куда-то переместить это в помощника. – Art

+0

У вас есть attr_accessible: address_attributes, добавленные в ваши модели, которым нужен доступ к этим атрибутам? – dodgerogers747

4

Что-то подсказывает мне, что я в основном идиотом за то, что такие трудности с получением полиморфный ассоциации для работы в приложении Rails 4.0 RC1, над которым я работаю. Будучи отвратительным, я попросил Stack Overflow помочь с проблемами, которые я видел, и перепросил вопрос о группе Ruby on Rails. Никаких ответов не поступало, поэтому этот вопрос становится первым, что я сам сам понял.

Так что это хорошо, правда?

В любом случае, моя проблема была простой. Я хочу, чтобы адреса улиц/почтовых/платежных адресов были доступны для разных компаний, клиентов, владельцев и т. Д. Я не хочу кодировать три разных таблицы, делая то же самое. Полиморфная ассоциация, похоже, идет из того, что я собираю из таких ассоциаций. Я трясусь за советом по этому поводу и имею некоторые вещи, чтобы моделировать после.

http://kconrails.com/2010/10/19/common-addresses-using-polymorphism-and-nested-attributes-in-rails/> Этот сайт был полезен, хотя и устарел. Я использую Rails 4. Это было написано в конце Rails 2, я считаю. Это действительно помогало мне сжиматься мое время, потому что я никогда не делал HAS_ONE ассоциации до и моя первая проблема была в консоли Rails, я не мог сделать что-то вроде:

b = Owner.first.businesses.first 
b.address.create!(params n' stuff) 

я продолжал получать no_method ошибку для создания , Именно тогда я действительно сосредоточился на статье выше и понял, что он тоже не использует. Он использовал:

b = Owner.first.businesses.first 
b.build_address(params n' stuff) -- he actually wrote @customer.build_address 

Совокупность_соединения - вещь has_one. Я знаю это сейчас очень хорошо. Конечно, я мог бы прочитать документы раньше времени, но я читал их во время этого. Вы можете прочитать об этом эффективно в http://guides.rubyonrails.org/association_basics.html#has_one-association-reference, если вам это интересно.

Я внимательно слежу за этим документом, но это не совсем верно. Элемент «build_address» в новом методе DID моего бизнес-контроллера разрешает отображение полей в моей форме. Но в базу данных ничего не записывалось. Пустая запись вводилась для адреса со всеми значениями nil и вообще не привязывалась к тому бизнесу, в который он был добавлен. И, очевидно, если бы бизнес фактически был «отредактирован», а не создан новым, вы бы не увидели никакой адресной формы, поэтому я решил, что нам понадобится этот метод build_address в поле редактирования, по крайней мере.

Я был прав, но все равно ничего не спас.

Как всегда я иду в Railscasts, чтобы узнать, что у Райана. И, http: // http: //railscasts.com/episodes/154-polymorphic-association-revised>, у него есть некоторые полиморфные вещи, которые будут здорово, когда я добавлю комментарии для разных моделей. Но это не было напрямую выгодно для того, что я хотел сделать здесь. Я много читал о переполнении стека. Проверьте список проблем в репозитории Rails в Github. Прочтите группу Rails Google. Ничего не вышло из того, что я видел.

Во многом потому, что я видел проблему с Rails 4.

Сильные параметры встроены в Rails 4. Таким образом, я добавил следующее к контроллеру адреса с учетом этого:

# Never trust parameters from the scary internet, only allow the white list through. 
def address_params 
    params.require(:address).permit(:line1, :line2, :city, :state, :zip) 
end 

Это то, что леска будет делать для вас, естественно, в Rails 4, если вы использовали для этого нужен рельс. Сильные параметры заменяют attr_accessible в модели из предыдущих версий Rails. Таким образом, модель является лишь ссылкой на полиморфную ассоциацию для адреса и адресной информации, а бизнес добавил адрес has_one: address, as: addressable, а также адрес accepts_nested_attributes_for:. Это все хорошо, но ничего не спасает. Я даже добавил hash address_params к appliction_controller.rb.

Теперь я понимаю, что я глуп. Добавление адреса происходит в бизнес-контроллере и НИКОГДА не увидит этот параметр hash. Даже в application_controller.rb ничего не изменилось. Так не может быть.

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

Я прошу помощи на этом этапе и попытаюсь настроить его.

Я вижу https://github.com/rails/strong_parameters#nested-parameters> этот раздел в github в хранилище сильных параметров. Я не понимаю, почему accepts_nested_attributes_for бы не сделать это для меня, но я иду в бизнес-контроллер и настроить Params хэш там выглядеть следующим образом:

# Never trust parameters from the scary internet, only allow the white list through. 
def business_params 
    params.require(:business).permit(:name, :description, :address_attributes => [:line1, :line2, :city, :state, :zip]) 
end 

Одна из статей я прочитал сказал has_one ассоциация пропускает: address_attributes через, поэтому я положил это там. Теперь все по-другому. Данные по-прежнему не сохраняются, но я не получаю ошибок. И до сих пор нет ответов на сайтах справки.

Я решил изменить мои новые, редактировать, создавать и обновлять методы.

В новых и редактирования у меня было:

@business.build_address 

Я изменил, что в новых и редактирования и добавлены для создания и обновления следующие:

@business.build_address(params[:address]) -- NOTE, :address_attributes also appears to work there. 

Теперь данные спасал. Все поля вошли в БД. Проблема была ДВА. Один из них был пуст, и каждый из них был заполнен при каждом новом обновлении. Таким образом, я удаляю код выше из методов создания и обновления в бизнес-контроллере. Теперь у меня есть один адрес. ПРАВИЛЬНО. Чувствуя себя хорошо, я открываю бизнес для редактирования адреса, и я получаю пустую форму адреса. Ничто не возвращается к виду формы.

Итак, я меняю свой метод редактирования в бизнес-контроллера, чтобы выглядеть следующим образом:

@ business.address || = @ business.build_address (PARAMS [: адрес])

Это в основном говорит, что если есть @ business.address, показать его, иначе @ business.address будет построен.

Теперь я катаюсь. Теперь я вижу сохраненный адрес, когда редактирую форму. Я редактирую адрес. Редактирование сохраняется и отображается снова. Но связанный с этим OLD-адрес остается. Адрес address_id просто изменяется на nil и записывается новая запись адреса. Это не то, что я хочу. По-прежнему нет помощи на сайтах справки. Ничего в журнале вообще.

Я думаю, что здесь используется метод обновления. Поэтому я добавить следующую строку в метод обновления бизнес-контроллера:

@ business.address.update (Params [: адрес])

Нет изменения поведения, но теперь журнал теперь показывает новый Неразрешенный параметр ,

Он показывает «ID» как не указано. Итак, я изменю хэш-код параметров бизнес-контроллера следующим образом:

# Never trust parameters from the scary internet, only allow the white list through. 
def address_params 
    params.require(:address).permit(:id, :line1, :line2, :city, :state, :zip) 
end 

И на этом все работает. Я могу создать бизнес с адресом. На самом деле, даже если я не заполняю ничего для адреса, адрес создается (на данный момент не указан валидаций). Я могу обновить этот адрес, заполнить или удалить, и он обновит существующую запись. Оно работает. Я не уверен, что это лучший или самый чистый способ, но я буду продолжать смотреть.

Существует одна проблема в том, что если я вручную удалю созданный адрес, связанный с бизнесом, и ТОГДА попробуйте отредактировать эту бизнес, метод обновления, который я добавил выше, выдает ошибку, если нет записи для обновления. Возможно, я могу жить без этого. Я ДУМАЮ, что я в порядке с созданием записи для каждого бизнеса (и, в конечном счете, пользователя, владельца, клиента и т. Д.), Даже если он пуст, а затем разрешает удаление только через ассоциацию, а не напрямую.

Но я могу настроить код, чтобы найти способ ТОЛЬКО для создания полного адреса и не писать его пустым.

В любом случае, все виды работ в настоящее время.

Я хотел бы услышать, есть ли что-нибудь, что я могу улучшить или изменить.

На данный момент я перехожу к следующему.

+0

Отличный ответ! У меня возникла другая проблема, связанная с полиморфной ассоциацией has_one: InverseOfAssociationNotFoundError. Я попытаюсь использовать ваше решение, но я почти уверен, что это не повлияет на мою проблему. : S Мой код выглядит так же, как ваш. <. У вас есть идеи? – JustBasti

Смежные вопросы