LINUX.ORG.RU

Еще один нубский вопрос по асоциациям в рельсах

 association, ,


1

1

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

итак есть следующие модели

Person

class Person < ActiveRecord::Base                                               
  has_one :person_role                                                          
 # TODO: this does not help us                                                  
 #validates_associated :person_role                                             
  belongs_to :property                                                          
                                                                                
  attr_accessible :name, :notes, :phone, :person_role_id                        
                                                                                
  validates :name, :phone, :presence => true                                    
  validates :phone, :length => { :minimum => 5 },                               
                    :uniqueness => {:scope => :name},                           
                    :numericality => {:only_integer => true}                    
end                                                                             

PersonRole

class PersonRole < ActiveRecord::Base                                           
  attr_accessible :name                                                         
  validates :name, :uniqueness => { :case_sensitive => false }                  
  belongs_to :person                                                            
end

вроде как они связаны с помощью has_one и belongs_to.

irb(main):031:0> Person.find(1).methods.include?(:person_role)
  Person Load (0.4ms)  SELECT `people`.* FROM `people` WHERE `people`.`id` = 1 LIMIT 1
=> true
irb(main):032:0> 

но обращение к методу person_role кидает трейс.

значит не все так хорошо, и я гдето на косячил.

к чему все это. ах да, не хочется в вьюхе плодить говнокод типа этого

<% @people.each do |person| %>                                                  
    <tr>                                                                        
        <td><%= person.name %></td>                                             
        <td><%= person.phone %></td>                                            
        <td><%= t('roles.' +                                                    
                  PersonRole.find(person.person_role_id).name                   
                 ) %></td>                                                      

как сие правильно писать? Хочется правильного, красивого и краткого решения.

да, я видел и joins и includes. но то ли я не въехал как их правильно использовать, то ли.. в обьщем поделитесь примером, или ткните носом в строчку мануала где сие разжовывается

★★★★★
Ответ на: комментарий от Mr_Gentoo
class CreatePeople < ActiveRecord::Migration
  def change
    create_table :people do |t|
      t.string :name
      t.string :phone
      t.text :notes
      t.references :person_role

      t.timestamps
    end
    add_index :people, :person_role_id
  end
end
20130125151957_create_people.rb (END)

если я понял правильно

ZuBB ★★★★★
() автор топика
Последнее исправление: ZuBB (всего исправлений: 1)
Ответ на: комментарий от Mr_Gentoo

ну там все просто. потому и не давал

vv@vv-Latitude-E5520 ~/work/own/ruby/reard/db/migrate $ cat 20130124011806_create_person_roles.rb
class CreatePersonRoles < ActiveRecord::Migration
  def change
    create_table :person_roles do |t|
      t.string :name

      t.timestamps
    end
  end
end
vv@vv-Latitude-E5520 ~/work/own/ruby/reard/db/migrate $ 
ZuBB ★★★★★
() автор топика
Ответ на: комментарий от Mr_Gentoo

да нет же. или я что-то основательно путаю

mysql> select * from person_roles;
+----+------------+---------------------+---------------------+
| id | name       | created_at          | updated_at          |
+----+------------+---------------------+---------------------+
|  1 | employee   | 2013-01-24 01:20:02 | 2013-01-24 01:20:02 |
|  2 | customer   | 2013-01-24 01:20:11 | 2013-01-24 01:20:11 |
|  3 | competitor | 2013-01-30 14:43:23 | 2013-01-30 14:43:23 |
+----+------------+---------------------+---------------------+
3 rows in set (0.00 sec)

mysql> select * from people limit 2;
+----+----------------+---------+---------------------------+----------------+---------------------+---------------------+
| id | name           | phone   | notes                     | person_role_id | created_at          | updated_at          |
+----+----------------+---------+---------------------------+----------------+---------------------+---------------------+
|  1 | марічка        | 552266  | (.)(.)                    |              1 | 2013-01-25 20:06:35 | 2013-01-26 21:21:33 |
|  6 | гаврило        | 1119999 | а що в нас тут?           |              2 | 2013-01-26 19:37:40 | 2013-01-31 07:40:56 |
+----+----------------+---------+---------------------------+----------------+---------------------+---------------------+
2 rows in set (0.00 sec)
ZuBB ★★★★★
() автор топика

PersonRole.find(person.person_role_id).name

O-O чувак, ты уже тут несколько месяцев вопросы задаешь, ну осиль ты ассоциации http://guides.rubyonrails.org/association_basics.html

В той модели, в которой используется belongs_to, должен быть внешний ключ в таблице.

special-k ★★★★
()
Последнее исправление: special-k (всего исправлений: 1)
Ответ на: комментарий от Mr_Gentoo

прочитал, понял про «has_one»/«belongs_to».

теперь оно дейстивельно работает.

irb(main):007:0> Person.find(1).person_role.name
  Person Load (0.4ms)  SELECT `people`.* FROM `people` WHERE `people`.`id` = 1 LIMIT 1
  PersonRole Load (0.3ms)  SELECT `person_roles`.* FROM `person_roles` WHERE `person_roles`.`id` = 1 LIMIT 1
=> "employee"

но оно делает два запроса. а раз уж переписывать, то с толком. хотелось бы в 1 запрос. как то так

irb(main):025:0> Person.joins(:person_role).select('people.*, person_roles.name')
  Person Load (0.4ms)  SELECT people.*, person_roles.name FROM `people` INNER JOIN `person_roles` ON `person_roles`.`id` = `people`.`person_role_id`
=> [#<Person id: 1, name: "employee", phone: "552266", notes: "(.)(.)", person_role_id: 1, created_at: "2013-01-25 20:06:35", updated_at: "2013-01-26 21:21:33">, ....

но изза одинаковых имен полей оно перекрывается. я могу конечно написать raw sql но в чем тогда весь сыр-бор?

нужно переименовать поле или что-то еще?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от special-k

я вопросы здесь задаю с того времени, когда я зарегистрирован :)

по рельсах первых вопрос был 24.01

я тебе благодарен за совет в вопросе о руби (который был немного ранее)

если не хочешь отвечать — не отвечай

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от Mr_Gentoo

вот если kelyar ничего нового не посоветует, тогда точно на этом варианте и остановимся пока

@kelyar: вопрос здесь

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

в выхлопе присутствуют только данные с таблицы «person»

role_name как метод не сработает, потому что такого поля нет в таблице, возможно сработает [:role_name]

kelyar ★★★★★
()
Ответ на: комментарий от kelyar

я вроде как понял что вы хотите сказать. но точно не понял как это написать. не подскажете?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от kelyar

в выхлопе присутствуют только данные с таблицы «person»

role_name как метод не сработает, потому что такого поля нет в таблице, возможно сработает [:role_name]

я вроде как понял что вы хотите сказать. но точно не понял как это написать. не подскажете?

я ничего не понял.

role_name как метод не сработает

почему он метод? здесь

Person.joins(:person_role).select('people.*, person_roles.name AS role_name')

role_name используется как новое имя столбца

UPD: нашел следующий полусолюшен

irb(main):067:0* Person.select('people.*, person_roles.name AS role_name').joins(:person_role).includes(:person_role).limit(1)
  SQL (0.4ms)  SELECT `people`.`id` AS t0_r0, `people`.`name` AS t0_r1, `people`.`phone` AS t0_r2, `people`.`notes` AS t0_r3, `people`.`person_role_id` AS t0_r4, `people`.`created_at` AS t0_r5, `people`.`updated_at` AS t0_r6, `person_roles`.`id` AS t1_r0, `person_roles`.`name` AS t1_r1, `person_roles`.`created_at` AS t1_r2, `person_roles`.`updated_at` AS t1_r3 FROM `people` INNER JOIN `person_roles` ON `person_roles`.`id` = `people`.`person_role_id` LIMIT 1
=> [#<Person id: 1, name: "марічка", phone: "552266", notes: "(.)(.)", person_role_id: 1, created_at: "2013-01-25 20:06:35", updated_at: "2013-01-26 21:21:33">]
ZuBB ★★★★★
() автор топика
Последнее исправление: ZuBB (всего исправлений: 2)
Ответ на: комментарий от ZuBB

почему он метод?

как ты показываешь этот role_name? где-то делаешь

@person = Person.joins ...
, а потом во вьюшке пытаешь сделать ему @person.role_name ? это и есть метод, но его не будет. И в инспектe он тебе role_name не покажет.

А ты попробуй сделать @person[:role_name].

kelyar ★★★★★
()
Последнее исправление: kelyar (всего исправлений: 1)
Ответ на: комментарий от kelyar

bingo!

еще раз спасибо. при первой личной встрече с меня причитается

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от kelyar

не хочу плодить еще одну тему, поэтому спрошу здесь

а есть ли возможность делать left join без использования raw sql?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от kelyar

LEFT JOIN table1 ON ...

хотелось как раз без этого ибо у меня их 4 штуки. но.. оставил пока так

спс

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от kelyar

и еще вопрос. у меня приближается время «продакшена» :)

какие основные ньюансы? есть ли"грабли", на которые наступают нубы (как я) в этом деле? какое минимальное железо для маленького web-application`а(будет юзаться в standalone/local network mode)? еще чтонибуть важное?

ZuBB ★★★★★
() автор топика
Последнее исправление: ZuBB (всего исправлений: 1)
Ответ на: комментарий от ZuBB

:) вроде ничего особенного.

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

kelyar ★★★★★
()
Ответ на: комментарий от kelyar

продакшн отменяется. в клиента факап другого рода (а я уже зае"№;лся все время исправлять, просто ждать и ждать свои деньги; извините, не удержался)

еще есть пара вопросов:

как правильно делается кастомизация под клиента? втч бекенд и клиент (и база, дааа). как/куда сохранять, как подключать, что делать послде деплоя? как быть с данными, которые должны быть в базе, но в тоже время они специфичны для каждого клиента?

как правильно приготовить миграцию(или сие делается не миграцией, тогда дайте совет) для данных, которые должны быть в базе изначально и они не специфичны для каждого клиента?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

для данных, которые должны быть в базе изначально и они не специфичны для каждого клиента?

vim db/seeds.rb
rake db:seed RAILS_ENV=production
kelyar ★★★★★
()
Ответ на: комментарий от ZuBB

как правильно делается кастомизация под клиента?

ты хочешь одно приложение ставить разным клиентам? еще и кастомайзить их?

kelyar ★★★★★
()
Ответ на: комментарий от kelyar

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

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от kelyar

мне этот вариант не нравится. если будет больше чем пара веток я рано или поздно запутаюсь что куда уже мержилось а что еще нет; или эту фичу клиенту нужно, а эту нет, а вот эту нельзя. да, гит я знаю на достаточном уровне, но тем не менее мне єта идея не нравится.

я думал что было бы не плохо если бы можна сделать так (набросок)

customer1
customer2
customer3
customer -> customer2 

и

require "customer/*"

но как быть с подключением кастомного JS и кастомных данных в базе. например в customer1 в таблице products должно изначально быть «хлеб» и «ватрушка», а в customer1 в таблице products должно изначально быть «огурцы» и «капуста». хотелось бы чтобы не увидели «другое» во избежание лишних вопросов

да, я в курсе что «ділити шкуру невбитого ведмедя», но опять же

потом нужно будет меньше переделывать

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

мне кажется проще написать одну крошечную команду, которая после добавления новой фичи пройдется и сребейзит ветки твоих клиентов, чем заливать на сервер каждого из ниx софт с кодом для _всех_ клиентов (что вообще как-то не очень) и гемороится с линками.

kelyar ★★★★★
()
Ответ на: комментарий от kelyar

которая после добавления новой фичи пройдется и сребейзит ветки твоих клиентов

тоесть вы предлагаете после ребейза в ветке клиента делать «push -f»? я понимаю что я один разраб, но все равно мне это не очень нравится.

тем более что

эту фичу клиенту нужно, а эту нет, а вот эту нельзя

а вот

чем заливать на сервер каждого из ниx софт с кодом для _всех_ клиентов (что вообще как-то не очень) и гемороится с линками

можна сделать так: линк содается только один раз, при изначальном деплое. после окончания деплоя все папки с кастомерским кодом, на которые не указывает софт линк удаляются. перед началом деплоя делается git checkout $(app_root) дабы сделать чистую копию перед апдейтом. как вам идея?

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

// можете меня поздравить. сегодня состоялся запуск в псевдо-«продакшен» режиме + я получил львиную долю оплаты. так что жизнь продолжается :)

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

сегодня состоялся запуск в псевдо-«продакшен» режиме + я получил львиную долю оплаты

поздравляю)

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

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

kelyar ★★★★★
()
Ответ на: комментарий от kelyar

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

ох, етить. уже вспомнил как ставил на линукс..

а что ты думаешь о том способе кастомизации что я предложил?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

а ты можешь хостить это все у себя и раздавать клиентам поддомены, например? или должен отдавать сырцы?

kelyar ★★★★★
()
Ответ на: комментарий от kelyar

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

в общем я понял. не все так просто. оставим пока этот вопрос до лучших времен..

еще раз спасибо

ZuBB ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.